天天看点

分布式系统容错-异步通信设计事件驱动设计

前面所说的隔离设计通常都需要对系统做解耦设计,而把一个单体系统解耦,不单单是把业务功能拆分出来,正如上面所说,拆分完后还会面对很多的问题。其中一个重要的问题就是这些系统间的通讯。

通讯一般来说分同步和异步两种。同步通讯就像打电话,需要实时响应,而异步通讯就像发邮件,不需要马上回复。各有千秋,我们很难说谁比谁好。但是在面对超高吐吞量的场景下,异步处理就比同步处理有比较大的优势了,这就好像一个人不可能同时接打很多电话,但是他可以同时接收很多的电子邮件一样。

同步调用虽然让系统间只耦合于接口,而且实时性也会比异步调用要高,但是我们也需要知道同步调用所带来如下的问题。

  • 同步调用需要被调用方的吞吐不低于调用方的吞吐。否则会导致被调用方因为性能不足而拖死调用方。换句话说,整个同步调用链的性能会由最慢的那个服务所决定。
  • 同步调用会导致调用方一直在等待被调用方完成,如果一层接一层地同步调用下去,所有的参与方会有相同的等待时间。这会非常消耗调用方的资源(因为调用方需要保存现场(Context)等待远端返回,所以对于并发比较高的场景来说,这样的等待可能会极度消耗资源)。
  • 同步调用只能是一对一的,很难做到一对多的通讯方式。
  • 同步调用最不好的是,如果被调用方有问题,那么其调用方就会跟着出问题,于是会出现多米诺骨牌效应,故障一下就蔓延开来。

所以,异步通讯相对于同步通讯来说,除了可以增加系统的吞吐量之外,最大的一个好处是其可以让服务间的解耦更为彻底,系统的调用方和被调用方可以按照自己的速率而不是步调一致,从而可以更好地保护系统,让系统更有弹力。

异步通讯的俩种方式

请求响应式

在这种情况下,发送方(sender)会直接请求接收方(receiver),被请求方接收到请求后,直接返回——收到请求,正在处理。

对于返回结果,有两种方法,一种是发送方时不时地去轮询一下,问一下干没干完。另一种方式是发送方注册一个回调方法,也就是接收方处理完后回调请求方。这种架构模型在以前的网上支付中比较常见,页面先从商家跳转到支付宝或银行,商家会把回调的 URL 传给支付页面,支付完后,再跳转回商家的 URL。

很明显,这种情况下还是有一定耦合的。是发送方依赖于接收方,并且要把自己的回调发送给接收方,处理完后回调。

通过 Broker 的方式

所谓 Broker,就是一个中间人,我理解就是MQ,发送方(sender)和接收方(receiver)都互相看不到对方,它们看得到的是一个 Broker,发送方向 Broker 发送消息,接收方向 Broker 订阅消息。如下图所示。

分布式系统容错-异步通信设计事件驱动设计

这是完全的解耦。所有的服务都不需要相互依赖,而是依赖于一个中间件 Broker。这个 Broker 是一个像数据总线一样的东西,所有的服务要接收数据和发送数据都发到这个总线上,这个总线就像协议一样,让服务间的通讯变得标准和可控。

在 Broker 这种模式下,发送方的服务和接收方的服务最大程度地解耦。但是所有人都依赖于一个总线,所以这个总线就需要有如下的特性:

  • 必需是高可用的,因为它成了整个系统的关键;
  • 必需是高性能而且是可以水平扩展的;
  • 必需是可以持久化不丢数据的。

事件驱动设计

上述的第二种就是比较著名的事件驱动架构(EDA – Event Driven Architecture)。正如前面所说,事件驱动最好是使用 Broker 方式,服务间通过交换消息来完成交流和整个流程的驱动。

如下图所示,这是一个订单处理流程。下单服务通知订单服务有订单要处理,而订单服务生成订单后发出通知,库存服务和支付服务得到通知后,一边是占住库存,另一边是让用户支付,等待用户支付完成后通知配送服务进行商品配送。

分布式系统容错-异步通信设计事件驱动设计

每个服务都是“自包含”的。所谓“自包含”也就是没有和别人产生依赖。而要把整个流程给串联起来,我们需要一系列的“消息通道(Channel)”。各个服务做完自己的事后,发出相应的事件,而又有一些服务在订阅着某些事件来联动。

事件驱动方式的好处至少有五个。

  • 服务间的依赖没有了,服务间是平等的,每个服务都是高度可重用并可被替换的。
  • 服务的开发、测试、运维,以及故障处理都是高度隔离的。
  • 业务流程不再那么明显和好管理。整个架构变得比较复杂。解决这个问题需要有一些可视化的工具来呈现整体业务流程。
  • 事件可能会乱序。这会带来非常 Bug 的事。解决这个问题需要很好地管理一个状态机的控制。
  • 事务处理变得复杂。需要使用两阶段提交来做强一致性,或是退缩到最终一致性

思考:异步通讯可以提升系统的吞吐量,以及业务解耦。但什么事情都有两面性,带来好处的同时,也引入了新的问题,比如排查问题困难,以及数据顺序问题,数据一致性问题。所以我们要适度的使用异步通信。美酒虽好,切莫贪杯。

继续阅读