mq 不仅是削峰填谷,也不仅是解耦服务,还有降低代码复杂性、增加稳定性的作用。中间件是一个稳定的、没有逻辑的、仅仅存储数据的。
现象
比如我们代码中安置逻辑里的 resource 的同步。
节点定时上报给 zoneleader,为了避免重复上报,节点自身又缓存了资源信息,每次上报前,先计算当前资源信息,然后和上一次缓存的资源信息对比,如果有差异,再汇报。
zoneleader 还会变。
上面两点,带来的复杂性:
- zoneleader 变了之后,节点得知道;
- 节点得区分 zoneleader 是否变化了,变了就直接上报资源信息;
- 节点不知道 zoneleader 用的资源信息是什么,说不定自己的缓存因为各种原因就不对呢;
- 处理异常情况能力弱。比如 zoneleader 因为个别原因更新失败,后续节点因为缓存的原因就不重试了。
这种方式虽然没有中心化的依赖问题,但是每个功能都需要处理上述类似的问题。
这是一种繁琐的、让代码复杂性大幅膨胀的方式,也是一种功能之间重复的、却不能统一处理的多余。
也是客户端和服务端相互紧密耦合的一种方式。
用中间件的方式
如果用中间件的方式:
- 客户端可以拉下来和当前资源对比;
- 服务端定期从中间件拉取资源即可;
- 中间件是一个稳定的、没有逻辑的、仅仅存储数据的。
所以:
- 客户端的逻辑只需要客户端处理,不变接口就不会影响服务端;
- 服务端也一样,自己处理逻辑,不用管客户端;
- 节点也不用关心 zoneleader 是不是变化了,它只想一个固定的中间件地址推送就行了;
- zoneleader 变化了,也不用想办法通知到其他节点,存储到中间件就行。
好处:
- 解耦;
- 不会相互影响了;
- 节点也知道当前使用的资源信息是什么样的,可以对比。
中间件依赖本身可以通过各种高可用方式保证其可用性,在现在已经不是什么主要矛盾或问题了。
小结
- mq 不仅是削峰填谷,也不仅是解耦服务;
- 还有降低代码复杂性、增加稳定性的作用;
- 中间件是一个稳定的、没有逻辑的、仅仅存储数据的;
- 客户端和服务端通过中间件解耦,互不影响;
- 中间件依赖可以通过高可用方式保证可用性,不是主要矛盾。