在遵循Microsoft中的几个示例后,我实现了 DbContext 的弹性版本,该版本从依赖于当前用户的租户(或客户)ID 的 Elastic ShardMapManager 获取其连接字符串。
这在技术上有效,我已将其部署到我的 Azure 帐户。我担心的是连接池管理,因为我已经覆盖了默认的上下文连接创建机制。此外,我不确定每次调用每个请求时shardMap.OpenConnectionForKey
如何管理连接(请参阅下面的ninject设置)。
昨天经过一些轻微的测试后,我的 Web 应用程序失败并显示以下消息:
超时已过期。 从池获取连接之前经过的超时期限。这可能是因为所有池连接都在使用中,并且已达到最大池大小。
这可能是一次性的,因为我今天无法重新创建它,但我想确保连接池得到有效利用,因为我最不希望的是当真实用户开始锤击系统时发生这种情况。
它失败的代码在我的ElasticScaleContext的完整代码中进行了注释:
public class ElasticScaleContext<T> : DbContext
{
/// <summary>
///
/// </summary>
/// <param name="shardMapManager">This is injected - only one of these exists per Application (Singleton)</param>
/// <param name="customerId">The Shard Key is the Customer Id</param>
/// <param name="shardConnectionString">The connection string for the Shard - this should only have the credentials and NOT any datasource. The correct datasource and initial catalog are returned by the Shard Map</param>
/// <param name="metadataWorkSpaceConnectionString">Metadata required by EF model first cannot be passed in the shard connection string, it is passed here and used to return the MetadataWorkspace - no actual connection is created</param>
public ElasticScaleContext(ShardMapManager shardMapManager, IPrincipal user, string shardConnectionString, string metadataWorkSpaceConnectionString)
: base(CreateEntityConnection(shardMapManager, user, shardConnectionString, metadataWorkSpaceConnectionString), true)
{
}
private static DbConnection CreateEntityConnection(ShardMapManager shardMapManager, IPrincipal user, string shardConnectionString, string metadataWorkSpaceConnectionString)
{
int shardKey = 0; // Default just to get a valid connection string on login page (it's never actually used)
if (user != null && user.Identity.IsAuthenticated)
{
shardKey = user.Identity.GetCustomerId();
}
// Loads the Shard Map from the Shard Manager
// This has the details of which shards are located on which databases
ListShardMap<T> shardMap = shardMapManager.GetListShardMap<T>(AppConfig.ShardMapName);
// No initialization
Database.SetInitializer<ElasticScaleContext<T>>(null);
// Create Elastic Scale SqlConnection
// ******* FAILED HERE *********
var shardConnection = shardMap.OpenConnectionForKey(shardKey, shardConnectionString, ConnectionOptions.None);
// Allocate metadata workspace via an EF connection
var efConnection = new EntityConnection(metadataWorkSpaceConnectionString);
// Create Entity connection that holds the sharded SqlConnection and metadata workspace
var workspace = efConnection.GetMetadataWorkspace();
EntityConnection entcon = new EntityConnection(workspace, shardConnection);
return entcon;
}
}
我正在使用Ninject,ShardMapManager被注入为Singleton:
// Only ever create one Shard Map Manager
kernel.Bind<ShardMapManager>().ToMethod(context =>
{
return ShardMapManagerFactory.GetSqlShardMapManager(AppConfig.ConnectionString, ShardMapManagerLoadPolicy.Lazy);
}).InSingletonScope();
并且上下文是按请求创建的:
kernel.Bind<DbContext>().ToMethod(ctx =>
{
return new ElasticScaleContext<int>(kernel.Get<ShardMapManager>(), kernel.Get<IPrincipal>(), AppConfig.BaseConnectionString, AppConfig.SCSMetaDataConnectionString);
}}).InRequestScope();
所以有几个问题:
我在上下文中创建的连接是否应该正常处理?
有谁知道如何管理
ShardMapManger
连接?下面的代码(由于我的模型第一EF是必需的 方法)打开然后不关闭连接?
更新- 根据@Evk的建议(见评论),我修改了对 EntityConnection 的构造函数调用,以传递 trueentityConnectionOwnsStoreConnection
这应该允许它在使用后正确关闭存储连接,见下文。我真的需要一种方法来监视连接池,看看这是否有任何影响:
var efConnection = new EntityConnection(metadataWorkSpaceConnectionString);
// Create Entity connection that holds the sharded SqlConnection and metadata workspace
var workspace = efConnection.GetMetadataWorkspace();
EntityConnection entcon = new EntityConnection(workspace, shardConnection. true);
最后,我可以通过任何方法监视和查看 Azure 弹性 SQL 池上连接的当前状态?
我意识到这是很多问题,但我正在寻找有关该领域的任何信息 - 网络上确实没有那么多现有信息。
附加信息: 该解决方案使用EF6、SQL Server 2014、MVC 5.0
如注释所示,CreateEntityConnection
方法中,您可以从底层连接创建实体连接,但不要将重要参数"entityConnectionOwnsStoreConnection"设置为 true。这意味着实体连接不负责管理您的商店连接,也不会关闭它,因此您的连接将泄漏。若要修复,请使用另一个EntityConnection
构造函数:
var entcon = new EntityConnection(workspace, shardConnection, true);
然后,当上下文被释放时,它将释放您的EntityConnection
,这反过来将释放底层数据库连接。