Tomcat 7异步处理

我想知道Tomcat 7如何实现异步处理。我了解到请求线程会立即返回,从而允许请求线程立即侦听新请求并对其进行响应。

如何处理“异步”请求?是否有一个单独的线程池来处理异步请求?我假设使用性能类似java.nio.Selector的东西来处理阻塞IO。那么阻塞CPU计算的线程呢?

回答:

您正在混淆不同的概念。您必须区分:

  1. ;一个使您能够将传入的Servlet请求与Web容器线程池分离的API。它不会动态创建任何线程。界面的用户可以实施适当的多线程解决方案。它与非阻塞IO不相关。
  2. ; 提供了一种获取和管理Web容器中的线程的机制。对于 异步请求处理, 您有2个选择。您可以定义自己的文件ExecutorService并使用它来进一步处理请求,也可以创建新文件RunnableAsyncContext通过调用将其提交给获得的文件AsyncContext.start()。对于Tomcat,后一种方法使用中定义的Tomcat线程池server.xml
  3. ;尽管它也是 异步的 ,但情况有所不同。它涉及非阻塞IO操作,例如磁盘或网络IO。如果要为HTTP请求处理启用NIO,请查看Tomcat的文档。


下面的示例概述了它 如何 工作。它仅使用一个线程进行工作者作业。如果您从2个不同的浏览器并行运行它,则输出如下所示(我使用自定义记录器):

   DATE                         THREAD_ID  LEVEL      MESSAGE

2011-09-03 11:51:22.198 +0200 26 I: >doGet: chrome

2011-09-03 11:51:22.204 +0200 26 I: <doGet: chrome

2011-09-03 11:51:22.204 +0200 28 I: >run: chrome

2011-09-03 11:51:27.908 +0200 29 I: >doGet: firefox

2011-09-03 11:51:27.908 +0200 29 I: <doGet: firefox

2011-09-03 11:51:32.227 +0200 28 I: <run: chrome

2011-09-03 11:51:32.228 +0200 28 I: >run: firefox

2011-09-03 11:51:42.244 +0200 28 I: <run: firefox

您会看到doGet方法立即完成,而工作程序仍在运行。2个测试请求:http://localhost:8080/pc/TestServlet?name=chromehttp://localhost:8080/pc/TestServlet?name=firefox

@WebServlet(asyncSupported = true, value = "/TestServlet", loadOnStartup = 1)

public class TestServlet extends HttpServlet {

private static final Logger LOG = Logger.getLogger(TestServlet.class.getName());

private static final long serialVersionUID = 1L;

private static final int NUM_WORKER_THREADS = 1;

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 String name = request.getParameter("name");

LOG.info(">doGet: " + name);

AsyncContext ac = request.startAsync(); // obtain async context

ac.setTimeout(0); // test only, no timeout

/* Create a worker */

Runnable worker = new TestWorker(name, ac);

/* use your own executor service to execute a worker thread (TestWorker) */

this.executorService.execute(worker);

/* OR delegate to the container */

// ac.start(worker);

LOG.info("<doGet: " + name);

}

}

public class TestWorker implements Runnable {

private static final Logger LOG = Logger.getLogger(TestWorker.class.getName());

private final String name;

private final AsyncContext context;

private final Date queued;

public TestWorker(String name, AsyncContext context) {

this.name = name;

this.context = context;

this.queued = new Date(System.currentTimeMillis());

}

@Override

public void run() {

LOG.info(">run: " + name);

/* do some work for 10 sec */

for (int i = 0; i < 100; i++) {

try {

Thread.sleep(100);

} catch (InterruptedException e) {

throw new RuntimeException(e);

}

}

ServletResponse response = this.context.getResponse();

response.setContentType("text/plain");

try {

PrintWriter out = response.getWriter();

out.println("Name:\t\t" + this.name);

out.println("Queued:\t\t" + this.queued);

out.println("End:\t\t" + new Date(System.currentTimeMillis()));

out.println("Thread:\t\t" + Thread.currentThread().getId());

out.flush();

} catch (IOException e) {

throw new RuntimeException(e);

}

this.context.complete();

LOG.info("<run: " + name);

}

}

以上是 Tomcat 7异步处理 的全部内容, 来源链接: utcz.com/qa/397488.html

回到顶部