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 TestAsync doGet INFO:收到请求:16

2013 年 9 月 17 日下午 12:26:00 TestAsync doGet INFO:发布请求:16

2013 年 9 月 17 日下午 12:26:00 TestAsync$1 运行信息:处理请求:26

2013 年 9 月 17 日下午 12:26:05 TestAsync$1 运行信息:已处理请求:26

2013 年 9 月 17 日下午 12:26:05 TestAsync doGet INFO:收到请求:27

2013 年 9 月 17 日下午 12:26:05 TestAsync doGet INFO:发布请求:27

2013 年 9 月 17 日下午 12:26:05 TestAsync$1 运行信息:处理请求:28

2013 年 9 月 17 日下午 12:26:10 TestAsync$1 运行信息:已处理请求:28

2013 年 9 月 17 日下午 12:26:10 TestAsync doGet INFO:收到请求:27

2013 年 9 月 17 日下午 12:26:10 TestAsync doGet INFO:发布请求:27

2013 年 9 月 17 日下午 12:26:10 TestAsync$1 运行信息:处理请求:29

2013 年 9 月 17 日下午 12:26:15 TestAsync$1 运行信息:已处理请求:29

2013 年 9 月 17 日下午 12:26:15 TestAsync doGet INFO:收到请求:27

2013 年 9 月 17 日下午 12:26:15 TestAsync doGet INFO:发布请求:27

2013 年 9 月 17 日下午 12:26:15 TestAsync$1 运行信息:处理请求:30

2013 年 9 月 17 日下午 12:26:20 TestAsync$1 运行信息:已处理请求:30

2013 年 9 月 17 日下午 12:26:20 TestAsync doGet INFO:收到请求:27

2013 年 9 月 17 日下午 12:26:20 TestAsync doGet INFO:发布请求:27

2013 年 9 月 17 日下午 12:26:20 TestAsync$1 运行信息:处理请求:31

2013 年 9 月 17 日下午 12:26:25 TestAsync$1 运行信息:已处理请求:31

4

2 回答 2

1

我相信这取决于在 Tomcat 中使用 BIO 连接器。这是 Tomcat 安装中的默认连接器。BIO 连接器阻止读取每个请求,直到写入响应,并且在池中使用单个线程,您可以看到您描述的行为。

如果将 增加到maxThreads1 以上,您将看到其他线程接收传入请求,但连接器仍会阻止新连接,直到现有线程空闲为止。要移动到您想要的模型(当您想将处理委托给另一个时释放的单个请求线程),您需要切换到不阻塞的连接器(NIO 或 APR/Native)。您还可能需要增加线程池的大小(这实际上取决于请求处理线程是否只执行一项工作以及它是否过载)。

于 2013-09-17T18:18:21.510 回答
0

您应该使用此处所述的 NIO 连接器和执行程序池。

如果您没有真正充分的理由;没有理由用前面的一条线来限制你的自我。请查看我提供的网址。

于 2013-09-24T07:16:59.747 回答