全链路异步,让你的 SpringCloud 性能优化10倍+
背景
随着业务的发展,微服务应用的流量越来越大,使用到的资源也越来越多。
在微服务架构下,大量的应用都是 SpringCloud 分布式架构,这种架构,总体是全链路同步模式。
同步编程模式不仅造成了资源的极大浪费,并且在流量发生激增波动的时候,受制于系统资源而无法快速的扩容。
全球后疫情时代,降本增效是大背景。
如何降本增效?
可以通过技术升级,全链路同步模式 ,升级为 全链路异步模式。
尼恩作为40岁资深老架构师,带大家来做一把全链路异步模式改造,给大家看看研究成果,一定会惊到大家目瞪口呆。
本文作为 全链路异步架构的知识,收录在尼恩《尼恩Java面试宝典》的架构专题中
注:本文以 PDF 持续更新,最新尼恩 架构笔记、面试题 的PDF文件,请从这里获取:码云
全链路同步模式架构图
先回顾一下全链路同步模式架构图
全链路同步模式 ,如何升级为 全链路异步模式, 就是一个一个 环节的异步化。
40岁老架构师尼恩,持续深化自己的3高架构知识宇宙,当然首先要去完成一次牛逼的全链路异步模式 微服务实操,下面是尼恩的实操过程、效果、压测数据。
全链路异步模式
网关纯异步化(提升 9倍以上)
网关层的特点:
- 不需要访问业务数据库只做协议转换和流量转发
- 特点是 IO 密集型,特别适合纯异步的架构,可以极大的节省资源。
如何进行网关异步化?
使用高性能的通信框架Netty,这是一个基于NIO 非阻塞IO+ Reactor 纯异步线程模型的纯异步化框架。
网关的技术选型主要有 zuul,SpringCloud GetWay 。
- zuul 1虽然使用的同步io,zuul2它也是使用异步的netty,但是没有和SpringCloud 框架集成
- springcloud getway 它是基于spring 5.0 、spring boot 2.0 和spring reacter,为微服务提供一个简单有效的网关API路由接口。和SpringCloud 框架完美集成,目标是为了代替zuul
SpringCloud GetWay 是基于webFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。所以最终还是基于IO的王者组件Netty。
如果大家使用Zuul 1,那么 升级为 SpringCloud GetWay,性能可以提升 9倍以上,
以上结论,是来自于尼恩的读者群(50+),如有疑问,可以来单挑。
总体来说,这个环节,是纯异步化最容易的。
这个环节,大部分已经升级到了 springcloud getway 已经使用了纯异步的架构;
Web 服务异步化(2W并发场景提升 20倍以上)
Web 服务作为微服务体系内的重要组成,服务节点众多,
Springboot的Web 服务默认为 Tomcat + Servlet 不支持纯异步化编程,
Tomcat + Servlet模式的问题:总体上没有使用Reactor 反应器模式, 每一个请求是阻塞处理的,属于同步 Web 服务类型。
Servlet 有异步的版本,可惜没有用起来。具体请参考 40岁老架构师尼恩为大家整理的深度文章:
京东一面:20种异步,你知道几种? 含协程
所以:跑在 大家生产环境上的,还是Tomcat + Servlet 同步 Web 服务。
如何实现 Web 服务异步化:
- 方式一:基于 Netty 实现web服务
- 方式二:使用 WebFlux (还是 Netty 实现web服务)
Spring WebFlux是一个响应式堆栈 Web 框架 ,它是完全非阻塞的,支持响应式流(Reactive Stream)背压,并在Netty,Undertow和Servlet 3.1 +容器等服务器上运行
我们再来看一下对于 WebFlux 的对比测试数据 (来自于参考文献1):
可见,非阻塞的处理方式规避了线程排队等待的情况,从而可以用少量而固定的线程处理应对大量请求的处理。
还有更绝的,小伙伴又一步到位直接测试了一下20000用户的情况:
- 对 mvc 的测试由于出现了许多的请求fail,最终以失败告终;
- 而 WebFlux 应对20000用户已然面不改色心不慌,吞吐量达到7228 req/sec
注意:正好是10000用户下的两倍,绝对是真实数据!也就是说, 2W并发场景提升 20倍以上
95%响应时长仅117ms。
最后,再给出两个吞吐量和响应时长的图,更加直观地感受异步非阻塞的WebFlux是如何一骑绝尘的吧:
此时,我们更加理解了Nodejs的骄傲,不过我们大Java语言也有了Vert.x和现在的Spring WebFlux。
RPC 调用异步化(提升 9倍以上)
异步RPC 调用,等待upstream 上游 response 返回时,线程不处于block 状态
作为微服务架构中数据流量最大的一部分,RPC 调用异步化的收益巨大;
RPC 调用主要的框架有:
特点是:
- feign 是同步IO 、阻塞模式的同步 RPC框架
- dubbo 是基于Netty的非阻塞IO + Reactor 反应堆线程模型的 异步RPC框架
40岁老架构师尼恩,完成了 SpringCloud + Dubbo RPC 的集成,在同一个微服务下,同时使用了Feign + Dubbo
然后进行了性能的对比验证
dubbo 的压测数据
wrk -t8 -c200 -d30s --latency http://cdh1:18081/dubbo-consumer-demo/user/detail/v1?userId=1[root@centos1 src]# wrk -t8 -c200 -d30s --latency http://cdh1:18081/dubbo-consumer-demo/user/detail/v1?userId=1
Running 30s test @ http://cdh1:18081/dubbo-consumer-demo/user/detail/v1?userId=18 threads and 200 connectionsThread Stats Avg Stdev Max +/- StdevLatency 30.10ms 45.68ms 644.45ms 95.43%Req/Sec 1.12k 465.63 2.36k 66.87%Latency Distribution50% 18.94ms75% 28.43ms90% 46.21ms99% 283.56ms264316 requests in 30.07s, 148.47MB read
Requests/sec: 8788.96
Transfer/sec: 4.94MB
feign 的压测数据
wrk -t8 -c200 -d30s --latency http://cdh1:18081/dubbo-consumer-demo/echo/variable/11[root@centos1 src]# wrk -t8 -c200 -d30s --latency http://cdh1:18081/dubbo-consumer-demo/echo/variable/11
Running 30s test @ http://cdh1:18081/dubbo-consumer-demo/echo/variable/118 threads and 200 connectionsThread Stats Avg Stdev Max +/- StdevLatency 321.50ms 294.59ms 2.00s 61.77%Req/Sec 87.18 43.39 232.00 67.00%Latency Distribution50% 309.06ms75% 503.06ms90% 687.99ms99% 1.21s20495 requests in 30.10s, 7.64MB readSocket errors: connect 0, read 0, write 0, timeout 49
Requests/sec: 680.90
Transfer/sec: 259.99KB
从数据来看, dubbo rpc 是feign rpc 性能10倍
当然,感兴趣的小伙伴,也可以自己实操一下,更有感触。
Cache异步化(提升2倍+)
Cache Aside 缓存模式,是大家通用的Cache使用方式,Cache纯异步的架构,必须使用异步存储层客户端,
主要有:
- Redisson
- Lettuce
Redisson、Lettuce如何选型?请参考40岁老架构师尼恩的文章:
Jedis那么低性能,还在用?赶紧换上 lettuce 吧
40岁老架构师尼恩,完成了自己的开发脚手架Crazy-SpringCloud 的Cache异步化,经过对比验证,性能提升足足2倍多
使用Lettuce的场景:
[root@centos1 ~]# wrk -t8 -c200 -d30s --latency http://192.168.56.121:7703/uaa-react-provider/api/userCacheAside/detail/v1?userId=1
Running 30s test @ http://192.168.56.121:7703/uaa-react-provider/api/userCacheAside/detail/v1?userId=18 threads and 200 connectionsThread Stats Avg Stdev Max +/- StdevLatency 18.29ms 13.56ms 213.57ms 89.56%Req/Sec 1.51k 504.74 4.26k 72.86%Latency Distribution50% 14.56ms75% 19.92ms90% 31.20ms99% 76.70ms359546 requests in 30.10s, 53.15MB read
Requests/sec: 11945.39
Transfer/sec: 1.77MB
使用jedis的场景
wrk -t8 -c200 -d30s --latency http://192.168.56.121:7702/uaa-provider/api/user/detailCacheAside/v1?userId=1[root@centos1 src]# wrk -t8 -c200 -d30s --latency http://192.168.56.121:7702/uaa-provider/api/user/detailCacheAside/v1?userId=1
Running 30s test @ http://192.168.56.121:7702/uaa-provider/api/user/detailCacheAside/v1?userId=18 threads and 200 connectionsThread Stats Avg Stdev Max +/- StdevLatency 42.20ms 44.79ms 1.11s 93.41%Req/Sec 683.30 245.08 1.85k 67.39%Latency Distribution50% 32.65ms75% 48.30ms90% 72.32ms99% 199.81ms162271 requests in 30.09s, 71.96MB read
Requests/sec: 5393.75
Transfer/sec: 2.39MB
吞吐量 从 5000 提升到 10000
99% 响应时间 从199.81ms降低到 76.70ms
DB的异步化 (假装提升10倍)
数据操作是每个请求调用链的 终点,纯异步的架构必须使用异步存储层客户端,
比如说,可以使用纯异步化的框架 Spring Data R2DBC
在尼恩的Crazy-SpringCloud 脚手架 纯异步化 改造中,没有对 的DB 进行异步化改造,为啥呢?DB是一个低吞吐的物种,对于DB而已,请求太多,反而忙不过来,造成整体的性能下降。
所以,尼恩没有对DB进行纯异步化改造,反而是进行隔离和保护:
- 参考 Hystrix 舱壁模式, 通过 DB 的操作进行 线程池隔离,
- 使用 手写 Hystrix Command 的方式,进行 DB 操作的 高压防护。
控制线程数和请求数,保护不至于拖垮DB
由于高压防护,在高并发场景能快速失败,所以肯定提升不止10倍,不过是假装提升10倍
纯异步与伪异步
异步调用目的在于防止当前业务线程被阻塞。
伪异步将任务包装为Runnable 放入另一个线程执行并等待,当前Biz 线程不阻塞;
纯异步为响应式编程模型,通过IO 实践驱动任务完成。
两个概念很重要,这里不做赘述,具体请参考 40岁老架构师尼恩为大家整理的深度文章:
京东一面:20种异步,你知道几种? 含协程
全链路异步,让你的性能优化10倍+
降本增效时代,大家行动起来吧,对SpringCloud 微服务进行一场性能提升革命
想尽办法,让一台服务器,发挥10台的价值
特别提示:
在尼恩的全链路异步 改造的过程中, 大量使用 了 响应式编程。关于响应式编程的知识,请参考尼恩的 深度文章:
Flux、Mono、Reactor 实战(史上最全)
遗憾的是,响应式编程非常复杂,
后面,尼恩还会有响应式编程专题的3高架构笔记pdf,做到通俗易懂,带大家轻轻松松成为响应式编程专家。
参考文献
https://blog.csdn.net/get_set/article/details/79492439
https://blog.csdn.net/crazymakercircle/article/details/128899176
https://blog.csdn.net/crazymakercircle/article/details/124120506
推荐阅读:
《网易二面:CPU狂飙900%,该怎么处理?》
《阿里二面:千万级、亿级数据,如何性能优化? 教科书级 答案来了》
《峰值21WQps、亿级DAU,小游戏《羊了个羊》是怎么架构的?》
《场景题:假设10W人突访,你的系统如何做到不 雪崩?》
《2个大厂 100亿级 超大流量 红包 架构方案》
《Nginx面试题(史上最全 + 持续更新)》
《K8S面试题(史上最全 + 持续更新)》
《操作系统面试题(史上最全、持续更新)》
《Docker面试题(史上最全 + 持续更新)》
《Springcloud gateway 底层原理、核心实战 (史上最全)》
《Flux、Mono、Reactor 实战(史上最全)》
《sentinel (史上最全)》
《Nacos (史上最全)》
《TCP协议详解 (史上最全)》
《分库分表 Sharding-JDBC 底层原理、核心实战(史上最全)》
《clickhouse 超底层原理 + 高可用实操 (史上最全)》
《nacos高可用(图解+秒懂+史上最全)》
《队列之王: Disruptor 原理、架构、源码 一文穿透》
《环形队列、 条带环形队列 Striped-RingBuffer (史上最全)》
《一文搞定:SpringBoot、SLF4j、Log4j、Logback、Netty之间混乱关系(史上最全)》
《单例模式(史上最全)》
《红黑树( 图解 + 秒懂 + 史上最全)》
《分布式事务 (秒懂)》
《缓存之王:Caffeine 源码、架构、原理(史上最全,10W字 超级长文)》
《缓存之王:Caffeine 的使用(史上最全)》
《Java Agent 探针、字节码增强 ByteBuddy(史上最全)》
《Docker原理(图解+秒懂+史上最全)》
《Redis分布式锁(图解 - 秒懂 - 史上最全)》
《Zookeeper 分布式锁 - 图解 - 秒懂》
《Zookeeper Curator 事件监听 - 10分钟看懂》
《Netty 粘包 拆包 | 史上最全解读》
《Netty 100万级高并发服务器配置》
《Springcloud 高并发 配置 (一文全懂)》
相关文章:

