Java Servlet3.0异步处理问题
通过本篇文章主要给大家讲解了在JAVA开发中Servlet3.0异步处理遇到的问题以及处理办法,以下是具体内容: Servlet 3.0 开始提供了AsyncContext用来支持异步处理请求,那么异步处理请求到底能够带来哪些好处? Web容器一般来说处理请求的方式是:为每个request分配一个thread。我们都知道thread的创建不是没有代价的,Web容器的thread pool都是有上限的。 但是这样依然有一个问题,考虑以下场景: 有一个web容器,线程池大小200。有一个web app,它有两个servlet,Servlet-A处理单个请求的时间是10s,Servlet-B处理单个请求的时间是1s。 看到问题了没有,因为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来处理AsyncContext.start()的。 这也就是说,我们原本是想释放HTTP thread的,但实际上并没有,因为有HTTP thread依然被用作Worker thread,只不过这个thread和接收请求的HTTP thread不是同一个而已。 这个结论我们也可以通过AsyncServlet1和SyncServlet的Jmeter benchmark看出来,两者的throughput结果差不多。启动方法:启动Main,然后利用Jmeter启动benchmark.jmx(Tomcat默认配置下HTTP thread pool=200)。 使用ExecutorService 前面看到了Tomcat并没有单独维护Worker thread pool,那么我们就得自己想办法搞一个,见AsyncServlet2,它使用了一个带Thread pool的ExecutorService来处理AsyncContext。 其他方式 所以对于AsyncContext的使用并没有固定的方式,你可以根据实际需要去采用不同的方式来处理,为此你需要一点Java concurrent programming的知识。 对于性能的误解 AsyncContext的目的并不是为了提高性能,也并不直接提供性能提升,它提供了把HTTP thread和Worker thread解藕的机制,从而提高Web容器的响应能力。 不过AsyncContext在某些时候的确能够提高性能,但这个取决于你的代码是怎么写的。 相反,如果当Worker thread的数量<=HTTP thread数量的时候,那么就不会得到性能提升,因为此时处理请求的瓶颈在Worker thread。 一定不要认为Worker thread pool必须比HTTP thread pool大,理由如下: 两者职责不同,一个是Web容器用来接收外来请求,一个是处理业务逻辑 thread的创建是有代价的,如果HTTP thread pool已经很大了再搞一个更大的Worker thread pool反而会造成过多的Context switch和内存开销 AsyncContext的目的是将HTTP thread释放出来,避免被操作长期占用进而导致Web容器无法响应 所以在更多时候,Worker thread pool不会很大,而且会根据不同业务构建不同的Worker thread pool。 比如:Web容器thread pool大小200,一个慢速Servlet的Worker thread pool大小10,这样一来,无论有多少请求到慢速操作,它都不会将HTTP thread占满导致其他请求无法处理。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- jsp、struts、spring、mybatis实现前端页面功能模块化拆分的
- JDK环境变量配置的具体操作步骤
- java – 引用具有指定参数的方法(用于lambda)
- JSP Response.addIntHeade()方法:添加对应名称的int属性
- java – Spring安全性OAuth2刷新令牌 – IllegalStateExcep
- 更改Java Swing Component Focus指示器的颜色
- java – 如何从Web服务方法访问WebContent文件夹
- java – 确定任何webapp和独立应用程序所需的-Xmx和-Xms的
- Java – 检查String的ArrayList是否按字母顺序排列
- Java 类的热替换---转载