ServletRequest startAsync()的有用性有限

前段时间我遇到了Servlet 3.0中AsyncContext.start(…)的目的是什么? 题。 引用上述方法的Javadoc :
使容器调度线程(可能从托管线程池中)运行指定的Runnable
提醒大家, AsyncContext是Servlet 3.0规范中定义的一种标准方式,用于异步处理HTTP请求。 基本上,HTTP请求不再绑定到HTTP线程,这使我们以后可以使用更少的线程来处理它。 事实证明,该规范提供了一个API,用于处理其他不同线程池中的异步线程。 首先,我们将了解该功能在Tomcat和Jetty中是如何被完全破坏和无用的,然后我们将讨论为什么该功能的用途普遍存在疑问。
我们的测试servlet只会在给定的时间内睡眠。 在正常情况下,这是可伸缩性的杀手,因为即使休眠的Servlet不会消耗CPU,但是与该特定请求绑定的休眠的HTTP线程也会消耗内存,并且其他传入请求都无法使用该线程。 在我们的测试设置中,我将HTTP工作线程的数量限制为10个,这意味着即使应用程序本身几乎完全处于空闲状态,也只有10个并发请求完全阻塞了该应用程序(外部没有响应)。 显然,睡眠是可扩展性的敌人。
@WebServlet(urlPatterns = Array("/*"))
class SlowServlet extends HttpServlet with Logging {protected override def doGet(req: HttpServletRequest, resp: HttpServletResponse) {logger.info("Request received")val sleepParam = Option(req.getParameter("sleep")) map {_.toLong}TimeUnit.MILLISECONDS.sleep(sleepParam getOrElse 10)logger.info("Request done")}
}
对这段代码进行基准测试可以发现,只要并发连接数低于HTTP线程数,平均响应时间就会接近sleep参数。 毫不奇怪,一旦我们超过HTTP线程数,响应时间就会开始增加。 第十一连接必须等待任何其他请求完成并释放工作线程。 当并发级别超过100时,Tomcat开始断开连接-太多的客户端已排队。
那么花哨的AsyncContext.start()方法又如何呢(不要与ServletRequest.startAsync()混淆)? 根据JavaDoc,我可以提交任何Runnable ,并且容器将使用某些托管线程池来处理它。 这将在一定程度上有所帮助,因为我不再阻止HTTP工作线程(但仍使用servlet容器中某个位置的另一个线程)。 快速切换到异步servlet:
@WebServlet(urlPatterns = Array("/*"), asyncSupported = true)
class SlowServlet extends HttpServlet with Logging {protected override def doGet(req: HttpServletRequest, resp: HttpServletResponse) {logger.info("Request received")val asyncContext = req.startAsync()asyncContext.setTimeout(TimeUnit.MINUTES.toMillis(10))asyncContext.start(new Runnable() {def run() {logger.info("Handling request")val sleepParam = Option(req.getParameter("sleep")) map {_.toLong}TimeUnit.MILLISECONDS.sleep(sleepParam getOrElse 10)logger.info("Request done")asyncContext.complete()}})}
}
我们首先启用异步处理,然后简单地将sleep()移至Runnable并希望移至其他线程池中,从而释放HTTP线程池。 快速压力测试揭示了一些出乎意料的结果(此处:响应时间与并发连接数):
猜猜是什么,响应时间与根本没有异步支持的响应时间完全相同 (!)。仔细检查后,我发现当调用AsyncContext.start() ,Tomcat将给定的任务提交回……HTTP工作线程池,即用于所有HTTP请求! 基本上,这意味着我们发布了一个HTTP线程,只是为了在稍后的一毫秒内使用(甚至可能是同一线程)。 在Tomcat中调用AsyncContext.start()绝对没有好处。 我不知道这是错误还是功能。 一方面,这显然不是API设计人员想要的。 假定servlet容器管理单独的独立线程池,因此HTTP工作线程池仍然可用。 我的意思是,异步处理的全部目的是逃避HTTP池。 Tomcat假装将我们的工作委托给另一个线程,而它仍然使用原始的工作线程池。
那么,为什么我认为这是一个功能? 因为Jetty以完全相同的方式“破坏”了……无论它是按设计运行还是仅是不良的API实现,因此在Tomcat和Jetty中使用AsyncContext.start()都是没有意义的,并且只会不必要地使代码复杂化。 它不会给您任何好处,该应用程序在高负载下的工作原理完全相同,就好像根本没有异步逻辑一样。
但是,如何在正确的实现(例如IBM WAS)上使用此API功能呢? 更好,但API仍然没有像在扩展性方面给我们带来太多好处。 再次说明:异步处理的全部要点是能够将HTTP请求与基础线程分离,最好通过使用同一线程处理多个连接来实现。
AsyncContext.start()将在单独的线程池中运行提供的Runnable 。 您的应用程序仍然可以响应,可以处理普通的请求,而您决定异步处理的长期运行的请求则在单独的线程池中处理。 更好的是,不幸的是线程池和每个连接线程的成语仍然是瓶颈。 对于JVM,启动什么类型的线程都没有关系–它们仍然占用内存。 因此,我们不再阻塞HTTP工作线程,但就我们可以支持的并发长期运行任务而言,我们的应用程序具有更大的可伸缩性。
在这个带有休眠servlet的简单,不现实的示例中,实际上,我们可以使用Servlet 3.0异步支持(只有一个额外的线程)并且不使用AsyncContext.start()来支持数千个并发(等待)连接。 你知道如何? 提示: ScheduledExecutorService
后记:斯卡拉善良
我差点忘了。 尽管示例是用Scala编写的,但我还没有使用任何出色的语言功能。 这是一个:隐式转换。 使它在您的范围内可用:
implicit def blockToRunnable[T](block: => T) = new Runnable {def run() {block}
}
突然之间,您可以使用代码块来代替手动和显式实例化Runnable
asyncContext start {logger.info("Handling request")val sleepParam = Option(req.getParameter("sleep")) map { _.toLong}TimeUnit.MILLISECONDS.sleep(sleepParam getOrElse 10)logger.info("Request done")asyncContext.complete()
}
甜!
参考: Javax 和 servlet 社区的 JCG合作伙伴 Tomasz Nurkiewicz提供的javax.servlet.ServletRequest.startAsync()用途有限 。

