文章深度解读了某商业银行做消息队列选型时考虑的因素,包括关键需求、选型要点、选型原则等,同时给出了选型建议、产品对比以及典型场景和二次封装的建议。本文作者在自己丰富实践经验基础上抽象出一些方法论,供读者在做消息队列技术选型时参考。 本文主要内容包括以下方面: 1 概述 2 为什么引入消息队列
3 消息队列选型
4 二次封装建议 5 典型场景
6 经验总结和建议 作为金融企业对公众提供服务一定要保证其可用性,尽量做到更多个9(一般SLA中描述的高可用性99.99%,中的9越多代表全年服务可用时间越长服务更可靠,停机时间越短),随着软件系统的复杂度越来越高,故障是不可避免的。这就需要企业实现整体的弹性架构(Resilient Architecture),为应对故障而设计。 然而,常见的RPC、RMI企业集成技术,因为是同步请求,常因为执行方失败、超时等因素而影响最终用户体验,而且很多故障是无法彻底消除的。而且RPC和RMI调用需要服务的消费方和服务的提供方同时在线,并且双方需要通过某种机制确认彼此的调用关系,因为存在这些弊端,就导致了面向消息的中间件(MOM)的产生,通过在企业架构中引入消息中间件,确保在故障发生时,受此影响的系统部分在一个很小的范围内。 消息中间件就是在分布式系统中间引入一个透明的中间层,隔离服务的提供方和消费方。 2.1 何为消息队列消息队列(Message Queue,MQ)是一种不同应用程序之间(跨进程)的通信方法,用于上下游应用程序之间传递消息。我们拆分来看:
这样就实现了上游与下游之间的解耦,上游向MQ发送消息,下游从MQ接收消息,上游下游互不依赖,它们只依赖MQ。因为有队列的存在,MQ可在上下游之间进行缓冲,把上游信息先缓存起来,下游根据自己的能力从MQ中拉取信息,起到削峰的作用。 2.2 消息队列的优势1 解耦1)什么是耦合 高内聚低耦合,是软件工程中的概念,这里的低耦合是指各个组件之间,尽可能相互独立。通俗一点的理解就是,增加模块间调用透明化,最高的透明度就是不用知道彼此的存在,因此减少接口的复杂性、规范调用的方式及传递的信息,降低产品各模块的依赖,提高重用程度。 2)如何解耦 在企业整体架构中解耦,主要设计两个方面:一是简化减少交互,二是增加一个中间层实现两方的隔离,MQ就是其中的中间层(如下图所示)。引入MQ后生产者和消费者不必知道彼此的存在也不必同时在线,主要交互流程如下:
2 削峰填谷 由于系统闲忙分布不均,QPS常相差几十倍甚至更高,特别是在遇到营销活动时,瞬间流量很可能超过后端系统的承载能力,这就要考虑通过消息中间件来缓冲,MQ客户端实例根据自己的处理能力从MQ服务器拉取消息,以此来减轻或消除后端系统的瓶颈。 (图片来源:https://github.com/alibaba/Sentinel/wiki/Sentinel-为-RocketMQ-保驾护航) 3 异构集成由于各种原因,我们在企业信息化建设过程中,都会面临软件产品来自不同的厂家只解决某特定领域的问题,这些产品因为封闭的架构无法对外提供服务或缺少核心开发而无法做大的改造,这就造成了彼此之间很难集成。通过引入MQ可以部分解决该问题,只需要在某个环节生产一条消息,或者根据消息做出具体的响应,只需与MQ对接,不必与其他系统做一对一的对接。 4 异步隔离为了提供金融服务的整体弹性,需要隔离内部、外部系统间的依赖。如支付通知分为两种,一种是同步通知,这时API调用会因为网络故障而超时,因为服务提供方处理能力限制而得不到及时响应等多种因素影响,另一种是异步通知,在一定时效范围内最终通知到即可,从而提供提高最终用户的体验和交易成功率,提高业务的整体生产率。 2.3 消息队列的不足凡有收益必有代价,MQ也有其不足:
所以在软件的正常功能开发中,并不需要去刻意的寻找消息队列的使用场景,而是当出现性能瓶颈时,去查看业务逻辑是否存在可以异步处理的耗时操作,如果存在的话便可以引入消息队列来解决。否则盲目的使用消息队列可能会增加维护和开发的成本却无法得到可观的性能提升,那就得不偿失了。 但凡选择就会受到主观和客观两个因素的影响。我们如何尽量客观的进行架构和框架选型,而避免先有结果而后找理由的文字游戏,下面我分享下我们做MQ选型的过程(这里不是说主观就是不好的,但作为工程师凡事做结构化和量化还是有必要的)。 3.1 关键需求
3.2 其他需要考虑的因素
3.3 选型要点及原则
3.4 选型建议 为未来最少三年或五到十年来选择,因为TedNeward在JAVA 消息服务的序言中总结了技术熟悉的过程4个阶段(门外汉、探索者、熟手、大师)。选型到全范围推广结束一年左右的时间就过去了,到大家熟悉和精通又一年过去了,谁都不想在刚熟悉还没用好,当前的产品就不满足要求了,又要重新来过。 区分关注点,确保只针对核心关注点进行选择。给出选择的deadline,并按时进入到项目实战准备,再多的理论分析,都不如真正使用过后的感受深入,产品需要成长、团队成员同样需要成长,既然路在远方就赶紧起程。 3.5 候选产品比较1 产品特性比较
2 测试建议功能测试:建议搭建POC环境进行验证,除验证相关功能性指标有没有,还要验证好不好用。所以在测试时要基于MQ提供的功能构建使用场景进行业务功能实现的验证。性能测试:其实性能测试涉及的各方面因素比较多,如:基于什么样的环境,做了哪些配置,采用什么样的压测脚本和报文来做压力测试?比较指标:除TPS(发送者TPS、消费者最终处理业务的TPS)、延时、支持多少同时在线链接(生产者数据量、消费者数据量)、Topic配置(Topic数量以及每个Topic队列数量与生产者、消费者数据量的关系)、服务器的性能指标(cpu、内存、磁盘io、网络io)如何等也是需要考量的。 疲劳测试:在一定压力下持续运行24小时、一周或更长时间。要重点关注稳定性、服务器的各项指标、是否有缓慢增长的趋势等。 重启或故障演练:分别对注册中心NameServer、Broker、Producer、Consumer的实例进行部分重启(或直接kill)或全部重启(或直接kill)、磁盘故障、网络故障等,查看应用的影响,如:在RocketMQ服务是否可以恢复,生产者消费者是否可以恢复服务,消息是否有丢失,消息是否有重复等。 3.6 选择RocketMQ的原因
我们最终选择RocketMQ的主要原因如下:
封装主要是对业务、技术和数据进行抽象和封装,封装具有如下优点:
将规范封装到基础代码中以便在企业内部统一交互标准,具体的规范包括:
通过赋义编码规范可以通过名称定位到所属项目、模块等业务场景,以便在出现未知问题时可以快速协调人员进行处理,当然对topic、生产者、消费者等原数据管理也是必要的,毕竟命名规范能保留的信息有限。通过命名规范还可以避免冲突,比如topic的冲突会或误会导致消息无法正常消费或者业务流转等问题,消费者GroupID冲突会导致消息丢失等问题。 通过封装和定制化增强管理功能如批量信息查询、批量信息重发、消息对账等。 RocketMQ是提高整体服务弹性的重要基础中间件,在个类金融交易中承担着重要的角色。4.1 支付场景 下面以活期账户转出服务场景为例来讲解。
这样各服务回归到本来应该的样子,账户转出服务不用关注于其它系统对它的依赖,只需要产生账户转出事件的消息,有需要的服务各自去订阅这个消息就好了,相互不受影响。 4.2 第三方延时调用场景在与银行外部系统对接的时候,会有需要在发送服务请求N秒后,去获得响应结果的异步请求。在使用RocketMQ的延时消息前,都是通过将数据落地到数据库或Redis缓存中,然后通过定时轮询任务来操作。这样做有以下缺点:
使用RocketMQ后有以下优点:
不过,当前版本还不支设置时间精度,只能按照特定的messageDelayLevel来设置,这就要在搭建RocketMQ时提前最好延时级别的规划或者对RocketMQ延时源码进行扩展以支持指定时间精度。
当故障是不可避免的,就需要在应用程序设计的时候考虑通过一系列机制具备自我管理、自我恢复、自我配置等自治功能,随着云原生架构的流行,面对负载的加重和不断发生的各类故障,MQ不会是弹性系统设计的唯一选择,但也许是一个不错的选择,值得一试。 声明:文章谨代表作者观点,与所在平台无关。 作者简介:金融业老兵,十余年金融行业工作经验,爱思考和分享,维护公众号【聊聊金融】(dhjr_it)。 |
|
来自: 刘振东 > 《RocketMQ实践》