11

これは長い投稿になるので、私と一緒にハングアップしてください。

数か月前にここで実装した本番サイトの1つで、ELMAHログに恐ろしい接続リークエラーメッセージが頻繁に表示されるようになりました。

"Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached."

EFを使用していて、接続処理は自動であるはずだったので、これは私を困惑させました。

それで私は掘り始めました。私が最初に考えた潜在的な原因は、MiniProfiler(または、miniprofilerを使用した実装)でした。私たちはこれを使用していて、うまく機能していますが、接続リークの可能性が心配でした。

    public OurContext() : base(GetProfilerConnection(), true)
    {}

    private static DbConnection GetProfilerConnection()
    {
        return new EFProfiledDbConnection(new SqlConnection(ConfigurationManager.ConnectionStrings["Database"].ConnectionString),
                                          MiniProfiler.Current);
    }       

基本呼び出しの「true」パラメーターによってコンテキストが接続の所有権を取得するという印象を受けたので、これは正常に機能し、接続は破棄されると思います。

ここに画像の説明を入力してください

拡張DEVブランチでは、EF5をサポートするように更新されていないため、ミニプロファイラーを削除しました。それほど遠くない将来に移行する予定なので、これは懸念事項として削除する必要があります。

懸念2は、「データコンテキストを適切に処理しているか」でしたか?そこで、私はEntity Framework Profilerを試用版としてダウンロードし、最も重いページを取得してテストを実行しました。

ここに画像の説明を入力してください

結果は、私たちが開いたコンテキストがすべて閉じられたことを明示的に示しましたが、私にとって懸念される部分は、開いたコンテキストの数です。DIコンテナ(Ninject 2)は、Web httpリクエストごとに1つのコンテキストをインスタンス化するように設定されていますが、これは正しいと思います。問題は、アプリケーションで画像をどのように処理するかによって決まります。特にこのページには、データベースに最大7つの画像を含めることができます。これらの各画像は、MVCアクションを介してページに含まれます。そのようです:

[<img src="/Controller/GetPhotoAction/[ImageId] />]

画像は別のリクエストであるため、別のコンテキストが開かれています。したがって、この特定のページでは、これを正しく理解していれば、接続プールからの7つの異なる接続を利用しています。これに多くのユーザーを掛けると、上記のエラーメッセージがどのように当てはまるかがわかります。

データベースに画像を保存する理由は2つあります。1つは、このアプリのデータを管理するための管理アプリケーションは米国西海岸にありますが、アプリケーションをホストするサーバーは米国東海岸にあります。ここ西海岸で稼働しているネットワークと東海岸のサーバーの間にVPNトンネルがあります。アプリも負荷分散されています(2つのWebフロントエンド)。VPNトンネルを介して画像をコピーし、各サーバー上のWebアプリ内のファイルの場所に画像を書き込む権限を処理しないように、画像をDBに保存することが決定されました(2つの場所も完全に異なるドメインです) 。

暫定的に、テスト中に、接続文字列の最大接続プールサイズを増やし、来週初めにこれをPRODに展開する予定です。

だから、私の質問は次のとおりです。

1)ここでリークチェックで拠点をカバーしましたか?私は持っていると信じています。私が上で述べたことに私は間違っていますか?

2)このページの複数のデータコンテキストが原因であることが判明した場合、アクセス許可を念頭に置いて全国の2つのサーバーにイメージを書き込む方法に関する提案はドメイン間で行われますか?現実的には、これをとにかくやりたいのですが、技術的なハードルは、休暇の直前の現時点で私たちがやろうとしていることよりも少し多いです。

3)上記のどちらも問題ではないと思われる場合、何が欠けている可能性がありますか?リクエストが十分に高いためにこのエラーが発生し、スケールアウトする必要があるのでしょうか。ログを掘り下げて使用統計を表示することはできますが、可能性は低いようです。このページは1時間キャッシュされます(パラメーターによって異なります)

4

1 に答える 1

2

Web アプリが接続をリークしているかどうかを確認する方法は他にもあります。最近、私はこれらを使用することで恩恵を受けています:

  • SQL プロファイラーを使用する(開いている/閉じている接続の数を確認できます)
  • IIS の接続プールを監視します- 詳細については、こちらを参照してください - http://msdn.microsoft.com/en-us/library/aa175863%28SQL.80%29.aspx
  • 接続文字列の最大プール サイズを、1 つの要求に対して予想される接続の最大値に設定します10 枚以上の画像があり、同じ例外で失敗しました。リクエストごとにネストされた接続のバグを削除したところ、画像に対するサブリクエストでも問題ありませんでした。

そしてあなたの質問に。リクエストごとに 1 つのデータ コンテキストで問題ないはずです。リクエスト スコープにバインドされると、リクエストの最後に破棄されます (実際には、ガベージ コレクターがリクエスト オブジェクトを収集するまで遅延されます)。ただし、datacontext を直接使用していない場合 (たとえば、リポジトリ パターン ラッパーを使用している場合) は注意してください。これは、隠れた (接続リーク) バグが存在する可能性があるためです。

于 2012-12-10T15:14:25.913 に答える