ServletRequest startAsync()的用途有限

前段时间我遇到了Servlet 3.0中AsyncContext.start(…)的目的是什么? 题。 引用上述方法的Javadoc :
使容器调度线程(可能从托管线程池中)运行指定的Runnable
提醒大家, AsyncContext是Servlet 3.0规范中定义的一种标准方式,用于异步处理HTTP请求。 基本上,HTTP请求不再绑定到HTTP线程,这使我们以后可以使用更少的线程来处理它。 事实证明,该规范提供了一个API,用于处理不同线程池中的异步线程。 首先,我们将了解该功能在Tomcat和Jetty中是如何被完全破坏和无用的,然后我们将讨论为什么该功能的用途普遍存在疑问。
我们的测试servlet只会在给定的时间内睡眠。 在正常情况下,这是可伸缩性的杀手,因为即使Hibernate的Servlet不会占用CPU,但是与该特定请求绑定的Hibernate的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工作线程,但是就我们可以支持的并发长期运行任务而言,我们的应用程序具有更大的可伸缩性。
在这个带有Hibernateservlet的简单,不现实的示例中,实际上,我们可以使用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/355704.shtml

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

相关文章

python3.7下载tensorflow_【AI初体验】在anaconda中python3.7版本安装Tensorflow 与 Keras来玩玩...

哈啰,大家好, 单纯分享自己摸索学习AI的过程, 在自己的文章【Python 超入门】(1) 心原一马从零开始带你学程序中, 记录了安装撰写python的工具-anaconda 的方法, 当时安装的版本是python3.7版, 但是据说目前…

古巴平台上的通用过滤器–类固醇上的excel过滤器

