1

Tomcat7 を構成して、ジョブをバックグラウンド スレッドのプールにポストする単一のコネクタ スレッドを作成し、リクエストを非同期的に完了させました。各リクエストには 1 秒の遅延があります。私のテスト (JMeter) は 5 つのスレッドをスピンアップし、5 つの同時要求を行います。単一のコネクタ スレッドが 5 つの要求のそれぞれをすぐに処理することを期待しています。代わりに、前のタスク (bg スレッドで実行されている) が完了するのを待ってから、次のタスクにサービスを提供します。

明確にするために、私の構成は、Node.js や Tornado などの「シングルスレッド」非同期サーバーのスレッド アーキテクチャを模倣しようとしています。

コネクタ:

<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           maxThreads="1"
           URIEncoding="UTF-8" />

サーブレット:

@WebServlet(asyncSupported = true, value = "/testasync", loadOnStartup = 1)
public class TestAsync extends HttpServlet {
    private static final Logger LOG = Logger.getLogger(TestAsync.class.getName());
    private static final long serialVersionUID = 1L;
    private static final int NUM_WORKER_THREADS = 100;

private ExecutorService executor = null;

@Override
public void init() throws ServletException {
    this.executor = Executors.newFixedThreadPool(NUM_WORKER_THREADS);
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    final AsyncContext ac = request.startAsync(); // obtain async context
    ac.setTimeout(0); // test only, no timeout

    LOG.info("received request on: " + Thread.currentThread().getId());
    this.executor.execute(new Runnable() {
        public void run() {
            try {
                LOG.info("processing request: "+ Thread.currentThread().getId());
                Thread.sleep(5000);
                LOG.info("processed request:"+ Thread.currentThread().getId());
                ac.getResponse().getWriter().write("<h1>Request Processed</h1>");
                ac.complete();
            }
            catch (Exception e) {
                LOG.info("failed:" + e);
            }
        }
    });
    LOG.info("posted request on: " + Thread.currentThread().getId());
}

}

ログ:

2013 年 9 月 17 日 12:26:00 PM TestAsync doGet 情報: 要求を受信しました: 16

2013 年 9 月 17 日 12:26:00 PM TestAsync doGet INFO: 投稿された要求: 16

2013 年 9 月 17 日 12:26:00 PM TestAsync$1 実行情報: 要求の処理: 26

2013 年 9 月 17 日 12:26:05 PM TestAsync$1 実行情報: 処理された要求:26

2013 年 9 月 17 日 12:26:05 PM TestAsync doGet 情報: 要求を受信しました: 27

2013 年 9 月 17 日 12:26:05 PM TestAsync doGet INFO: 投稿された要求: 27

2013 年 9 月 17 日 12:26:05 PM TestAsync$1 実行情報: 要求の処理: 28

2013 年 9 月 17 日 12:26:10 PM TestAsync$1 実行情報: 処理された要求:28

2013 年 9 月 17 日 12:26:10 PM TestAsync doGet 情報: 要求を受信しました: 27

2013 年 9 月 17 日 12:26:10 PM TestAsync doGet INFO: 投稿された要求: 27

2013 年 9 月 17 日 12:26:10 PM TestAsync$1 実行情報: 要求の処理: 29

2013 年 9 月 17 日 12:26:15 PM TestAsync$1 実行情報: 処理された要求:29

2013 年 9 月 17 日 12:26:15 PM TestAsync doGet 情報: 要求を受信しました: 27

2013 年 9 月 17 日 12:26:15 PM TestAsync doGet INFO: 投稿された要求: 27

2013 年 9 月 17 日 12:26:15 PM TestAsync$1 実行情報: 要求の処理: 30

2013 年 9 月 17 日 12:26:20 PM TestAsync$1 実行情報: 処理された要求:30

2013 年 9 月 17 日 12:26:20 PM TestAsync doGet INFO: 要求を受け取りました: 27

2013 年 9 月 17 日 12:26:20 PM TestAsync doGet INFO: 投稿された要求: 27

2013 年 9 月 17 日 12:26:20 PM TestAsync$1 実行情報: 要求の処理: 31

2013 年 9 月 17 日 12:26:25 PM TestAsync$1 実行情報: 処理された要求:31

4

2 に答える 2

1

これは、Tomcat での BIO コネクタの使用によるものだと思います。これは、Tomcat インストールのデフォルトのコネクタです。BIO コネクタは、応答が書き込まれるまですべての要求をブロックして読み取り、プール内の単一のスレッドで、説明した動作を確認できます。

を 1 より大きくするmaxThreadsと、他のスレッドが着信要求を受け取ることがわかりますが、コネクタは既存のスレッドが解放されるまで新しい接続を引き続きブロックします。希望するモデル (処理を別のスレッドに委任したいときに解放される単一の要求スレッド) に移行するには、ブロックしないコネクタ (NIO または APR/Native) に切り替える必要があります。また、スレッド プールのサイズを大きくする必要がある場合もあります (これは、要求処理スレッドが 1 つのジョブのみを実行するかどうか、および過負荷になっているかどうかによって異なります)。

于 2013-09-17T18:18:21.510 に答える