全链路异步,让你的 SpringCloud 性能优化10倍+
背景 随着业务的发展,微服务应用的流量越来越大,使用到的资源也越来越多。 在微服务架构下,大量的应用都是 SpringCloud 分布式架构,这种架构,总体是全链路同步模式。 同步编程模式不仅造成了资源的极大浪费&#x…...
131.《router v 5 与 react-router v 6》
文章目录1.什么是路由2.路由分类3.react-router-dom的理解4. react-router-dom相关API5.其他6. react-router5 路由基本使用1.效果2.代码App.js一级路由home.js下的二级路由7.路由传参的三种方式8.react-router6 基本使用1.一级路由2.二级路由3.hooksuseRoutesuseParamsuseSear…...
2023第十届北京老年产业博览会/中国养老护理人才培育计划
CBIAIE北京老博会,打造2023年度唯具参展价值的老年行业盛会; 北京老博会:2011年,我国首场以“老年产业”为主题,一场专注于老年福祉、健康的国际型行业发展盛会,中国(北京)国际老年…...

STM32F407VET6 / BLACK_F407VE开发板间隔0.5秒不断重启
有一块 STM32F407VET6 的故障开发板, 之前的问题是经常无法烧录, 必须reset之后才能连接, 具体查看这篇 STM32F407VET6烧录出现flash download failed target dll has been cancelled. 并且程序运行一段时间后会halt. 这块开发板后来一直搁箱底吃灰了几年. 最近打算把这片 STM…...
什么是圈复杂度
圈复杂度是一种软件度量指标,用于度量程序中的控制流程的复杂性。它是通过计算程序中独立路径的数量来确定的。简单来说,圈复杂度是指在一个函数或模块中有多少个独立的路径,也就是说,有多少个不同的输入序列可以导致不同的执行路…...

