关键词总结:同步调用、异步调用、请求响应、直接订阅、中间人订阅、事件驱动设计
同步调用
同步调用让系统间只耦合于接口,而且实时性也会比异步调用要高,但同步调用会带来一些问题。
同步调用问题
- 调用链木桶效应
整个同步调用链的性能会由最慢的那个服务所决定。 - 调用链阻塞
同步调用会导致调用方一直阻塞等待被调用方完成,调用链中所有的参与方会有相同的等待时间。 - 同步调用一对一
同步调用只能是一对一的,很难做到一对多 - 调用链多米诺效应
同步调用中如果被调用方有问题,那么其调用方就会跟着出问题,于是会在调用链中出现多米诺骨牌效应
异步通讯
异步通讯相对于同步通讯来说,除了增加系统的吞吐量之外,最大的一个好处是其可以让服务间的解耦更为彻底
异步通讯的三种方式
请求响应式
发送方(sender)直接请求接收方(receiver),被请求方接收到请求后,直接返回,接收方处理请求。
这时发送方接收返回结果的方式有两种:
- 轮询:发送方每隔一段时间查看一下是否出现结果。
- 回调:接收方处理完结果后将结果返回至发送方提供的回调地址。
发送方依赖于接收方,耦合依然存在。
发送订阅方式
接收方(receiver)会来订阅发送方(sender)的消息,发送方会把相关的消息或数据放到接收方所订阅的队列中,而接收方会从队列中获取数据。发送方并不关心订阅方的处理结果,它只是告诉订阅方有事要干,收完消息后给个 ACK 就好了,干成啥样我不关心。
接收方需要向发送方订阅事件,接收方依赖于发送方,所以还存在一些耦合。
Broker(代理) 方式
Broker,就是一个中间人代理人,发送方(sender)和接收方(receiver)都互相看不到对方,它们看得到的是一个 Broker,发送方向 Broker 发送消息,接收方向 Broker 订阅消息。这是完全的解耦。所有的服务都不需要相互依赖,而是依赖于一个中间件 Broker。
由于所有人都依赖于一个Broker(代理) ,所以这个Broker(代理) 就需要有如下的特性:
- 高可用:代理需要随时处在可用状态,因为发送和接收方需要通过它来进行通讯,它成了整个系统的关键。
- 高性能:代理的响应必须要快,不能让发送以及接收的任何一方产生阻塞,而且是可以水平扩展的。
- 持久化:可以持久化不丢数据的。
事件驱动设计
发送订阅方式 和 Broker(代理) 方式 都属于事件驱动架构(EDA,Event Driven Architecture)。代理是最好的事件驱动架构。
事件驱动方式的五个好处:
- 服务无依赖可重用
服务间的依赖没有了,服务间是平等的,每个服务都是高度可重用并可被替换的。 - 服务高度隔离
服务的开发、测试、运维,以及故障处理都是高度隔离的。 - 服务无阻塞
服务间通过事件关联,所以服务间是不会相互 block 的。 - Adapter易添加
在服务间增加一些 如日志、认证、版本、限流、降级、熔断等Adapter相当容易。 - 服务间无处理速度依赖
服务间的吞吐被解开了,各个服务可以按照自己的处理速度处理。
事件驱动方式的缺点:
- 业务流程不明显难管理
服务无依赖,高度隔离,业务流程不再那么明显和好管理。整个架构变得比较复杂。 - 事件可能会乱序
事件驱动设计中的事件可能会乱序,带来非常 Bug 的事。解决这个问题需要很好地管理一个状态机的控制。 - 事务处理变复杂
事件驱动设计会将分布式事务变得更复杂,我们可能需要使用两阶段提交来做强一致性,或是退缩到最终一致性。
为什么要异步通讯
解耦
异步通讯最重要的是解耦服务间的依赖。最佳解耦的方式是通过 Broker 的机制。
隔离
解耦的目的是让各个服务的隔离性更好,这样不会出现“一倒倒一片”的故障。确保其他服务不会受出故障服务的影响。
独立
异步通讯的架构可以获得更大的吞吐量,而且各个服务间的性能不受干扰相对独立。服务相对独立,在部署、扩容和运维上都可以做到独立不受其他服务的干扰。
削峰
利用 Broker 或队列的方式还可以达到把抖动的吞吐量变成均匀的吞吐量
异步通讯注意事项
高可用与无顺序
异步通讯的中间件 Broker 成为了关键,需要设计成高可用不丢消息的。另外,因为是分布式的,所以可能很难保证消息的顺序,因此设计最好不依赖于消息的顺序。
服务消息可跟踪
异步通讯会导致业务处理流程不那么直观,在 Broker 上需要有相关的服务消息跟踪机制,否则出现问题后不容易调试。
业务流程需维护
服务间只通过消息交互,所以业务状态最好由一个总控方来管理,这个总控方维护一个业务流程的状态变迁逻辑,以便在故障发生时知道业务处理到哪一步了,从而可以在故障清除后继续处理。
消息重传与幂等
异步通讯中的消息在代理没有收到 ACK 时可以进行多次重传,但是接收消息的一方要确保相同的消息如论被重传多少次都能被处理一次。
参考资料:
左耳听风(极客时间)链接:
http://gk.link/a/10f5D
GitHub链接:
https://github.com/lichangke/LeetCode
CSDN首页:
https://me.csdn.net/leacock1991
欢迎大家来一起交流学习