3

RabbitMQ を介してメッセージを受信する Windows サービスがあります。これにより、何らかの作業を行うイベント ハンドラーがトリガーされ、結果をデータベースに永続化しようとします。以下を使用してスレッド化されています。

ThreadPool.QueueUserWorkItem(ProcessMessageOnThread, messageReceived);

ここで、RabbitMQ からデキューされたメッセージの表現である でProcessMessageOnThread作業を行うメソッドです。messageReceived

通常の状況では、Windows サービスは期待どおりに動作しました。つまり、デキュー、プロセス、および永続化です。

すべてのメッセージが処理され、適切な変更が処理されるようにしたいので、SQL Server への接続を開くことができない場合は、メッセージを再度キューに入れ、再度処理できるようにします (うまくいけば、そのとき SQL Server はそうしないと、これが続きます-そして私はそれで問題ありません)。

プロセスが一定期間期待どおりに実行されていたときに問題が発生し、SQL Server 接続プールがいっぱいになり SQL Server が切断されました。これは、状況が少し不安定になったときです。

次の 2 つのいずれかが発生する可能性があります。

  • 例外がスローされますconnection.Open()-しかし、私はこれをキャッチしているので、心配していません

  • cmd.ExecuteNonQuery()ストアドプロシージャを実行している場所で例外がスローされます

これは、処理方法を理解する必要がある 2 番目のオプションです。以前は、ここで例外が発生した場合、ストアド プロシージャに渡したデータに問題があったため、データをキューから移動し、別の方法で分析する必要があると考えていました。

ただし、実際には接続が確立されていない場合に例外が発生する場合を処理するには、新しいアプローチが必要だと思います。

クラスを調べたところ、この説明を持つSqlExceptionプロパティが呼び出されていることに気付きました。これに関する情報には次のように記載されています。ClassGets the severity level of the error returned from SQL Server

重大度レベルが 10 以下のメッセージは情報提供を目的としており、ユーザーが入力した情報の間違いによって引き起こされた問題を示しています。11 から 16 までの重大度レベルはユーザーが生成し、ユーザーが修正できます。17 ~ 25 の重大度レベルは、ソフトウェアまたはハードウェアのエラーを示します。レベル 17、18、または 19 のエラーが発生した場合、特定のステートメントを実行できない場合がありますが、作業を続行できます。

これは、ストアド プロシージャに不正な形式のデータが送信される可能性が最も高いためif (ex.Class > 16)、接続に問題があるため、メッセージをチェックしてから再キューイングできる例外処理を修正することを意味しますか?else

したがって、問題は、例外処理をどのように行うべきか、およびcmd.ExecuteNonQuery()スローされた例外が接続の切断によるものであるかどうかを呼び出すときにどのように検出できるかです。


アップデート:

接続がプールに返されないという問題が以前に発生し (これはスレッドの問題が原因でした)、これらの問題を修正したので、問題は接続がプールに戻らないこととは関係がないと確信しています。また、接続が使用されている目的に関するロジックは非常に単純であり、それらが一貫して閉じられていることを確認しています...したがって、Sqlサーバーの切断と動作のキャプチャに関する回答にもっと興味がありますcmd.ExecuteNonQuery() の

4

1 に答える 1

3

接続プール内の接続は、さまざまな理由で奇妙な状態になる可能性があります。これらはすべて、アプリケーションの設計が不十分であることに関係しています。

  • 関連付けられたデータ リーダーの前に接続を閉じる
  • プールがリセットされない設定 (トランザクション分離レベルなど) を変更する
  • 非同期クエリ ( BeginOpenReader) を開始し、非同期ハンドラが起動する前に接続をプールに戻す

アプリケーションを調査し、接続がプールに適切に返されていることを確認する必要があります。デバッグに役立つことの 1 つは、開発環境でアプリケーション プールのサイズを小さくすることです。接続文字列でプールのサイズを変更します。

...;Integrated Security=SSPI;Max Pool Size=2;Pooling=True;

これにより、プーリングの問題を簡単に再現できます。

原因が見つからなくても、修正を展開する必要がある場合は、ClearPoolまたは のいずれかを使用できますClearAllPoolsOpen()これを行うのに適した場所は、またはの後に疑わしい例外の 1 つを検出したときですExecuteNonQuery()。どちらもSqlConnectionクラスの静的メソッドです。

SqlConnection.ClearPool(yourConnection);

または、さらに大まかなアプローチの場合:

SqlConnection.ClearAllPools()

これは基本的にPokémon Exception Handlingであることに注意してください。それが機能する場合、その理由はわかりません。:)

于 2012-09-24T16:19:34.000 に答える