异步servlet
我们日常使用的 SpringMVC,基本上都不是异步 Servlet,而学习 WebFlux,异步 Servlet 是基础,WebFlux。
1.什么是异步 Servlet
先来说说什么是非异步 Servlet。
在 Servlet3.0 之前,Servlet 采用 Thread-Per-Request 的方式处理 Http 请求,即每一次请求都是由某一个线程从头到尾负责处理。
如果一个请求需要进行 IO 操作,比如访问数据库、调用第三方服务接口等,那么其所对应的线程将同步地等待 IO 操作完成, 而 IO 操作是非常慢的,所以此时的线程并不能及时地释放回线程池以供后续使用,如果并发量很大的话,那肯定会造性能问题。
传统的 MVC 框架如 SpringMVC 也无法摆脱 Servlet 的桎梏,原因很简单,他们都是基于 Servlet 来实现的。如 SpringMVC 中大家所熟知的 DispatcherServlet(如果大家对于 SpringMVC 的原理不太理解,可以查看松哥之前的系列文章SpringMVC源码解读系列,20 篇干货完美收官!)。
为了解决这一问题,Servlet3.0 中引入了异步 Servlet,然后在 Servlet3.1 中又引入了非阻塞 IO 来进一步增强异步处理的性能。
在正式开整 WebFlux 之前,我们先来了解下异步 Servlet 的一些基本玩法。
2.版本关系
我们要先看看 Servlet 和 Tomcat 之间的对应关系,毕竟异步 Servlet 这种事,用错了 Tomcat 版本可能就不支持了。
下图来自 Tomcat 官网(http://tomcat.apache.org/whichversion.html):
从上图我们可以看出,Servlet3.0 对应的 Tomcat 版本是 7.0.x,Servlet3.1 对应的 Tomcat 版本是
8.0.x。
换句话说,如果我们要使用异步 Servlet,Tomcat 至少要 7.0 以上的版本;如果你还想体验一把非阻塞IO,那么 Tomcat 至少要 8.0 以上。
接下来的案例小伙伴们记得选好自己本地的 Tomcat 版本。
3.基本玩法
先来看一个大家熟悉的同步 Servlet:
@WebServlet(urlPatterns = "/sync")
这个 Servlet 大家再熟悉不过了。
前端请求到达后,我们调用 printLog 方法做一些处理,同时把 doGet 方法执行耗时打印出来。
在 printLog 中,我们先休息 3s,然后给前端返回一个字符串给前端。
前端发送请求,最终 doGet 方法中耗时 3001 毫秒。
这是我们大家熟知的同步 Servlet。在整个请求处理过程中,请求会一直占用 Servlet 线程,直到一个请求处理完毕这个线程才会被释放。
接下来我们对其稍微进行改造,使之变为一个异步 Servlet。
有人可能会说,异步有何难?直接把 printLog 方法扔到子线程里边去执行不就行了?但是这样会有另外一个问题,子线程里边没有办法通过 HttpServletResponse 直接返回数据,所以我们一定需要
Servlet 的异步支持,有了异步支持,才可以在子线程中返回数据。
我们来看改造后的代码:
public class SyncServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
doGet(request, response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
long start = System.currentTimeMillis();
printLog(request, response);
System.out.println("总耗时:" + (System.currentTimeMillis() - start));
}
private void printLog(HttpServletRequest request, HttpServletResponse
response) throws IOException {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
response.getWriter().write("ok");
}
}
@WebServlet(urlPatterns = "/async",asyncSupported = true)
public class AsyncServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
doGet(request, response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
long start = System.currentTimeMillis();
AsyncContext asyncContext = request.startAsync();
这里的改造主要有如下几方面:
1. @WebServlet 注解上添加 asyncSupported 属性,开启异步支持。
2. 调用 request.startAsync(); 方法开启异步上下文。
3. 通过 JDK8 中的 CompletableFuture.runAsync 方法来启动一个子线程(当然也可以自己 new 一
个子线程)。
4. 调用 printLog 方法时的 request 和 response 重新构造,直接从 asyncContext 中获取,注意,
这点是【关键】。
5. 在 printLog 方法中,方法执行完成后,调用 asyncContext.complete() 方法通知异步上下文请求
处理完毕。
经过上面的改造之后,现在的控制台打印出来的总耗时几乎可以忽略不计了。
也就是说,有了异步 Servlet 之后,后台 Servlet 的线程会被及时释放,释放之后又可以去接收新的请求,进而提高应用的并发能力。
第一次接触异步 Servlet 的小伙伴可能会有一个误解,以为用了异步 Servlet 后,前端的响应就会加快。这个怎么说呢?后台的并发能力提高了,前端的响应速度自然会提高,但是我们一两个简单的请求是很难看出这种提高的。
CompletableFuture.runAsync(() ->
printLog(asyncContext,asyncContext.getRequest(),asyncContext.getResponse()));
System.out.println("总耗时:" + (System.currentTimeMillis() - start));
}
private void printLog(AsyncContext asyncContext, ServletRequest request,
ServletResponse response){
try {
Thread.sleep(3000);
response.getWriter().write("ok");
asyncContext.complete();
} catch (InterruptedException | IOException e) {
e.printStackTrace();
}
}
}
相关文章:
异步servlet
我们日常使用的 SpringMVC,基本上都不是异步 Servlet,而学习 WebFlux,异步 Servlet 是基础,WebFlux。 1.什么是异步 Servlet 先来说说什么是非异步 Servlet。 在 Servlet3.0 之前,Servlet 采用 Thread-Per-Request 的方…...

