27 | 新特性:Tomcat如何支持异步Servlet?
Posted IT编程学习栈
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了27 | 新特性:Tomcat如何支持异步Servlet?相关的知识,希望对你有一定的参考价值。
通过专栏前面的学习我们知道,当一个新的请求到达时,Tomcat 和 Jetty 会从线程池里拿出一个线程来处理请求,这个线程会调用你的 Web 应用,Web 应用在处理请求的过程中,Tomcat 线程会一直阻塞,直到 Web 应用处理完毕才能再输出响应,最后 Tomcat 才回收这个线程。
我们来思考这样一个问题,假如你的 Web 应用需要较长的时间来处理请求(比如数据库查询或者等待下游的服务调用返回),那么 Tomcat 线程一直不回收,会占用系统资源,在极端情况下会导致“线程饥饿”,也就是说 Tomcat 和 Jetty 没有更多的线程来处理新的请求。
那该如何解决这个问题呢?方案是 Servlet 3.0 中引入的异步 Servlet。主要是在 Web 应用里启动一个单独的线程来执行这些比较耗时的请求,而 Tomcat 线程立即返回,不再等待 Web 应用将请求处理完,这样 Tomcat 线程可以立即被回收到线程池,用来响应其他请求,降低了系统的资源消耗,同时还能提高系统的吞吐量。
今天我们就来学习一下如何开发一个异步 Servlet,以及异步 Servlet 的工作原理,也就是 Tomcat 是如何支持异步 Servlet 的,让你彻底理解它的来龙去脉。
异步 Servlet 示例
我们先通过一个简单的示例来了解一下异步 Servlet 的实现。
@WebServlet(urlPatterns = {"/async"}, asyncSupported = true)
public class AsyncServlet extends HttpServlet {
//Web 应用线程池,用来处理异步 Servlet
ExecutorService executor = Executors.newSingleThreadExecutor();
public void service(HttpServletRequest req, HttpServletResponse resp) {
//1. 调用 startAsync 或者异步上下文
final AsyncContext ctx = req.startAsync();
// 用线程池来执行耗时操作
executor.execute(new Runnable() {
@Override
public void run() {
// 在这里做耗时的操作
try {
ctx.getResponse().getWriter().println("Handling Async Servlet");
} catch (IOException e) {}
//3. 异步 Servlet 处理完了调用异步上下文的 complete 方法
ctx.complete();
}
});
}
}
复制代码以上是关于27 | 新特性:Tomcat如何支持异步Servlet?的主要内容,如果未能解决你的问题,请参考以下文章
Day694.Tomcat如何支持异步Servlet -深入拆解 Tomcat & Jetty