设计原则

前面我们讲到单元化架构中分为GZone、CZone和RZone,所以在消息的场景中跨Zone投递场景必不可少,我们应该本着一下原则就对我们架构进行升级改造。

最小化对业务的侵入性

希望业务不做改造或者做很少的改造就能支持跨Zone消息,尽量将跨Zone逻辑封装到消息服务器端。

节约网络流量

消息中心采用的是pub/sub的模式,一个消息往往有多个订阅端。在跨Zone的场景下,如果每个跨Zone的订阅端都单独投递一份消息,会带来大量的网络流量。所以消息在跨Zone时进行了合并,跨Zone时只将一条消息转发过去,实际投递时再给每个订阅端分别投递一份。

可维护性

消息在投递时需要区分出哪些消息需要跨Zone,一种方法是维护一个白名单,将需要跨Zone的消息配置在白名单中,这种方式非常直观,但是有一个很明显的缺陷,就是非常难以维护,每次新增跨zone消息时都需要修改白名单,这不但带来大量的维护工作还很容易出错。

那我们最好可以采取一种动态自适应的方式,即Rzone在投递时判断是否有订阅端在线,如果不在线那么跨到Gzone。在Gzone应用全量部署阶段可以做到应用对跨Zone消息无感知。当然,随着LDC架构的发展,Gzone逐渐演变为非全量应用部署,此时,当Gzone中的应用下线时,需要做一定的维护工作。但是,大量的系统其实是部署在Gzone的,所以这种动态自适应的方式还是会继续发挥重要的作用。

合理的成本

消息在跨Zone时,有两种处理方式,一种是经典的存储转发方式,消息跨Zone后先落数据库再进行投递,好处是落库成功后即可完成跨Zone逻辑,不会受实际订阅端的影响,稳定性和故障隔离性较好。坏处是消息多次入库,增加了成本。

另外一种方式是消息跨Zone后不落地,直接投递给实际订阅端,投递结果再一路返回到产生消息的Zone,这样做的好处是单次入库,成本低,坏处是通信链路长,故障会一定程度上反向扩散。综合对比来说明显第二种方式会更好一点。

架构升级

过往的架构中Server是互相隔离的,互不通信的,但是在单元化架构的场景中消息需要跨Zone转发,这条架构原则被打破了。

为了对使用消息的应用屏蔽消息跨Zone的复杂性,我们应该把绝大部分的跨Zone逻辑都封装在了服务器端。改造后的消息中心之间有了互相通信的机制。消息中心之间通过连接每个IDC的配置中心,获取每个IDC里面的消息中心的地址,互相建立长连接,来支持跨Zone的消息转发。

当消息需要进行跨Zone转发时,我们称产生消息的Zone为源Zone,称需要转发到的Zone为目标Zone。出于成本的考虑,消息跨Zone转发使用的是源Zone驱动的方式,到了目标Zone后,消息不落地,直接进行投递,投递的结果再返回到源Zone。如果投递失败,也由源Zone再次发起重试。

在下图中,左边的Rzone是产生消息的源Zone,右边的Gzone是目标Zone,中间的绿线表示消息中心间的消息跨Zone转发路径。

单元化架构 缺点 单元化架构规范_单元化架构 缺点

跨zone场景和投递逻辑

一般有哪几种场景可能会出现跨Zone呢?

  • 消息订阅端只部署在GZone,那么RZone发出的消息就需要跨Zone,从RZone转到GZone
  • 另一种场景消息订阅端在RZone,那么GZone发出的消息就需要跨Zone,从GZone转到RZone

上面我们提到动态自适应的方式,我们需要改造订阅关系,我们为订阅关系添加了“Zone属性”维度,目前有以下几个值:rzone,gzone,czone,local,空(默认)。其中,前三个分别表示针对本订阅关系的消息需要转发到Rzone,Gzone和Czone。local表示消息只在本zone内投递,不跨zone。比如定时任务消息,此类消息需要在本zone内投递,如果跨zone有可能引起业务问题,所以需要设置订阅关系的zone属性为local。空(默认)主要是为了兼容从无LDC架构到有LDC架构的演变,主要含义是,如果消息从Gzone产生,那么本zone内投递,如果从Rzone产生,那么先从本zone内寻找在线的订阅端,如果有,则本zone内投递,否则转发到Gzone。

下面这张图描述了投递逻辑

单元化架构 缺点 单元化架构规范_单元化架构 缺点_02

异地部署

随着业务的发展,以及对持续可用的追求,为了满足容量和容灾的需求,而异地带来的最大问题就是数据访问的延迟。

对于那些需要全量访问的数据,有两种方式进行异地的复制。一种是通过DB本身的复制逻辑,这种方式理论上有3秒的延迟,对于一些对数据实时性要求不高的业务场景,这种方式就够用了。有些业务场景无法容忍这么长的延时,比如访问tair缓存数据,需要较高的实时性。于是出现了基于消息进行异地数据复制的方式,在这种方式下,业务数据落地到Czone,通过消息进行异地Czone间的互相复制,达到全量数据的效果。消息复制理论上有30ms左右的延迟,当然这会受网络链路状况的影响。由于Czone的特殊地位,原则上Czone只有外部流入的消息,内部不应该主动产生消息。

所以为了支持异地的消息复制,我们需要一个全新的架构来支持异地部署。我们需要将全新的消息路由部署在Czone。跨到异地的消息先转发给“消息路由”,由“消息路由”再转发到异地的“消息路由”,然后再转发给消息中心进行投递。

示意图如下:

单元化架构 缺点 单元化架构规范_架构_03