正如我上次承诺的那样,我计划浏览该平台的某些功能,这些功能我认为非常有价值。 所以我将在这里做一些系列。 从明显的用户界面,过滤,安全性到一些高级功能(如Web Portal,可扩展性,审核&#xf…

基准测试:Java 8 Lambda和流如何使您的代码慢5倍

与长期的实现相比,Java 8 lambda和流的性能如何? Lambda表达式和流在Java 8中受到了热烈的欢迎。这些是迄今为止很激动人心的功能,很长一段时间以来,它们就已经应用到Java中了。 新的语言功能使我们可以在代码中采用更具功能性的…

ssm框架逻辑删除mysql_MybatisPlus--CRUD接口及主键增长策略、自动填充、乐观锁更新数据...

目录一、insert1、插入操作2、主键策略二、update1、根据Id更新操作2、自动填充3、乐观锁三、select1、根据id查询记录2、通过多个id批量查询3、简单的条件查询4、分页四、delete1、根据id删除记录2、批量删除3、简单的条件查询删除4、逻辑删除一、insert1、插入操作RunWith(Sp…

python对英语的要求_学python需要英语基础吗

在很多人的眼里,学习编程需要英语基础,因为程序代码全是英文字母,如果没有英语基础可能很难学懂编程。程序代码是英文确实没有错,但是也不是必须得懂英语,因为计算机程序有自己语言,并不是我们生活中的英语…

python找不到csv文件_Python如何读取csv文件

逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列&…

python cv2模块imshow_Python-OpenCV:cv2.imread(),cv2.imshow(),cv2.imwrite()

一、需要工具本机使用python 2.7.10下调试代码均通过,一下学习需要有一定的代码阅读能力,一下学习只介绍函数方法:Python 作为一种高效简洁的直译式语言非常适合我们用来解决日常工作的问题。而且它简单易学,初学者几个小时就可以…

2016年将是Java终于拥有窗口函数的那一年!

你没听错。 到目前为止,出色的窗口功能是SQL独有的功能。 即使是复杂的函数式编程语言似乎也缺少这种漂亮的功能(如果我记错了,请纠正我,Haskell伙计们)。 我们撰写了许多有关窗口函数的博客文章,并在诸如…

android 仿京东地址选择_Android 开发:仿美团地址选择

最近做了这个功能,分享一下,用的是百度地图api,和美团外卖的地址选择界面差不多,也就是可以搜索或者滑动地图展示地址列表给用户选择,看下效果图先。文章重点展示地图并定位到“我”的位置 滑动地图获取周边poi(逆地理…

ps还原上一步快捷键_ps还原上一步快捷键_photoshop恢复上一步操作的快捷键是什么...

满意答案simonsinxer推荐于 2017.09.01采纳率:53% 等级:11已帮助:63469人还原/重做前一步操作 【Ctrl】【Z】其他一些快捷键:还原两步以上操作 【Ctrl】【Alt】【Z】重做两步以上操作 【Ctrl】【Shift】【Z】剪切选取的图像或路…

python中排序从小到大_从Python看排序:冒泡排序

冒泡排序在排序算法中是最简单的一种,它通过多次遍历列表,将最大的元素冒泡到列表的头部或尾部。我们通过对四张扑克牌(花色相同)以从小到大的方式进行排序来演示该算法的工作原理。首先将扑克牌面朝上放在桌上,如下图…

c语言三个数从小到大排序/输出_我的c语言笔记(三)

int表达式这个表达式存在的目的在于将表达式转为整数。比如:float a9999.9999;int b;b(int)(a/1000);就可以得到9啦,别忘了套上固定格式哦~然后我们接下来一起来做一道很重要的题哦,反复练习,可以顺利拿下同…

java虚拟_Java虚拟机(JVM)工作原理

虽然本教程的内容为 x86 处理器的原生汇编语言,但是了解其他机器架构如何工作也是有益的。JVM 是基于堆栈机器的首选示例。JVM 用堆栈实现数据传送、算术运算、比较和分支操作,而不是用寄存器来保存操作数(如同 x86 一样)。数据结构,让它们协…

java string blob_java String类型转换为Blob类型

展开全部这个是mysql下存取blob字段的一个很简单的类,跟据自己的需要32313133353236313431303231363533e4b893e5b19e31333332623936改改就行了/*** Title: BlobPros.java* Project: test* Description: 把图片存入mysql中的blob字段,并取出* Call Module…

Neo4j:特定关系与一般关系+属性

为了在Neo4j查询中获得最佳的遍历速度,我们应该使关系类型尽可能具体 。 让我们看一下几周前我在Skillsmatter上发表的“ 建模建议引擎建模 ”演讲中的一个例子。 我需要决定如何为成员和事件之间的“ RSVP”关系建模。 一个人可以对事件表示“是”或“否”&#…

java 按位置格式化字符串_Java字符串格式化,{}占位符根据名字替换实例

我就废话不多说了,大家还是直接看代码吧~import java.beans.PropertyDescriptor;import java.lang.reflect.Method;import java.util.HashMap;import java.util.Map;import java.util.regex.Matcher;import java.util.regex.Pattern;public class StringFormatUtil …

Apache Drill 1.4性能增强的简要概述

今天,我们很高兴宣布Apache Drill 1.4现已在MapR发行版中可用。 钻1.4是MAPR生产就绪和支持的版本,可以从下载这里 ,找到1.4版本说明这里 。 Drill 1.4以其高度灵活和可扩展的体系结构为基础,带来了多种新功能以及对查询性能的增…

【01背包】洛谷P1282多米诺骨牌

题目描述 多米诺骨牌有上下2个方块组成,每个方块中有1~6个点。现有排成行的 上方块中点数之和记为S1,下方块中点数之和记为S2,它们的差为|S1-S2|。例如在图8-1中,S161119,S2153211,|S1-S2|2。每个多米诺骨牌…

java geolitecity_GeoLite2 Java根据IP获得城市、经纬度

之前我们介绍过通过 qqwry.dat 根据IP获得所属城市和运营商信息。但是这个 qqwry.dat 已经太久没更新了,数据有些不准确,而且现在我们有个需求就是想获取某个IP所在的经纬度。这里我们可以使用 GeoLite2,这个是国外开源的一个库,需…

计算机专业英语第二版张强华翻译_计算机语言发展的三个阶段,机器语言、汇编语言与高级语言...

在如今信息发达的时代,科技日新月异,计算机和Internet网络的发展也成为人们日常生活的重要部分。学习一两门计算机编程语言也如当初学习英文一样的火热,随着人工智能AI和云计算的不断发展,Python语言和Scala语言已经成为这两个领域…