Hbase 数据迁移
Hbase 数据迁移 可选方案对比 l 已验证方案操作说明: n Export&import u 导出命令及示例 hbase org.apache.hadoop.hbase.mapreduce.Export “表名” 文件路径 导出至本地文件系统: ./bin/hbase org.apache.hadoop.hbase.mapreduce.Export ‘defa…...

Docker consul的容器服务更新与发现
一、Consul概述(1)什么是服务注册与发现服务注册与发现是微服务架构中不可或缺的重要组件。起初服务都是单节点的,不保障高可用性,也不考虑服务的压力承载,服务之间调用单纯的通过接口访问。直到后来出现了多个节点的分…...

数据库关系模型
关系模型简述 形象地说,一个关系就是一个table。 关系模型就是处理table的,它由三个部分组成: 描述DB各种数据的基本结构形式;描述table与table之间所可能发生的各种操作;描述这些操作所应遵循的约束条件࿱…...

你是真的“C”——详解指针知识
你是真的“C”——详解指针知识😎前言🙌1、 指针是什么?🙌2、指针和指针类型🙌2 、1指针-整数2 、 2指针的解引用3、 野指针🙌3、 1野指针成因3、 2如何规避野指针4、指针运算🙌4、1 指针-整数4…...
React/ReactNative面试攻略(偏RN)
useMemo Vs useCallBackuseMemo第一个参数返回的是值,useCallBack返回的是函数useMemo和useCallBack第二个参数都是依赖项useMemo避免组件非依赖项更新时参数的计算useCallback避免父组件非依赖项更新时造成子组件的重复渲染React.memo 使用场景纯prue组件ÿ…...