翻译自: https://www.javacodegeeks.com/2012/05/servletrequest-startasync-limited.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372904.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql所支持的比较运算符_mysql比较运算符有哪些?Mysql比较运算符详解

比较运算符可用于比较数字和字符串。今天发一篇Mysql比较运算符详解,希望对初学者有所帮助,虽然现在流行NoSQL,但是MYSQL还是很有用的,数字作为浮点值进行比较,字符串以不区为例进行比较,运算符用于比较表达…

Http Invoker的Spring Remoting支持

Spring HTTP Invoker是Java到Java远程处理的重要解决方案。 该技术使用标准的Java序列化机制通过HTTP公开服务,并且可以被视为替代解决方案,而不是Hessian和Burlap中的自定义序列化。 而且,它仅由Spring提供,因此客户端和服务器应…

学习后缀自动机想法

小序:学习后缀自动机是要有耐心的,clj的论文自己看真心酸爽!(还是自己太弱,ls,oyzx好劲啊,狂膜不止) 刚刚在写博客之前又看了篇论文,终于看懂了,好开心 正文&…

mysql 分组top_MySQL:如何查询出每个分组中的 top n 条记录?

问题描述需求:查询出每月 order_amount(订单金额) 排行前3的记录。例如对于2019-02,查询结果中就应该是这3条:解决方法MySQL 5.7 和 MySQL 8.0 有不同的处理方法。1. MySQL 5.7我们先写一个查询语句。根据 order_date 中的年、月,…

利用jenkins的api来完成相关工作流程的自动化

[本文出自天外归云的博客园] 背景 1. 实际工作中涉及到安卓客户端方面的测试,外推或运营部门经常会有很多的渠道,而每个渠道都对应着一个app的下载包,这些渠道都记录在安卓项目下的一个渠道列表文件中。外推或运营部门经常会有新的渠道产生&a…

拥有成本分析:Oracle WebLogic Server与JBoss

Crimson Consulting Group 撰写的非常有趣的白皮书 ,比较了Weblogic和JBoss之间的拥有成本 。 尽管JBoss是免费的,但该白皮书却严肃地宣称,从长远来看,Weblogic更便宜。 尽管此研究是由Oracle赞助的,但它看起来非常严肃…

mysql limit 分页 0_Mysql分页之limit用法与limit优化