煤矿皮带运输智能监控算法 opencv
煤矿皮带运输智能监控算法通过opencvpython深度学习算法网络模型,煤矿皮带运输智能监控算法实时监测皮带运输过程中的各种异常情况,如跑偏、撕裂、堆料异常等,一旦检测到异常情况,立即发出告警并采取相应的措施,以保障…...

Docker搭建elasticsearch+kibana测试
最近需要做大数据画像,所以先简单搭建一个eskibana学习使用,记录一下搭建过程和遇到的问题以及解决办法 1.拉取es和kibana镜像 在拉取镜像之前先搜索一下 elasticsearch发现是存在elasticsearch镜像的,我一般习惯性拉取最新镜像,…...
QT(C++)-QTreeview节点折叠与展开
文章目录 1、前言2、QTreeview全部展开与折叠3、QTreeview某个节点展开与折叠3.1 节点折叠与展开的信号与槽3.2 槽函数的实现3.3 某个节点展开与折叠 1、前言 最近要用QT开发项目,对QT不是很熟,就根据网上的查到的知识和自己的摸索,将一些经…...

项目 - 后端技术栈转型方案
前言 某开发项目的后端技术栈比较老了,现在想换到新的技术栈上。使用更好的模式、设计思想、更合理的架构等,为未来的需求迭代做铺垫。怎么办呢?假设系统目前在线上运行着的,直接整体换的话耗时太久,且中间还有新的需…...
Oracle权限语句
授予权限:grant 权限 to 用户名; 撤销权限:revoke 权限 from 用户名; 常用: 创建用户: create user zhangsan identified by zhangsan; grant connect, resource to zhangsan; //授权zhangsan用户连接权限 grant create …...

