Microsoft のいくつかの例に従った後、現在のユーザーのテナント (または顧客) ID に依存する Elastic ShardMapManager から接続文字列を取得する DbContext の Elastic バージョンを実装しました。
これは技術的に機能し、Azure アカウントにデプロイしました。デフォルトのコンテキスト接続作成メカニズムをオーバーライドしたので、接続プールの管理に関心があります。また、リクエストごとに呼び出されるたびに接続がどのように管理されるのかわかりませんshardMap.OpenConnectionForKey
(以下のninject設定を参照)。
昨日、簡単なテストを行った後、Web アプリが次のメッセージで失敗しました。
タイムアウトになりました。プールから接続を取得する前に、タイムアウト期間が経過しました。これは、プールされたすべての接続が使用中で、最大プール サイズに達したために発生した可能性があります。
今日は再現できないため、これは 1 回限りの可能性がありますが、接続プールが効率的に使用されていることを確認したいと考えています。
失敗したコードは、私の 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;
}
}
シングルトンとして注入されている ShardMapManager で Ninject を使用しています。
// Only ever create one Shard Map Manager
kernel.Bind<ShardMapManager>().ToMethod(context =>
{
return ShardMapManagerFactory.GetSqlShardMapManager(AppConfig.ConnectionString, ShardMapManagerLoadPolicy.Lazy);
}).InSingletonScope();
Context はリクエストごとに作成されます。
kernel.Bind<DbContext>().ToMethod(ctx =>
{
return new ElasticScaleContext<int>(kernel.Get<ShardMapManager>(), kernel.Get<IPrincipal>(), AppConfig.BaseConnectionString, AppConfig.SCSMetaDataConnectionString);
}}).InRequestScope();
いくつか質問があります:
コンテキスト内で作成している接続は、通常どおり破棄する必要がありますか?
ShardMapManger
接続がどのように管理されているか知っている人はいますか?以下のコード ( Model First EF アプローチのために必要) は、接続を開いてから閉じませんか?
更新- @Evk からのアドバイスの後 (コメントを参照)、EntityConnection へのコンストラクター呼び出しを変更して true を渡しentityConnectionOwnsStoreConnection
、使用後にストア接続を適切に閉じることができるようにしました。以下を参照してください。これが何らかの影響を与えるかどうかを確認するために、接続プールを監視する方法が本当に必要です。
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 Elastic SQL プールの接続の現在の状態を監視および表示する方法はありますか?
たくさんの質問があることは承知していますが、私はこの分野に関するあらゆる情報を求めています。実際、Web 上にはそれほど多くの既存の情報はありません。
追加情報: このソリューションでは、EF6、SQL Server 2014、MVC 5.0 を使用しています