Mysql limit分页语句用法与Oracle和MS SqlServer相比,mysql的分页方法简单的让人想哭。--语法:SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset--举例:select * from table limit 5; --返回前5行select * from table limit 0…

linux每天一小步---sed命令详解

1 命令功能 sed是一个相当强大的文件处理编辑工具,sed用来替换,删除,更新文件中的内容。sed以文本行为单位进行处理,一次处理一行内容。首先sed吧当前处理的行存储在临时的缓冲区中(称为模式空间pattern space&#xf…

mysql trace工具_100% 展示 MySQL 语句执行的神器-Optimizer Trace

在上一篇文章《用Explain 命令分析 MySQL 的 SQL 执行》中,我们讲解了 Explain 命令的详细使用。但是它只能展示 SQL 语句的执行计划,无法展示为什么一些其他的执行计划未被选择,比如说明明有索引,但是为什么查询时未使用索引等。…

006_过滤器

过滤器 过滤器(Filter)把附加逻辑注入到MVC框的请求处理,实现了交叉关注。所谓交叉关注(Cross-Cutting Concerns),是指可以用于整个应用程序,而又不适合放置在某个局部位置的功能,否…

Android_项目文件结构目录分析

android项目文件结构目录分析 在此我们新建了一个helloworld的项目,先看一些目录结构: 这么多的文件夹和文件中,我们重点关注是res目录、src目录、AndroidManifest.xml文件: 一、res目录主要是用来存放android项目的各种资源文件&…

实体 联系 模型mysql_数据库系统概念读书笔记――实体-联系模型_MySQL

bitsCN.com数据库系统概念读书笔记——实体-联系模型前言为了重新回顾我写的消息系统架构,我需要重新读一下数据库系统概念的前三章,这里简单的做一个笔记,方便自己回顾基本概念实体-联系(E-R)数据模型基于对现实世界的这样一种认识&#xff…

使用Twitter Bootstrap,WebSocket,Akka和OpenLayers玩(2.0)

原始帖子可以在ekito网站上找到。 对于我们的一位客户,我们需要显示一张具有实时更新的车辆位置的地图。 因此,我开始使用Play制作原型! 框架及其最新发布的版本2.0,使用Java API。 我从Play的网络聊天室开始! 2.0个样…

mysql 5.6.23免安装_mysql5.6.23免安装配置

1.官网下载,并解压2.环境变量,path下,追加mysql的bin路径D:\Program Files\mysql\bin;3.mysql目录下的my-default.ini重命名为my.ini,并添加下面的代码basedirD:/Program Files/mysql #mysql路径datadirD:/Program Files/mysql/d…

在Intellij IDEA中运行Vaadin应用

在本文中,我将向您展示如何使用Intellij IDEA运行vaadin应用程序。 Vaadin提供了一些用于Eclipse和Netbeans的插件。 但是对于Intellij IDEA来说,还没有插件。 但是部署vaadin应用程序比其他两个IDE容易。 这是您要遵循的步骤。 1.首先创建一个新项目&am…

mysql主从数据库

Mysql主从配置,实现读写分离 大型网站为了软解大量的并发访问,除了在网站实现分布式负载均衡,远远不够。到了数据业务层、数据访问层,如果还是传统的数据结构,或者只是单单靠一台服务器扛,如此多的数据库连…

Java EE 6示例– Galleria –第3部分

关于Galleria示例的先前文章( 第1 部分 | 第2部分 | 第3部分 | 第4部分 )指导您完成基础知识以及对GlassFish和WebLogic的初始部署。 从今天开始,我尝试在其中添加一些企业级功能,因为我发现他们在自己的项目中提出了很多要求。 我…

在 Windows 上测试 Redis Cluster的集群填坑笔记

redis 集群实现的原理请参考http://www.tuicool.com/articles/VvIZje集群环境至少需要3个节点。推荐使用6个节点配置,即3个主节点,3个从节点。新建6个文件夹 分别是 7000/7001/7002/7003/7004/7005将redis.windows.conf 复制一份然后修改配置文件中的下面…

拓扑排序最长链-P3119 [USACO15JAN]草鉴定Grass Cownoisseur

https://www.luogu.org/problem/show?pid3119 本来我是来练习tarjan的,结果tarjan部分直接copy了,反而拓扑排序部分想了好久; 这道题SZB大神两次就AC; 但我等到AC,写好题解就只能洗洗睡了; 唉~ 差距怎…