应用服务器的web容器一般会为每一个请求分配一个服务线程。在重负载的场景下,容器须要大量的线程去服务全部客户端请求。服务可扩展性的限制包括内存不足或者耗尽容器线程。建立可扩展web程序,你必须确保没有关联请求的线程是空闲的,因此容器可使用他们处理新请求。
这里有两个关联请求的线程空闲的两个场景:html
这些场景表明限制web程序可扩展性的阻塞操做。异步处理是指给这些阻塞操做分配一个新线程,并把关联请求处理的线程返回给web容器。java
java ee支持servlet和filter的异步处理。若是一个servlet或一个filter处理请求时可能到达一个阻塞操做,它能够把操做分配给一个异步处理上下文而且在不生成响应的状况下将关联请求处理的线程回送给web容器。阻塞操做在不一样线程的异步上下文中执行完成,它能够生成响应或者转发请求到另外一个servlet。
在一个servlet上启用异步处理,设置@WebServlet注解的asyncSupported参数为true,以下:web
@WebServlet(urlPatterns={"/asyncservlet"}, asyncSupported=true) public class AsyncServlet extends HttpServlet { ... }
javax.servlet.AsyncContext类提供在Service方法中执行异步处理所需的功能。得到一个AsyncContext实例,在service方法中调用request对象的startAsync()方法;例如:数据库
public void doGet(HttpServletRequest req, HttpServletResponse resp) { ... AsyncContext acontext = req.startAsync(); ... }
这个调用将请求进入异步模式而且确保响应在退出service方法时每个月被提交。你必须在异步上下文完成阻塞操做时生成响应或者转发到其余servlet中。
AsyncContext类提供的基础功能描述:
方法签名:void start(Runnable run)
描述:容器提供的能提供阻塞操做处理的不一样线程
方法签名:ServletRequest getRequest()
描述:返回用来初始化异步上下文的请求。在上面的例子中,request与service方法中的相同。你能够经过这个方法在异步上下文中从请求中获取参数。
方法签名:ServletResponse getResponse()
描述:返回初始化异步上下文的响应。在上面的例子中,response与service方法中的相同。你能够在异步上下文中,使用这个方法写入阻塞操做的结果到响应中。
方法签名:void complete()
描述:完成异步操做,并关闭与此异步上下文关联的响应。你能够在异步上下文完成写入响应后调用这个操做。
方法签名:void dispatch(String path)
描述:转发请求和响应到给定的路径。在阻塞操做完成后,使用这个方法调用另外一个servlet写出响应。服务器
这个章节示范了怎么使用AsyncContext上下文提供的功能,有以下用例:并发
下面的例子是一个不使用异步处理的常见servlet:异步
@WebServlet(urlPatterns={"/syncservlet"}) public class SyncServlet extends HttpServlet { private MyRemoteResource resource; @Override public void init(ServletConfig config) { resource = MyRemoteResource.create("config1=x,config2=y"); } @Override public void doGet(HttpServletRequest request, HttpServletResponse response) { response.setContentType("text/html;charset=UTF-8"); String param = request.getParameter("param"); String result = resource.process(param); /* ... print to the response ... */ } }
下面的示例是同一个servlet,但使用了异步处理:async
@WebServlet(urlPatterns={"/asyncservlet"}, asyncSupported=true) public class AsyncServlet extends HttpServlet { /* ... Same variables and init method as in SyncServlet ... */ @Override public void doGet(HttpServletRequest request, HttpServletResponse response) { response.setContentType("text/html;charset=UTF-8"); final AsyncContext acontext = request.startAsync(); acontext.start(new Runnable() { public void run() { String param = acontext.getRequest().getParameter("param"); String result = resource.process(param); HttpServletResponse response = acontext.getResponse(); /* ... print to the response ... */ acontext.complete(); } }
AsyncServlet在@WebServlet注解属性中添加asyncSupported=true。其他的差别在service方法中:ide
AsyncServlet的service方法当即返回,同时请求在异步上下文中处理。url