Tomcat7:异步Servlet无法正常工作

时间:2013-09-17 17:56:35

标签: servlets tomcat7

我已将Tomcat7配置为具有单个连接器线程,该线程将作业发布到后台线程池,后者以异步方式完成请求。每个请求都有1秒的延迟。我的测试(JMeter)旋转5个线程并同时发出5个请求。我期待单连接器线程立即处理5个请求中的每一个。相反,它正在等待上一个任务(在bg线程上运行)完成,然后再为下一个任务服务。

为了澄清,我的配置试图模仿Node.js和Tornado等“单线程”异步服务器的线程架构。

连接器:

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

的Servlet

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

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

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

2013年9月17日下午12:26:05 TestAsync $ 1运行INFO:已处理的请求: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 PM TestAsync $ 1运行INFO:处理请求:28

2013年9月17日下午12:26:10 TestAsync $ 1运行INFO:已处理的请求: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运行INFO:处理请求:29

2013年9月17日下午12:26:15 TestAsync $ 1运行INFO:已处理的请求: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运行INFO:处理请求:30

2013年9月17日下午12:26:20 TestAsync $ 1运行INFO:已处理的请求: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运行INFO:处理请求:31

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

2 个答案:

答案 0 :(得分:1)

我认为这取决于在Tomcat中使用BIO连接器。这是Tomcat安装中的默认连接器。 BIO connector blocks to read every request until the response is written,并且池中有一个线程,您可以看到您描述的行为。

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

答案 1 :(得分:0)

您应该按照here所述使用NIO连接器和执行程序池。

如果你没有充分的理由;没有理由在前面用一个线程来限制你的自我。请参阅我提供的网址。

相关问题