Leetcode-每日一题1234. 替换子串得到平衡字符串(滑动窗口 + 哈希表)
题目链接:https://leetcode.cn/problems/replace-the-substring-for-balanced-string/description/ 思路 题目意思 这题意思是一个只含有[Q, W, E, R] 四个字符的字符串s且长度一定是 4的倍数, 需要你通过替换子串,使他变成一个「平衡字符…...
linux命令小结-查看日志命令
一、查看日志命令cat查看文件 vi编辑后可以用cat进行查看保存是否成功1)cat -n alert_monitor.log2)cat -n alert_monitor.log | tail -n 100 | head -n 20 //查询100行之后的日志,且在100行之后里再查前20条日志more 可以通过回撤键翻页mor…...

Java知识点细节简易汇总——(8)枚举和注解+Java面向对象高级作业
一、枚举 自定义枚举 当我们使用 enum 关键字开发一个枚举类时,默认会继承 Enum 类, 而且是一个 final 类[如何证明],老师使用 javap 工具来演示传统的 public static final Season2 SPRING new Season2(“春天”, “温暖”); 简化成 SPRING(“春天”, “温暖”)…...
快速上手JVM- Java Virtual Machine面试不用慌
一、JVM的定义 JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。 引入Java语言虚拟机后,J…...

