1

クライアントからリクエストを受信し、別のサーバーにリクエストを送信し、元のクライアント リクエストへのレスポンスで 2 番目のリクエストからのレスポンスを使用する netty サーバーがあります。タイムアウトが発生した場合に一般的な応答を送信できるように、2 番目のサーバーへの要求に短いタイムアウト (~40ms) を設定したいのですが、2 番目のサーバーへの接続を閉じたくありません。代わりに、タイムアウトになったリクエストが到着したときにそのレスポンスを単に破棄し、接続をプールに戻します。

nettyでこれを行う最良の方法は何ですか? ReadTimeoutHandler を試しましたが、タイムアウトが発生すると、2 番目のサーバーへの接続が閉じられるようです。

4

1 に答える 1

4

要件のために、2 番目のサーバーへの接続に関する独自のタイミング管理を作成する必要があるようです。さらに、2番目のサーバーに対して同時に確立できる接続の数にも制限があることを意味する可能性のある接続プールについて言及しているため(まあ、常に制限があります。実際に心配する必要があるかどうかによって異なります)か否か)。

アウトバウンド要求をキューに入れることを心配しない単純なケースでは、ReadTimeoutHandler のコピーを作成し、必要に応じて変更することができます。ほとんどの場合、コンテキストからコールバックをプルして、閉じる代わりに呼び出します。 readTimedOut() メソッドでの接続。

アウトバウンド要求をキューに入れる場合は、応答を受信する時間だけでなく、キューに費やされた時間も考慮する必要があります。そのため、ソリューションには、項目を入れるとすぐに開始する独自のタイマーが必要になります。アウトバウンド キュー。さらに、タイマーと返される有効な結果との間で同期する方法が必要です (タイマーがタイムアウトしたときに 1 つではなく、2 番目のサーバーからの応答が入ったときに 1 つの応答のみを送信する必要があります)。これを行うには、チャネルへの参照を含む何らかのタイプのマネージャー オブジェクトを使用し、このマネージャーを介してコールバックを書き戻す必要があると思います。

例(擬似的なコードで)

MyStateManager manager = new MyStateManager(channel);
// Scheduled a timer task for 40ms from now to invoke the callback
// method of your ReadTimedOutCallback and send a message through the manager
myTimer.schedule(new ReadTimedOutCallback(manager),40);
// Send an outbound request to server 2 through a class that queues
// and manages such requests asynchronously.  When the request is complete
// it invokes the callback method of RequestCompletedCallback which then
// sends a response through the manager.
myAsyncOutboundServerRequester.request(new RequestCompletedCallback(manager));
// ... finish and return the thread to Netty for use with other requests
// while the async tasks process

そして、単純な形式のマネージャーは次のようになります (例外処理、チャネル状態チェックなどを除く):

public class MyStateManager
{
    private final Channel channel;
    private AtomicBoolean messageSent = new AtomicBoolean(false);
    public MyStateManager(Channel channel)
    {
        this.channel = channel;
    }

    // Called by the ReadTimeoutCallback
    public void sendGenericResponse()
    {
        if (messageSent.getAndSet(true))
        {
           //... write generic response to channel
           ChannelFuture future = channel.write... 
           // Add listeners to future, etc
        } 
    }

    // Called by the RequestCompletedCallback
    public void sendResponse(MyResponseObject response)
    {
        if (messageSent.getAndSet(true))
        {
            // write returned response to channel
            ChannelFuture future = channel.write(response);
            // Add listeners to future, etc
        }
    }

}

2 番目のサーバーへの接続が長時間 (30 秒または 1 分程度) 応答しない場合に接続を閉じるために、何らかのタイムアウト チェックを行うことをお勧めします。

于 2013-04-10T21:51:29.633 に答える