springboot优雅shutdown时如何保障异步线程的安全
我前面写了一篇springboot优雅shutdown的文章,看起来一切很美好。
https://blog.csdn.net/chenshm/article/details/139640775
那是因为没有进行多线程测试。如果一个请求中包括阻塞线程(主线程)和非阻塞线程(异步线程),会是什么效果?接下来我们就测试一番。
1. 验证优雅shutdown的异步线程安全性
- 确认graceful shutdown配置
查看源码可以看到springboot graceful shutdown默认只会等待30s,我这里设置更长的时间只是方便测试,实际设置还是需要根据你业务api最长执行时间来配置。
- 准备测试代码
@Slf4j
@RestController
@RequestMapping("/api")
public class DemoController {@GetMapping("/{userId}")public ResultVo<Object> getUserInfo(@PathVariable String userId) throws InterruptedException {log.info("userId:{}", userId);Runnable runnable = () -> {for (int i = 0; i < 60; i++) {log.info("async thread to update user login info to other services, service num: {}", i);try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}};Thread thread = new Thread(runnable);thread.start();for (int i = 0; i < 30; i++) {log.info("querying user info for {}, waiting times: {}", userId, i);Thread.sleep(1000);}return ResultVo.ok();}
}
这里我设置非阻塞线程的循环是60次,大概60s完成,阻塞线程循环只有30次,大概30s完成。主要是为了测试我的阻塞线程完成后,graceful shutdown能不能保证我的异步线程安全。
- 请求api
Administrator@USER-20230930SH MINGW64 /d/git/micro-service-logs-tracing
$ curl http://localhost:8080/api/sandwich
- shutdown app(Ctrl+F2)
- 查看日志
可以看到shutdown信号发出之后,两个线程都还在跑,但是阻塞线程(0-29)结束之后,异步线程也跟着终结了。它的循环应该是从0到59才算结束,但是只跑到30,所以异步线程是不安全的。
- 验证主线程返回结果
阻塞线程还是安全的,response正常返回了。
其实这种测试方法并不局限于解决springboot的问题,其他微服务也是类似的。过去我看到一些朋友测试release的安全性,只是不断call health api,只要release 期间health api没有返回异常就当作ok了,其实这只能验证你的负载均衡服务的可靠性,你自己app的安全问题还是没有得到解决。
既然问题找到了,接下来我来解决它。
2. 确保优雅shutdown app时异步线程也安全
2.1 优化代码
前面的异步线程只是简单地写个野线程,并不规范,我先优化一下。
- 把野线程放到线程池执行;
- 利用mbean的PreDestroy来在servcie销毁前先等待异步线程完成;
- 利用ExecutorService 的awaitTermination方法预判断异步线程的最长等待时间,等待异步线程完成,如果线程没有按时完成再强制结束。
@Slf4j
@Service
public class AsyncServiceImpl implements AsyncService {private final ExecutorService executorService;public AsyncServiceImpl() {this.executorService = Executors.newFixedThreadPool(10);}@Overridepublic void feedUserInfoToOtherServices(String userId) {executorService.execute(() -> {for (int i = 0; i < 35; i++) {log.info("async thread to update {} login info to other services, service num: {}", userId, i+1);try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});}@PreDestroypublic void tearDown() {if (null != executorService) {executorService.shutdown();try {if (!executorService.awaitTermination(50, TimeUnit.SECONDS)) {executorService.shutdownNow();}} catch (InterruptedException e) {log.info("PreDestroy executorService is interrupted", e);executorService.shutdownNow();}}}
}
api代码调整如下
@Slf4j
@RestController
@RequestMapping("/api")
public class DemoController {@ResourceAsyncService asyncService;@GetMapping("/{userId}")public ResultVo<Object> getUserInfo(@PathVariable String userId) throws InterruptedException {log.info("userId:{}", userId);asyncService.feedUserInfoToOtherServices(userId);for (int i = 0; i < 30; i++) {log.info("updating user info for {}, waiting times: {}", userId, i+1);Thread.sleep(1000);}return ResultVo.ok();}
}
2.2 验证shutdown过程异步线程的安全
从新代码看来,我们期待的结果是一个api请求,主线程循环从1到30,异步线程是从1到35,主线程先完成,异步线程会在AsyncServiceImpl servcie bean销毁前先等待异步线程完成。接下来是验证步骤。
- 重启服务
- call api
Administrator@USER-20230930SH MINGW64 /d/git/micro-service-logs-tracing
$ curl http://localhost:8080/api/sandwich
- shutdown app(Ctrl + F2)
- 查看日志
分析日志发现一切如代码所料,app graceful shutdown的时候,异步线程的安全性得到保障。
这个过程看起来非常完美,其实还不够完美,解决方案没最好,只有更好。请先关注我,容我研究一下,下期告诉你为什么。
相关文章:
springboot优雅shutdown时如何保障异步线程的安全
我前面写了一篇springboot优雅shutdown的文章,看起来一切很美好。 https://blog.csdn.net/chenshm/article/details/139640775 那是因为没有进行多线程测试。如果一个请求中包括阻塞线程(主线程)和非阻塞线程(异步线程)…...
C++格式化库fmt使用方法
1. 格式化库fmt简介 fmt github地址 api说明 格式化参数说明 内容的格式化,体现在代码中主要表现为字符串、基本类型、自定义类型的拼接。例如说打印日志、拼接变量等。C中我们会经常使用类似printf,snprintf(C风格使用不方便),std::string.append(繁琐), std::io…...
HTML 颜色名:网页设计的调色板
HTML 颜色名:网页设计的调色板 在网页设计和开发中,颜色是一个关键元素,它不仅影响视觉效果,还能传达情感和品牌信息。HTML 颜色名是用于在 HTML 和 CSS 代码中指定颜色的预定义名称。这些颜色名易于记忆,方便设计师和开发者快速选择和应用颜色。本文将详细介绍 HTML 颜色…...
12306 火车票价格解析 (PHP 解析)
1. 从接口拿数据 日期 出发站 终点站 都填上 xxx/otn/leftTicketPrice/queryAllPublicPrice?leftTicketDTO.train_date2024-06-15&leftTicketDTO.from_stationBJP&leftTicketDTO.to_stationSJP&purpose_codesADULT 返回的数据是这样的 {"validateMess…...
了解统计学中不同类型的分布
目录 一、说明 二、均匀分布: 三、机器学习和数据科学中的均匀分布示例: 3.1 对数正态分布: 3.2 机器学习和数据科学中的对数正态分布示例: 四、 帕累托分布 4.1 什么是幂律? 4.2 机器学习和数据科学中的帕累托分布示例…...
k8s-CCE创建工作负载变量引用
CCE创建工作负载变量引用 背景,看到cce创建负载时会生成变量,如下。在skywaking-agent的使用,想要调用cce负载变量生成service_name。 -Dskywalking.agent.authentication里含有敏感信息需要写到配置项。简单粗糙的都写到配置项好像不合适。…...
后端主流框架--Spring02
前言:上篇关于Spring的文章介绍了一些Spring的基本知识,此篇文章主要分享一下如何配置Spring环境,如何注入等。 Spring项目构建 导入Spring相关JAR包 <dependency><groupId>org.springframework</groupId><artifactId>spring…...
[数据集][目标检测]减速带检测数据集VOC+YOLO格式5400张1类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):5400 标注数量(xml文件个数):5400 标注数量(txt文件个数):5400 标注…...
分析Linux操作指令及使用场景与频率分析 持续更新
本篇主要针对在日常工作与学习中使用较多的linux指令的使用方法以及使用频次进行分析与讲解,旨在能够更好的掌握这些必备的技能。 linux指令非常的多,如果要记住所有的指令使用方法是非常困难的且要花费很长的时间,很多人习惯离开使用去通篇…...
Redis 字符串(String)
Redis 字符串(String) 介绍 Redis是一种开源的、高性能的键值数据库,它支持多种类型的数据结构,其中字符串(String)是Redis中最基本的数据类型之一。字符串类型可以存储任何形式的字符串,包括文本、序列化的对象或二进制数据。在Redis中,字符串类型的最大容量为512MB。 …...
第一篇:容器化的未来:从Docker的革命到云原生架构
容器化的未来:从Docker的革命到云原生架构 1. 引言 在当今快速演进的技术领域,容器化技术已经成为云计算和微服务架构的重要组成部分。该技术以其高效的资源利用率、快速的部署能力和卓越的隔离性能,彻底改变了软件开发和部署的方式。容器化…...
【2024最新华为OD-C/D卷试题汇总】[支持在线评测] URL拼接(100分) - 三语言AC题解(Python/Java/Cpp)
🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 📎在线评测链接 URL拼接(100分) 🌍 评测功能需要订阅专栏后私信联系清隆解…...
反射,枚举以及lambda表达式
【本节目标】 1. 掌握反射 2. 掌握枚举 3. 掌握lambda表达式使用 反射 1 定义 Java的反射(reflection)机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调…...
DNS域名解析----分离解析、多域名解析、父域与子域
1 理论部分 1.1 分离解析 DNS的分离解析,是指根据不同的客户端提供不同的域名解析记录。来自不同地址的客户机请求解析同一域名时,为其提供不同的解析结果。也就是内外网客户请求访问相同的域名时,能解析出不同的IP地址,实现负载…...
Spring底层架构核心概念解析
BeanDefinition BeanDefinition表示Bean定义,BeanDefinition中存在很多属性用来描述一个Bean的特点.比如: beanClass:表示Bean类型scope:表示Bean作用域,单例/原型等lazyInit:表示Bean是否懒加载initMethodName:表示Bean初始化时要执行的方法destoryMethodName:表示Bean销毁时…...
C++ 44 之 指针运算符的重载
#include <iostream> #include <string> using namespace std;class Students04{ public:int m_age;Students04(int age){this->m_age age;}void showAge(){cout << "年龄是: " << this->m_age << endl;}~Students0…...
onlyoffice在线预览加载优化
背景: 使用容器部署onlyoffice到linux服务器,使用内网访问速度还可以接受,但是如果放到外网路径访问起来,速度就会很慢,甚至加载失败; 优化方案: 预览的过程排除网络因素,可以发现打…...
依赖自动装配
黑马程序员SSM框架 文章目录 1、依赖自动装配2、依赖自动装配的特征 1、依赖自动装配 IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配自动装配方式 按类型(常用)按名称按构造方法不启用自动装配 配置中使用bean标签auto…...
mysql和redis的双写一致性问题
一,使用方案 在使用redis作为缓存的场景下,我们一般使用流程如下 二,更新数据场景 我们此时修改个某条数据,如何保证mysql数据库和redis缓存中的数据一致呢? 按照常规思路有四种办法,1.先更新mysql数据&a…...
Qwen2——阿里巴巴最新的多语言模型挑战 Llama 3 等 SOTA
引言 经过几个月的期待, 阿里巴巴 Qwen 团队终于发布了 Qwen2 – 他们强大的语言模型系列的下一代发展。 Qwen2 代表了一次重大飞跃,拥有尖端的进步,有可能将其定位为 Meta 著名的最佳替代品 骆驼3 模型。在本次技术深入探讨中,我…...
等级考试3-2021年3月题
作业: #include <iostream> using namespace std; int chonghe(int,int,int,int); int main(){int a[1000],b[1000];int n,ma0;cin>>n;for(int i0;i<n;i){cin>>a[i]>>b[i];}for(int i0;i<n;i){for(int ji1;j<n;j){mamax(ma,chongh…...
Web前端开发PPT:深入探索与实战应用
Web前端开发PPT:深入探索与实战应用 在数字化时代,Web前端开发已成为构建丰富、交互性强的网页应用的关键环节。本次分享旨在通过PPT的形式,带领大家深入探索Web前端开发的精髓,并分享一些实战应用的经验。接下来,我们…...
liunx常见指令
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 二、安装环境 1.租借服务器 2.下载安装 XShell 3.使用xshll登录服务器 三、Linux基础命令 一、文件和命令 编辑1、cd 命令 2、pwd 命令 3、ls 命令 4、cp 命令 …...
vscode设置成中文界面
在Visual Studio Code(VSCode)中设置中文界面,你可以采用以下几种方法,以下是详细步骤: 方法一:通过设置菜单设置中文 打开VSCode:首先,确保你已经打开了VSCode软件。进入设置&…...
python命名空间详解
Python中的命名空间是编程语言设计的一个核心概念,它负责存储变量名与其对应的值之间的映射关系,确保了程序中变量的唯一性和可访问性。命名空间不仅关乎变量的生命周期和作用范围,也是Python中实现封装、避免命名冲突的重要机制。 1. 命名空…...
【日常记录】【vue】vite-plugin-inspect 插件的使用
文章目录 1、vite-plugin-inspect2、安装3、使用4、链接 1、vite-plugin-inspect vite-plugin-inspect 可以让开发者在浏览器端就可以看到vue文件编译后的代码、vue文件的相互依赖关系 2、安装 npm i -D vite-plugin-inspect// vite.config.ts import Inspect from vite-plugi…...
mini web框架示例
web框架: 使用web框架专门负责处理用户的动态资源请求,这个web框架其实就是一个为web服务器提供服务的应用程序 什么是路由? 路由就是请求的url到处理函数的映射,也就是说提前把请求的URL和处理函数关联好 管理路由可以使用一个…...
基于C#开发web网页管理系统模板流程-主界面统计功能完善
点击返回目录-> 基于C#开发web网页管理系统模板流程-总集篇-CSDN博客 前言 紧接上篇->基于C#开发web网页管理系统模板流程-主界面管理员入库和出库功能完善_c#web程序设计-CSDN博客 统计功能是管理系统很常见的功能,例如仓库管理系统要统计某时间段的出入库以…...
chromedriver114以后版本下载地址汇总chromedriver所有版本下载地址汇总国内源下载
谷歌浏览器版本经常会升级,chromedriver 也得下载匹配的版本 chromedriver 114以前版本下载地址https://registry.npmmirror.com/binary.html?pathchromedriver/ 但是自从115版本及其以后网站就找不到了,因此整理了截止2024年6月16日前所有在windows x6…...
x86计算机的启动初期流程 Linux 启动流程
x86计算机的启动初期流程 CPU: step1,加点开机,cpu自己初始化 step2,cpu 从物理地址 0xFFFFFFF0h 取指令执行;此处存放BIOS代码,这些代码可以是由主板自动从 EEPROM中拷贝至此内存地址处;即下…...
恩施市住房和城乡建设局网站/seo工具软件
闭包的优点,延长或扩大了变量的使用范围,延长了变量的使用时间,2.避免了变量命名的冲突 缺点:如果乱用闭包,会造成空间的浪费 创建person新实列:1创建一个新对象 2.将构造函数的作用域赋给新对象࿰…...
tp5做企业网站/文明seo
涉及平台:平台管理(包含自营店面)、商家端(PC端、手机端)、买家平台(PC端、H5/公众号、小程序、APP端(IOS/Android)、微服务平台(业务服务) 核心架构…...
常州想做个企业的网站找谁做/百度seo排名软
1 23456789查询汽车页面1011<?php 12 //造链接对象。取出用户传的值13 $db new MySQLi("localhost","root","511108","text");14 //1先定个$name "";变量15 //$name $_POST["name"];//取name的值16 $tj &…...
开购物网站需要多少钱/网页设计效果图及代码
www.bnjyedu.com...
网站改版做301重定向/dw软件怎么制作网页
混杂模式 只要流经该机器的报文都会被抓取 抓包过滤器 简单使用 保存 停止抓包后保存。file->save 最好保存为pcap格式 选择解析方式 例如访问web网页默认是80端口,若访问了81端口,需要用decode as指定按什么协议解析 数据量跟踪 常用视图 常见协…...
如皋住房和城乡建设局网站/高端网站定制设计
2019独角兽企业重金招聘Python工程师标准>>> 使用react时,如果我们将层级划分的很清楚,那么就会经常出现子级组件更改父级组件状态的情况,而这种情况并不能单单由redux来解决,那么要怎么样方便快捷的实现这种需求呢? 其实说来也很容易, 简单地说就是在父级元素调用…...