微信小程序发布一个npm包
参考:https://developers.weixin.qq.com/miniprogram/dev/devtools/npm.html 同npm一样流程 npm install weixin_heath_apis...
Pytorch-lightning简介
Pytorch-lightning pytorch-lighting(简称pl),它其实就是一个轻量级的PyTorch库,用于高性能人工智能研究的轻量级PyTorch包装器。缩放你的模型,而不是样板。 框架核心内容 研究代码(位于LightningModule…...
【ES6】迭代器Iterator
JavaScript中的Iterator是一种特殊对象,它允许我们访问并操作对象的每一个元素。Iterator对象由具有next方法的对象创建,next方法返回一个包含两个属性的对象:value和done。value属性是当前元素的值,done属性是一个布尔值…...

火狐浏览器使用scss嵌套编写css无法识别问题
火狐浏览器使用scss嵌套编写css无法识别问题 版本: “node-sass”: “^4.14.1”, “sass-loader”: “^7.3.1”,vue版本: v2问题描述: 我的文件目录是这样的: 而在scss文件中我是这样书写的 .vue文件中 在火狐浏览器中 在谷…...

Kotlin的Lambda闭包语法
Lambda 表达式是一种在现代编程语言中常见的特性,它可以用来创建匿名函数或代码块,使得将函数作为参数传递、简化代码以及实现函数式编程范式变得更加便捷。Lambda 表达式在函数式编程语言中得到广泛应用,也在诸如 Java 8 和 Kotlin 等主流编…...

day-01 Docker
一、docker简介 Docker 是一种开源的容器化平台,它可以帮助开发人员将应用程序及其依赖项打包成一个独立的、可移植的容器,而无需担心环境差异和依赖问题。通过使用 Docker,您可以更轻松地创建、分发和运行应用程序,无论是在开发、…...

ARM开发,stm32mp157a-A7核SPI总线实验(实现数码管的显示)
1.目标: a.数码管显示相同的值 0000 1111 ......9999; b.数码管显示不同的值 1234; 2.分析m74hc595芯片内部框图; 真值表: 3.代码; ---spi.h头文件--- #ifndef __SPI_H__ #define __SPI_H__#include &quo…...

思路灰度传感器及红外传感器线序
四路红外传感器 黑线读取数据为0 白线读取数据为1 四路灰度传感器 黑线读取数据为1 白线读取数据为0...

squid服务器
目录 squid初识 安装squid代理 常用命令 主要配置文件 正向代理 环境配置 linux服务器设置 windows客户端设置 反向代理 环境配置 在web服务器配置服务 linux服务器配置 squid初识 含义:squid cache是一个流行的自由软件(GNU通用公共许可证…...
spring的后置处理器BeanPostProcessor
什么是BeanPostProcessor 是spring IOC容器给我们提供的一个扩展接口在调用初始化方法前后对bean进行额外加工,ApplicationContext会自动扫描实现了BeanPostProcessor的bean,并注册这些bean为后置处理器是bean的统一前置后置处理而不是基于某一个bean 执…...
vue、uniapp中动态添加绑定style、class 9种方法实现
9种方法介绍 直接使用静态class和style属性: 使用场景:当class和style属性是固定不变的时候,可以直接在模板中写死。优点:简单直接,没有额外的计算和逻辑。缺点:无法根据条件动态修改class和style。 使用v…...
【CicadaPlayer】seek :SeekInCache(int64_t pos)的实现
SuperMediaPlayer::SeekInCache(int64_t pos) 的实现 seek的pos就是pts值。缓冲是list,那么插入的包是按照到达的顺序插入到list的,也就是无排序的。包的pts 正常应该单调连续,即使不单调连续,缓存也不在意。seek的操作主要是先比较pos与mCurrentPos ,pos 比 mCurrentPos …...
【C/C++】x -x 的含义
1、含义 -x 的值,其实就是在x的值的基础上进行按位取反(~x)之后在增加1所得(C语言中,-x实现是用取反1实现)也就是说:x & -x x & (~x 1) 2、x 为偶数 当一个奇数 1时,表示…...

[ZenTao]源码阅读:加载自定义任务类型
www/index.php config/config.php framework/base/router.class.php tmp/model/common.php module/common/model.php framework/router.class.php...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...

以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...

Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...

Razor编程中@Html的方法使用大全
文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...

宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...