1

1000 を超える同時接続を受け入れるマルチスレッド Socket Server アプリケーションを作成しました。最近、アプリケーションがクラッシュしました。ダンプファイルを分析した後、ヒープの破損によりアプリがクラッシュしたことがわかりました。次のリンクで説明されている同じ問題を見つけました。

.NET には信頼できる非同期ソケット通信がありませんか? http://support.microsoft.com/kb/947862

また、ディスカッションでは3つの解決策が提案されています。

  1. ネットワーク アプリケーションは、ポストする未処理の非同期 IOの数に上限を設定する必要があります。

  2. Microsoft CCR を使用する

  3. TPL を使用する

時間的要因により、私は#1に固執することを考えましたが、これを実装する方法を明確に把握していません. 良い出発点を教えてください。

また、この問題を解決するために Async with TPL を使用した人はいますか?

4

2 に答える 2

1

あなたが参照している回答でリンクしたブログ投稿よりも良い出発点を意味しますか?

問題はこれです:

  • 非同期書き込み中に使用されるメモリやその他の操作ごとのリソースは、多くの場合、リモート ピアの TCP スタックがデータを確認し、ローカル スタックが非同期書き込み操作を完了して、バッファーを再利用できることを通知するまで、"使用中" になります。
  • リモート ピアがソケットからデータを読み取る速度と、2 つのピア間のリンクの輻輳によってすべてが管理されるため、ローカル ピアはこれを制御できません。

上記のため、一度に未処理の非同期書き込みの量に厳しい制限を設ける必要があります。非同期書き込みを発行する直前にカウンターをインクリメントし、完了ハンドラーでそれをデクリメントすることで、これを追跡できます。

その限界に達したとき、あなたがどうするかはあなた次第です。元の記事では、書き込まれるデータが配置されるキューを好みます。このキューは、書き込み完了時にデータのソースとして使用できます。キューが空になると、通常どおり送信できます。もちろん、これは問題を解決するだけです。リモート ピアによって制御されるメモリ リソース (キューに入れられたデータ) はまだありますが、他の OS リソースも使用されていません (非ページ プール、I/O ページ ロック制限、等)。

制限に達したときにピア送信を停止するだけで済みます。非同期 API を介して構築する API には、以前は常に送信されていた送信からの「現時点では送信できません。後で再試行してください」という戻り値が必要です。 "仕事"。

これを行っている場合は、1 つの連続したブロックにバッファーの大きなブロックを割り当て、それらをプールから使用することで、固定されたメモリの問題を回避することも真剣に検討します。

于 2013-11-14T13:39:30.750 に答える
0

まず、これは非常に古い KB 記事です。その特定の問題があることをどのように確信していますか?それから、Hans Passant が SO の質問で答えているように、悪い非同期コードを書く噛み付きます。リソースを管理しないと (メモリ バッファはリソースです)、並行プログラムでメモリエラーが発生します。

生のスレッドを使用して優れた並行コードを作成するのは非常に難しく、TPL を使用すると簡単になりますが、既に発生しているバグを修正することはできません。実際、現在の問題を特定しない限り、TPL を使用するバージョンに移行する可能性があります。

アプリケーションがクラッシュする原因となった具体的な問題がわからないので、いくつか提案することしかできません。

  1. 新しいメモリ バッファを割り当てる代わりに、BufferManagerを使用してメモリ バッファを再利用します。
  2. リクエストごとに新しいスレッドを開始する代わりに、キューを使用してリクエストを保存し、非同期的に処理します。

構築しているアプリケーションの種類によっては、他にも使用できる手法があります。たとえば、TPL DataFlow を使用して、独立したステップで処理を分割できます。

CCR については、Robotics Studio 以外で使用してもあまり意味がありません。TPL には、並行アプリを作成するために必要な関連機能のほとんどが含まれています。

于 2013-11-14T10:06:41.513 に答える