源宝导读:移动PaaS项目的异步场景中,随着订阅主题数的增加,会出现开发维护成本高、管理难度大等问题,本文将分享如何通过构建面向业务的微服务消息总线应对这些问题。
一、背景
面向业务的消息总线本质上是对消息队列进行二次封装,而不是让各业务服务直接对接消息中间件。在微服务架构设计下,面向业务的消息总线是服务间异步通信、解耦的核心基础设施。
二、为什么需要消息总线
在没有消息总线前,移动PaaS项目中的异步请求都是通过直连RabbitMQ来实现,PHP开发的服务往往需要借助Swoole之类的第三方扩展来实现消费端常驻进程消费。当异步任务不多的时候没有问题,但随着订阅主题数的增加,这种客户端消费模式逐渐显现出以下几个缺点:
开发成本高,需要业务服务引入消息中间件SDK需要关注消息中间件的各种复杂繁琐的配置,不同微服务的实现有大量重复逻辑。
维护成本高,PHP的业务服务需要起很多消费容器来跑多进程消费,浪费系统资源,发布部署很麻烦。多语言下的消费实现方式不统一。
管理难度大,随着订阅关系复杂,Topic日益增多,服务之间的订阅关系变得不清晰。
扩展成本高,无法统一消息系统扩展功能,如路由、延时、重试、消费确认等。
从实际业务角度出发,对整个移动PaaS项目中涉及消息通信的业务场景进行梳理,得出以下几个核心需求点:
集中的消息发布入口,生产端无需关注消息系统的实现细节和复杂配置。
集中化的微服务间订阅关系维护,通过在统一的面板上管理维护订阅关系。
集中化的消息消费,通过集中消费消息,根据微服务间的订阅关系来推送消息。
支持多种协议gRPC、http。
总体来说,直接使用消息系统可以被看成是一个面向技术的接入方式;而消息总线则期望通过隐藏消息中间件的内部细节,实现一个面向业务的接入方式。
三、架构设计和技术实现
3.1、架构设计
消息总线隐藏了消息发送、超时处理、消费负载、通信等一系列问题。对于使用者来说,只需要调用一个http或者gRPC接口就能发送消息,无需集成消息系统SDK。在PaaS2.0中消息总线使用RabbitMQ 作为消息引擎,实现了消息生产端的集中发送,并且通过RabbitMQ 的死信队列实现对消息的超时控制。下图为PaaS2.0中消息总线的架构图。
3.2、技术实现
统一消息格式
提供简单易用的消息体格式,使用者可以很方便的完成一条消息的发送。
{
"id": "5675682526732228", //消息的id
"timeout": 30, //超时时间
"topic": "event.workspace.delete", //消息主题
"content": {} //消息内容
}
统一声明交换机
使用死信队列来处理消息超时
RabbitMQ的ttl超时属性可以设置在消息上也可以设置在队列上,但是设置到消息上时消息的超时校验只有在消息被消费时才能生效,这就会导致超时控制不精准。所以通过设置超时队列将不同的超时时间设置到不同的队列上,并且绑定死信队列,这样消费端在消息超时的时候就能得到通知。
PaaS2.0中实现了消息生产端的集中发送,不仅统一了消息体的格式而且也简化了消息超时控制。但是仍然没有解决消费订阅管理、集中消费的问题。
作为PaaS平台,必须具备开放能力,服务间的通信边界可能会延伸到系统间的通信,比如支持webhook。所以集中式消息消费,消息订阅关系管理成为消息总线迭代的方向。
下图为基于消息总线实现的webhook。
MessageBusBroker 消息发送端服务 用于接收消息写入MQ。
MessageBusDeliver 消息投递服务 用于消费MQ中的消息根据订阅关系触发消息通知。
MessageBusAdmin 消息总线管理服务 用于服务管理、主题管理、订阅关系维护以及配置参数调整。
四、2.0版消息总线架构设计
2.0版本的消息总线主要屏蔽了消息发送、存储、消费负载、通信、高可用等一系列技术问题,对业务开发者来说只需要调用SDK即可,简化了接入流程并提升了可靠性。同时在PaaS系统中,消息总线也作为WebHook能力的基础设施。
消息总线整体架构图如下图所示:
Publish Service通过集成SDK向Message发送消息。
Deliver Service通过订阅关系向相关的服务和站点发起通知请求实现webhook。
消费端服务通过特殊状态码来完成消息确认。
消费端的高可用保证
为了保证消费时的高可用,Deliever除了在负责进行消费协议转换之外,通过一些策略来保证消费端的高可用。
熔断限流,消费在消息一段时间内失败数据超过阈值时,停止对队列的消费,避免由于服务抖动或者线上故障引起的大面积消息消费失败。
自恢复,熔断后Deliver服务会对应用服务健康度进行监控,在服务恢复后可自动恢复消费。
失败重试,消息总线服务发生故障时,可对期间的失败消息采用重试策略进行重试,在业务应用消费产生异常时,可在订阅消息时指定是否进行重试
优雅重启,Deliver可实现优雅重启和退出,保障当前正在消费的消息都处理完成后才退出进程。
五、总结
面向业务的消息总线设计的目标,本质上是为了服务间解耦,降低业务开发的复杂度,让业务开发不去关注消息通信细节,从而实现业务的快速迭代,消息系统也可以根据不同的业务场景选用不同的消息引擎。消息总线的设计重点和难点集中在消费端的处理。
------ END ------
作者简介
段同学: 后端研发工程师,目前负责天际移动PaaS平台的研发工作。
也许您还想看