Java Servlet 3.0 异步处理问题 Java Servlet 3.0 异步处理问题主要介绍了 Java 中 Servlet 3.0 异步处理的原理以及遇到的问题分析。Servlet 3.0 开始提供了 AsyncContext 用来支持异步处理请求,那么异步处理请求到底能够带来哪些好处? 在传统的 Web 容器中,处理请求的方式是为每个 request 分配一个 thread。这意味着 thread 的创建不是没有代价的,Web 容器的 thread pool 都是有上限的。那么一个很容易预见的问题就是,在高负载情况下,thread pool 都被占着了,那么后续的 request 就只能等待,如果运气不好客户端会报等待超时的错误。 在 AsyncContext 出现之前,解决这个问题的唯一办法就是扩充 Web 容器的 thread pool。但是这样依然有一个问题,考虑以下场景:有一个 web 容器,线程池大小 200。有一个 web app,它有两个 servlet,Servlet-A 处理单个请求的时间是 10s,Servlet-B 处理单个请求的时间是 1s。现在遇到了高负载,有超过 200 个 request 到 Servlet-A,如果这个时候请求 Servlet-B 就会等待,因为所有 HTTP thread 都已经被 Servlet-A 占用了。 这个时候工程师发现了问题,扩展了线程池大小到 400,但是负载依然持续走高,现在有 400 个 request 到 Servlet-A,Servlet-B 依然无法响应。看到问题了没有,因为 HTTP thread 和 Worker thread 耦合在了一起,所以导致了当大量 request 到一个耗时操作时,就会将 HTTP thread 占满,导致整个 Web 容器就会无法响应。 但是如果使用 AsyncContext,我们就可以将耗时的操作交给另一个 thread 去做,这样 HTTP thread 就被释放出来了,可以去处理其他请求了。注意,只有使用 AsyncContext 才能够达到上面所讲的效果,如果直接 new Thread() 或者类似的方式的,HTTP thread 并不会归还到容器。 下面是一个官方的例子: @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(); } }); } } 但是,在这个官方例子里,每个 HTTP thread 都会开启另一个 Worker thread 来处理请求,然后把 HTTP thread 就归还给 Web 容器。但是,看 AsyncContext.start() 方法的 javadoc:Causes the container to dispatch a thread, possibly from a managed thread pool, to run the specified Runnable。实际上这里并没有规定 Worker thread到底从哪里来,也许是 HTTP thread pool 之外的另一个 thread pool?还是说就是 HTTP thread pool? The Limited Usefulness of AsyncContext.start() 文章里写道:不同的 Web 容器对此有不同的实现,不过 Tomcat 实际上是利用 HTTP thread pool 中的 thread 来实现异步处理的。 AsyncContext 可以解决传统的 Web 容器中的 thread 复用问题,使得 Web 容器能够更好地处理高负载的情况。但是,在使用 AsyncContext 时,我们需要注意到 Worker thread 的来源,以避免出现新的问题。
- 粉丝: 4
- 资源: 967
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助