异步Servlet
Servlet默认情况下都是同步的,但是Servlet可以进行异步的调用。
/**
* Servlet implementation class MainServlet
*/
@WebServlet(value = "/MainServlet", asyncSupported = true)
public class AsynServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* Default constructor.
*/
public AsynServlet() {
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long startTime = System.currentTimeMillis();
System.out.println("DoGet Start ThreadName = " + Thread.currentThread().getName() + " ThreadId = "
+ Thread.currentThread().getId());
AsyncContext asyncCtx = request.startAsync();
asyncCtx.setTimeout(9000);
ExecutorService executorService = (ExecutorService) request.getServletContext().getAttribute("executorService");
executorService.execute(() -> {
try {
System.out.println();
Thread.sleep(5000);
asyncCtx.complete();
} catch (Exception e) {
e.printStackTrace();
}
});
long endTime = System.currentTimeMillis();
System.out.println("doGet End ThreadName = " + Thread.currentThread().getName() + " ThreadId = "
+ Thread.currentThread().getId() + " Time = " + (endTime - startTime) + " ms.");
request.getRequestDispatcher("/AnotherServlet").forward(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
异步调用代表当前线程(Tomcat容器线程)到达异步调用处 request.startAsync() 时,会释放掉自己,然后委托另一个业务线程(这里是新建的线程池里的一个业务线程)来完成业务处理,然后调用异步请求的 complete 方法完成异步任务,而 Tomcat 容器线程在异步任务正在执行的过程中会保存起当前任务的状态,一边执行其他的请求,一边等待 complete 的调用,一旦 complete 调用,则异步的请求完成,由原来的 Tomcat 线程完成清理工作,并返回客户端。
这种模式下,Tomcat 容器线程可以在耗时操作的情况下得到快速的释放并处理新请求,缓解容器线程被占满的情况。
对于 Long Pool 模型,可以有两种请求模式:
一种是客户端不断的轮询,根据每一次请求返回的状态进行判断渲染页面,这种方式需要选定合适的轮询周期,否则会导致服务器端计算压力巨大。
另一种是使用长连接,由服务器 hold 住连接,等待一个事件发生之后让长连接返回客户端,客户端渲染页面,之后客户端在次发起一个长连接,这种方式需要消耗掉服务器大量的资源,需要设置合适的在次连接延迟和连接超时时间。
时间: 2024-12-05 11:37:47