10 | 如何使用异步设计提升系统性能

导入导出设计导入篇) 导入交互设计、逻辑整理,一起学习呀 阅读详情

对开发者来说,异步是一种程序设计的思想,使用异步模式设计的程序可显著减少线程等待,从而在高吞吐的场景中,极大提升系统的整体性能,显著降低延时。

因此,像消息队列这种需要超高吞吐量和超低时延的中间件系统,在其核心流程中,一定会大量采用异步的设计思想。

接下来,我们一起来通过一个非常简单的例子学习,如何使用异步设计,提升系统性能。

异步设计如何提升系统性能?

假设我们要实现一个转账的微服务,Transfer(accountFrom, accountTo, amount),这个服务有三个参数:分别是转出,转入,金额。

实现过程也比较简单,要从账户A转账100元到账户B中:

1. 先从 A 的账户减 100 元

2. 再给 B 的账户加 100 元,转账完成

对应的时序图是这样:

client                                    transfer_service                                          account_service

     |-------Transfer(A, B, 100)------>  |  ------------------  Add(A,-100)-----------------> | 

     |                                                  |  <--------------------- OK -------------------------  |

     |                                                  |  ------------------  Add(B ,  100)----------------> |

     | <--------------OK ------------------- |  <--------------------- OK -------------------------  |

client                                    transfer_service                                          account_service

 

在这个例子的实现构成中,我们调用了另外的微服务 Add,功能是给账户增减金额。

特别说明,这段时序未做错误和事务处理,实际开发勿学。仅用于专注学习性能优化。

1. 同步实现的性能瓶颈

首先来看下同步实现。

首先从from扣钱,再从to加钱。分析一下代码性能,很容易计算出实现的微服务的transfer的平均响应时延大约等于两次 Add 的时延,也就是 100ms。随着调用 Transfer 服务的请求越来越多,每个请求100ms独占一个线程。一秒每个线程最多处理10个请求。每个机器上的线程资源并非无限,假使我们的服务器能同时打开的线程数量上线是1万。可计算出单服务器每秒的QPS为 10万。

如果请求超出,只能阻塞或者排队,此时transfer服务的响应时延由100ms延长到了:排队等待+处理时延。在大量请求下,微服务的平均响应时延变长。

但其实,此时机器CPU、内存、网卡流量、IO都空闲的很,因为1万个线程基本都在等待下游Add服务返回结果。

也就是说,采用同步实现,整个服务大部分的线程没在工作,都在等待

若能减少或避免无意义等待,就可大幅提升服务的吞吐能力,从而提升服务总体性能

2. 采用异步实现解决等待问题

接下来我们看一下,如何用异步思想来解决这个问题,实现同样的业务逻辑

先定义两个回调方法

  • OnDebit:扣减账户from后的回调方法
  • OnAllDone:转入账户 to 完成后的回调方法

改造后的整体异步语义是:

1. 异步从from的账户减去前述钱数,然后调用OnDebit

2. 在OnDebit中,异步把减去的钱加到to,然后执行 OnAllDone

3. 在OnAllDone中,调用OnComplete

client                                    transfer_service                                          account_service

     |-------TransferAsync ----------->  |  ------------------  AddAsync   ---------------->  | 

     |                                                  |  <----------------- OnDebit  ---------------------  |

     |                                                  |  ------------------  AddAsync   -----------------> |

     | <---------  OnComplete ---------- |  <--------------------- OnAllDone ---------------  |

client                                    transfer_service                                          account_service

会发现,异步化实现后,整个流程的时序和同步实现是完全一样的,区别只是在线程模型上由同步顺序调用改为了异步调用和回调的机制

接下来分析一下异步实现的性能,由于流程和同步一致,低请求的时延仍然是100ms。在超高请求数量场景下,异步实现不再需要线程等待执行结果,只需要个位数量的线程,即可实现同步场景大量线程一样的吞吐量。

因为没有线程数量的限制,总体吞吐会超过同步,在CPU,内存,网络带宽,I/O的资源达到极限之前,响应时延不会随请求量增大而增加,几乎可以一直维持100ms。

