1

ポート統合の例をコードベースに適応させようとしています。私が抱えていると思う問題は、サーバーがシャットダウンするか、クライアントがタスクを完了するまで、またはより具体的には、同じパイプラインがずっと使用されるまで、クライアントとサーバーの間でチャネルが開いたままになることです。そのため、統合ハンドラがパイプラインから削除された例のワークフローは機能しません。

ポート統合の例で見た問題は、クライアントが各リクエストの前に保留中のマジック バイトを保持し続けていたが、サーバー側のチャネルがポート統合ハンドラーを削除したことでした。有効なプロトコル メッセージであること。クライアントからのプレフィックス マジック バイトを含むチャネルを介した後続のメッセージは、統合ハンドラがパイプラインでマジック バイトを消費しなくなったため、処理できず、メッセージの形式が正しくありませんでした。

統合ハンドラーをパイプラインに残すことでこれを回避できましたが、スニファーがプロトコルを識別するたびに、プロトコル ハンドラーが追加されていました。パイプラインはチャネルの存続期間中永続的だったので、同じハンドラーを何度も追加し続けました。これは、チャネルに属性を追加してパイプラインに再度追加することを回避することで簡単に回避できました。

今私が見ている問題は、メッセージがいくつかのバッファに分割されていることです。クライアントが 2k バイトを 2 つのメッセージに分割して送信した場合。最初のメッセージは正しく盗聴され、次のハンドラー (具体的には、LengthFieldBasedFrameDecoder) に渡されます。すべてのバイトが揃っているわけではないので、残りを待ちます。次のメッセージが残りのバイトと共に入ってくると、パイプラインから統合子を削除できないため、もう一度スニッフィングしますが、スニッフィングは失敗します。

これに対する回避策、または同じことを達成するためのより良い方法はありますか?

アップデート:

ユニファイアからマジック バイトの消費を移動することは正しいアプローチのように思えますが、まだ問題になっている (またはそう思われる) のは、パイプラインを動的に変更することが netty 4 では netty と同じように機能しないことです。 3.

私のクライアントプロトコルは、それを識別するためにバイトシーケンスを使用してすべてのリクエストを先頭に追加しています。netty 3 では、単純に ChannelBuffer 内のバイトをスキップし、ユニファイヤを削除して、その要求を処理するための適切なプロトコル処理を追加しました。後続のすべてのリクエストで同じことが起こり、完全に機能しました。

ただし、netty 4 では、マジック バイトを消費するパイプラインからハンドラーを削除すると、クライアントがチャネルを閉じるまで存続するチャネルの存続期間中、そのハンドラーはなくなります。したがって、チャネルを通過する各メッセージに対してパイプライン/ChannelHandlerContext が新しいように見える前は、毎回再利用されており、これが問題の場所だと思います。

事実、これにより、この種のパイプラインの動的な変更は、実際には困難または不可能になります。各リクエストの最初の N バイトだけを消費する何かが欲しいのですが、いくつかの ByteBuf に分割された大きなリクエストはすべて最初の N バイトを食べてしまうため、パイプラインに残すことはできません。

更新 2: 現在見ている動作は、フォローアップ トピックで言及した内容に関連していると思います: プロトコルを識別するプレフィックス付きバイト シーケンスを管理する方法

4

1 に答える 1

1

ポート統合の例では、クライアントがプロトコルを切り替えることを想定していません。本当にそれをサポートしたい場合は、クライアントが「今のところこの特定のプロトコルの使用は終了しました。次のメッセージは別のプロトコルを使用する可能性があります」と言うメカニズムを考え出す必要があります。クリアされたパイプラインに挿入されます。

アップデート:

シナリオをもう一度読んだ後、あなたの問題は、統合ハンドラーが「マジックバイト」を消費していることだと思います。すべきではありません。Netty の例はそうではありません。統合ハンドラーは、プロトコルを決定し、正しいハンドラー シーケンスをインストールして終了する必要があります。新しいハンドラ シーケンスは、最初のバイト バッファが変更されていないことを確認する必要があります。つまり、バイトは消費されていないはずです。

于 2013-08-26T15:38:23.997 に答える