4

より大規模な監視およびデータ収集システム用に ZeroMQ を評価しようとしています。小規模ではすべてうまく機能しますが、負荷とスケールを少し上げるのは難しいようです。

現在、C# ラッパー (clrzmq、3.0.0-rc1) を使用して、パブリッシャー アプリケーションとサブスクライバー アプリケーションの両方を作成しています。パブリッシャー ソケット (ソケット 1 つ、コンテキスト 1 つ) を 1000 のエンドポイント (ローカルホスト + ポートの範囲) にバインドし、サブスクライバー アプリケーション ソケット (ソケット 1 つ、コンテキスト 1 つ) をパブリッシャー エンドポイントにバインドします。

これは機能する場合もあれば、機能しない場合もあります (プロセスによって処理されるソケットの最大数に関係していると思います)。アプリケーションを起動する順序に依存しているようですが、確かなことはわかりません。私が見る唯一のものは、詳細がまったく含まれていない厄介な SEHExceptions です。単純なコンソール アプリケーションを作成すると、次のような低レベルの C++ アサートが表示されることがあります。

  • アサーションに失敗しました: fds.size () <= FD_SETSIZE (......\src\select.cpp:70)
  • アサーションに失敗しました: 権限が拒否されました (......\src\signaler.cpp:281)
  • アサーションに失敗しました: ピアによって接続がリセットされました (......\src\signaler.cpp:124)

私にはあまり役に立ちません。C# ラッパーでは、コンテキストの作成が失敗します。ソケットへの接続やソケットの作成を開始する機会すらありません。低レベルの ZeroMQ エラーは例外をスローすることで処理されることを期待していますが、エラーの処理方法をまだ理解していないだけかもしれません。

私が今持っている質問は次のとおりです。

  • すべて C# を使用して、単一のマシン (実際には 1 つのパブリッシャー = 1 マシン) 上の 1000 の個別のパブリッシャーと別のマシン上のいくつかのサブスクライバーをシミュレートする (ある程度) 現実的なテスト セットアップを作成するにはどうすればよいですか。それは可能ですか?
  • さらに重要なことは、C# コードで ZeroMQ エラーをトラップして、何が問題なのかを理解できるようにするにはどうすればよいでしょうか?

ZeroMQ はかなり安定していて成熟しているように見えるので、1000 のパブリッシャーを処理するのが問題になるとは思えません。ただし、C# で ZeroMQ を使用するには、現在利用可能なものよりも優れたエラー サポートが必要です (ここで何かを完全に見逃していない限り)。

アップデート:

ソースを掘り下げた後、私zmq_assert(...)RaiseException (0x40000015, EXCEPTION_NONCONTINUABLE, 1, extra_info);. これにより、元の assert ステートメントがコンソールにダンプされた後、アプリケーションが突然終了します。これは少し厳しいように思えますが、実際には回復不可能であることを考えると、最良の選択肢かもしれません。ただし、多少優れたエラー メッセージが表示されても問題はありません。誰もが意味を知っているわけではありませんfds.size () <= FD_SETSIZE。ソースのコメントはいくつかの手がかりを与えてくれます。エラー メッセージにそのコメントがあるといいでしょう。とにかく、私のアプリケーションがコンソール アプリではないことを考えると、未処理の SEHException が残ります。これには、アサート ステートメントや行/ファイル情報さえ含まれていないようです。他の同様の不可解なエラーを引き起こすバグを他にいくつ作成するのだろうか.

4

3 に答える 3

3

これをもう少し調べたところ、デフォルトのソケット数が 1024 に設定されているようです。C# ラッパーには、Contextこの設定を変更できるオブジェクトのプロパティがありますが、少なくとも期待どおりには機能していません。また、ネイティブzmqlibではコンテキスト オブジェクトにこの設定がありません。

clrzmq説明のようなセットアップを実行することは、少なくともC# ZeroMQ ラッパーを使用しない限り、不可能のようです。別のマシンで 500 のパブリッシャーを実行し、別のマシンで別の 500 プラス 1000 のサブスクライバーを実行することで解決しました。これはエラーなしでうまくいきました。

他のトピックも少し残念です。ソケットの最大数に達すると、ZeroMQ は単純にキャッチ不能な例外をスローし、アプリケーションを突然クラッシュさせます。これはフェイル ファストのアプローチであり、これ以上のデータや状態の破損を回避しますが、残念なことに、アプリケーションが停止する原因となった原因についての手掛かりがほとんど残りません。他の投稿から判断すると、これが発生した場合、事後分析のためのデータを収集するのは非常に難しいようです. C# コードで例外をキャッチすることは不可能または非常に難しいように思われます。出力されたアサートを取得するために stdout にフックすることも非常に難しいようです (コマンド プロンプトから実行していない場合、アサート メッセージは直前に出力されます)。アプリケーションが停止します)。

全体として、これにより、zmq_assert(...) 呼び出しを介して ZeroMQ が終了すると、コンソール以外の C# 設定での低レベルのトラブルシューティングと事後分析が非常に難しくなります。うまくいけば、これは極端なケースでした。すべての障害モードがこのような突然の終了を引き起こすわけではないようです。

于 2012-12-04T19:11:29.137 に答える
2

デフォルトの FD_SETSIZE は 1024 (MSVC libzmq プロジェクトで定義) であるため、テスト ケースのほぼ半分でこれに到達します。もう一方は、そこから転落したと主張します。

libzmq プロジェクトでこれを 4K または 8K に増やすと、うまく機能するはずです。

assert() 呼び出しに関しては、確かに Windows では残忍すぎます。Linux では、適切なスタック ダンプと、問題を追跡するのに十分な情報が得られます。assert マクロを自由に改善して、デバッガーを起動するなど、よりスマートに実行できるようにしてください。いずれにせよ、アサートにヒットすると、合理的に続行できなくなります。

FD セットがいっぱいになったときにアサートするほうが、うまく処理できます。C/C++ について何か知っている場合は、遠慮なくコードを見てください。私たちは人々のパッチに依存しています。

また、1024 が小さすぎると感じた場合は、プロジェクトでこれを上げて、パッチを送ってください。

于 2012-12-11T12:56:58.007 に答える
1

この問題をざっと見てみると、コンピュータに対して作成しているソケット接続が多すぎることがわかります。MSDNのソケットの最大数に関するこのリンクを確認してください。あなたが得ているエラーは、これがあなたのエラーの原因である可能性があるのに十分に関連しているように見えます.

正直なところ、1000 の個別のパブリッシャーを持つことは、zmq を使用するために問題に少し間違って取り組んでいるように思えます。1 つのパブリッシャーを使用して「名前空間」を使用し、サブスクライバーが受け取るメッセージを分割するために必要なものにサブスクライバーをサブスクライブさせないのはなぜですか。

于 2012-12-03T18:36:01.390 に答える