简单实用的java的异步框架 CompletableFuture

小结

简单的说,异步思想就是,当我们要执行一项比较耗时的操作,不要等操作结束,而是给这个操作一个命令,当操作完成后接下来执行什么

使用异步变成模型,虽然不能加快程序本身的速度,但可以减少或避免线程等待,只用很少的线程就可以达到超高的吞吐。

同时我们也需注意异步模型的问题,相比于同步实现,异步实现的复杂度要大很多,代码的可读性和可维护性都会显著下降。虽然使用异步编程框架简化了异步开发,但并不能解决模型高复杂度。

异步性能虽好,但不要滥用,只有类似消息队列这种业务逻辑简单并且要高吞吐的场景下,后者必须长时间等待资源的地方,才考虑使用一步模型。

若业务逻辑复杂,性能足够满足业务需求情况下,采用符合人类自然的思路且易于开发和维护的同步模型是更加明智的选择。

思考

第一个思考题:我们实现转账的时候,并没有考虑失败的处理。

如果调用账户服务失败,如何通知客户端。(callback中通知)

在两次调用账户服务失败时,如果某次失败,如何保证账户数据是平的。(首次失败后一步无需执行,第二次失败考虑重试,不能重试进行补偿,undo首次的转账。另一种想法是改造成单次调用的,下游进行单机事务操作。)

第二个思考题:

异步实现中,回调方法OnComplete是在什么线程中运行的。(OnAllDone)

是否能控制回调方法的执行线程数,该如何做?(原理是使用异步线程池控制回调方法的线程数。绑定回调到指定线程池执行即可)

3秒延迟?5步搞定SpringEvent:WebUploader大文件上传解耦效率飙升10倍! 摘要:SpringEvent技术在大文件上传场景中的解耦优势分析 本文通过对比传统同步处理与SpringEvent异步解耦方案,揭示大文件上传场景中的性能优化关键点: 传统同步方式存在代码耦合、响应延迟、扩展性差等问题(实测文件上传耗时30秒以上) SpringEvent方案通过事件驱动架构实现: 响应时间缩短90%(3秒内完成异步处理) 内存占用降低80%(500MB内) 扩展性提升(新增业务逻辑只需10分钟添加监听器) 实战演示5步解耦流程(自定义事件设计异步线程池配置等关键代码) 性能对比数据:Sp 阅读详情

相关推荐

消息队列学习笔记3——异步设计、序列化