安警官的IP地址是怎样定位到莽村附近的?
要说最近大火的电视剧非《狂飙》莫属。电视剧《狂飙》自开播以来,一举超过《三体》《去有风的地方》等先播电视剧,收视率一路“狂飙”,牢牢占据近期的收视冠军。 在剧中,张译扮演一名坚持公平、正义与理想的人民警察“安欣”&…...

STL中重要容器vector总结
你要尽全力保护你的梦想。那些嘲笑你的人,他们必定会失败,他们想把你变成和他们一样的人。如果你有梦想的话,就要努力去实现。 ——《当幸福来敲门》引言:C中STL里面的容器用法很巧妙,可以解决很多复杂的模型ÿ…...

11_会话原理与实现流程
1、会话的基本知识 # 会话## 1.会话是什么?客户端与服务器之间的对话交流## 2.为什么需要会话?-http 协议是无状态的(六亲不认)-同一用户多次访问同一网站,对网站来说,每次都是全新的-网站不能识别用户身份…...

Java测试——junit的使用(2)
排序 我们同一个类下的多个用例的执行顺序是不确定的,如果需要指定固定的顺序,则需要在类上加这个注解 TestMethodOrder(MethodOrderer.OrderAnnotation.class)然后在想要第一个执行的用例上加上 Order(1)第二个执行的用例上注解: Order(…...

数据库(六): MySQL的主从复制和读写分离
文章目录一、为什么要使用主从复制和读写分离二、主从复制的原理三、如何实现主从复制3.1 master配置3.2 slave配置3.3 测试主从复制四、读写分离五、缺点一、为什么要使用主从复制和读写分离 注意到主从复制和读写分离一般是一起使用的。目的很简单,就是提高数据库…...

编程思想-0x00架构
产生架构的原因? 1、代码均摊 将不同的代码进行分块,然后简历联系,低耦合、高内聚; 原则上:合理的App架构应该是合理分配每个类、结构体、方法、变量的存在都应该遵循单一职责的原则 2、便于测试 测试确保代码质量&…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...

【深度学习新浪潮】什么是credit assignment problem?
Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…...

轻量级Docker管理工具Docker Switchboard
简介 什么是 Docker Switchboard ? Docker Switchboard 是一个轻量级的 Web 应用程序,用于管理 Docker 容器。它提供了一个干净、用户友好的界面来启动、停止和监控主机上运行的容器,使其成为本地开发、家庭实验室或小型服务器设置的理想选择…...