2

非同期コンテキストからのリクエストを完了しないと、タイムアウト時に元のリクエストが再度再生されるという Jetty の問題に直面しています。動作は次のとおりです。リクエストごとにタイムアウト付きの非同期リスナーを設定するため、2 つのスレッドが実行されJetty Thread1ますThread2。ここで、クライアントへのデータの書き込みがタイムアウトよりも長くかかるとしましょう。リクエストが完了していないため、タイムアウト スレッドがトリガーされ、誰かがデータを書き込んでいることを確認して、サイレントに戻ります。Jetty は黙って戻るのが好きではありません。リクエストをリプレイして、別のサービングおよびタイムアウト スレッドが作成され、データが書き込まれ、非同期コンテキストが完了するまで続行します。

問題のコードはこちら - In HttpChannelStatein expired()method

if (aListeners!=null)
{
   for (AsyncListener listener : aListeners)
   {
       try
       {
           listener.onTimeout(event);
       }
       catch(Exception e)
       {
           LOG.debug(e);
           event.setThrowable(e); 
           _channel.getRequest().setAttribute(RequestDispatcher.ERROR_EXCEPTION,e);
           break;
        }
    }
}


boolean dispatch=false;
synchronized (this)
{
    if (_async==Async.EXPIRING)
    {
        _async=Async.EXPIRED;
        if (_state==State.ASYNC_WAIT)
        {
            _state=State.ASYNC_WOKEN;
            dispatch=true;
        }
    }
}
if (dispatch)
scheduleDispatch();   // <------------ dispatch again why
}
4

1 に答える 1

4

これは正常な動作です。リクエストを非同期状態にしてからタイムアウトを処理しなかったため、リクエストは ASYNC の DispatcherType で再ディスパッチされます。

独自のタイムアウト リスナーを追加し、そのタイムアウト内で asyncContext を完了するかディスパッチする場合、jetty はそれを再ディスパッチしません (リスナーがディスパッチを呼び出さない限り)。

DispatcherType のテストを使用して非同期サーブレット コードを保護することもできますが、非同期で処理される可能性のある問題が複数ある場合は混乱する可能性があります。

    asyncContext.addListener(new AsyncListener()
    {

        @Override
        public void onTimeout(AsyncEvent event) throws IOException
        {
            event.getAsyncContext().complete();

        }

        @Override
        public void onStartAsync(AsyncEvent event) throws IOException
        {                
        }

        @Override
        public void onError(AsyncEvent event) throws IOException
        {
        }

        @Override
        public void onComplete(AsyncEvent event) throws IOException
        {
        }
    });
于 2015-06-17T02:36:16.310 に答える