文章目录一、异步设计1.同步的性能瓶颈2.采用异步实现解决等待问题3.JDK8异步框架: CompletableFuture二、异步网络框架1. Netty2. NIO三、序列化思考题 一、异步设计 1.同步的性能瓶颈 假设一个转账业务,伪代码如下: Transfer(accountFrom, accountTo, amount) { // 先从accountFrom的账户中减去相应的钱数 ...

耶律妙月的博客 745

异步导入导出架构设计

为什么要用异步?在我们平时的业务系统中,文件导入,文件导出是一个很常见的业务需求。正常情况下,同步导出就可以满足我们80%的需求。但是对于数据量大,业务拼接复杂的系统来说...

架构文摘 3937

异步处理设计方案

异步处理设计方案,针对于BS系统,看看是否可用,请大家指导

设计模式:异步处理文件常用设计模式

设计模式:异步处理文件常用设计模式

m0_49464000的博客 824

Flink集成Redis组件,使用异步IO能完全解决性能瓶颈问题?

基于上述的问题,我们先来对异步IO有个大致的认识,了解的同学可以选择跳过。 流计算系统中经常需要与外部系统(Redis、MySQL等)进行交互,我们通常的做法如向数据库发送用户a的查询请求,然后等待结果返回,在这之前,我们的程序无法发送用户b的查询请求。这是一种同步访问方式,如下图所示。 图中棕色的长条表示等待时间,可以发现网络等待时间极大地阻碍了吞吐和延迟。为了解决同步访问的问题,异步模...

JK_GOME的博客 3037

10 | 如何使用异步设计提升系统性能

对于开发者来说,异步是一种程序设计的思想,使用异步模式设计的程序可以显著减少线程等待,从而在高吞吐量的场景中,极大提升系统的整体性能,显著降低时延。 因此,像消息队列这种需要超高吞吐量和超低时延的中间件系统,在其核心流程中,一定会大量采用异步设计思想。 接下来,我们一起来通过一个非常简单的例子学习一下,使用异步设计是如何提升系统性能的。 异步设计如何提升系统性能? 假设我们要实现一个转账的微服务 Transfer( accountFrom, accountTo, amount),这个服务有三个参数

一蓑烟雨任平生 702

10个Tornado实战技巧:快速掌握异步Web开发核心

Tornado是一个强大的Python异步Web框架,专门为高性能网络应用设计。通过非阻塞I/O和协程机制,Tornado能够轻松处理数万个并发连接,是构建实时Web应用、长轮询服务和WebSocket应用的理想选择。本文将分享10个实用的Tornado开发技巧,帮助你快速掌握异步Web开发的核心要点。 ## 🚀 1. 快速搭建Hello World应用 从最简单的Hello World开始

gitblog_00413的博客 346

架构师必备10大接口性能优化秘技

在软件开发中,接口性能优化是架构师必须掌握的关键技能之一。一个高效的接口不仅能够提升用户体验,还能减少服务器资源消耗,提高系统稳定性。本文将介绍10大接口性能优化秘技,并通过Java示例代码展示这些技巧在实际业务场景中的应用。

喜欢猪猪 1002

深入剖析通信层和RPC调用的异步化(上)

《Netty 进阶之路》、《分布式服务框架原理与实践》作者李林锋深入剖析通信层和 RPC 调用的异步化。李林锋此后还将在 InfoQ 上开设 Netty 专题持续出稿,感兴趣的同学可以持续关注。1. 异步的一些常见误区1.1.常见的理解误区在将近10年的平台中间件研发历程中,我们的平台和业务经历了从C++到Java,从同步的BIO到非阻塞的NIO,以及纯异步的事件驱动I/O(AIO)。服务器也从...

cpongo5 439

异步FIFO设计

格雷码如果每2^n个数一循环,首尾两个格雷码仍然是只有一位变化,如果不是2^n个数,那么首尾数据就不是仅有一位变化,那就不是真正的格雷码,所以这也是异步FIFO的存储深度只能是2^n的原因。自然二进制码转换成二进制格雷码,其法则是保留自然二进制码的最高位作为格雷码的最高位,而次高位格雷码为二进制码的高位与次高位相异或,而格雷码其余各位与次高位的求法相类似。当读地址和写地址在不同圈时,格雷码的最高位也会不同。当写指针比读指针多循环RAM一周时,此时读写指针的最高位和次高位都相反,其余位相同,FIFO为满。

chouchoudenanren的博客 602

异步设计实现

java 异步设计

weixin_42115825的博客 1072

项目实战中的异步设计

在后台系统中,快递公司可以通过合理的任务调度,处理多个异步请求,提高寄件服务的整体吞吐量。这种方式类似于在后端异步处理任务,而用户无需等待任务完成,可以继续进行其他操作,提高了整个寄件过程的并发性和响应性。系统会在后台异步处理你的请求,安排合适的快递员前来取件。channel(通道): 是网络通信的载体,提供了基本的API用于网络I/0 操作如register、bind、connect、read、write、flush 等Netty自己实现的 Channel是以JDK NIO Channel为基础的。

weixin_39682329的博客 1081

异步设计7个优点

异步设计尽管存在很多缺点,但是同时也给我们带来了很多福利: 1.Robust mutual exclusion and external input handling 2.Automatic adaptation to physical properties 3.Better technology migration potential 4.Easing of global tim...

zilan23的博客 2971

【性能设计篇】聊聊异步处理

聊聊性能设计异步的处理

芝兰生于深谷,不以无人而不芳 638
上一篇: 09 | 学习开源代码该如何入手?
下一篇: 10 | 如何实现高性能的异步网络传输
vectorX
博客等级 码龄10年 37粉丝 21原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值