微服务架构已成为了互联网的热门话题之一,而这也是互联网技术发展的必然阶段。然而,微服务概念的提出者 Martin Fowler 却强调:分布式调用的第一原则就是不要分布式。数据库
纵观微服务实施过程当中的弊端,能够推断出做者的意图,就是但愿系统架构者可以谨慎地对待分布式调用,这是分布式系统自身存在的缺陷所致。但不管是 RPC 框架,仍是 REST 框架,都由于驻留在不一样进程空间的分布式组件,而引入了额外的复杂度。于是可能对系统的效率、可靠性、可预测性等诸多方面带来负面影响。服务器
信用算力自2016年开始实施微服务改造,经过消息队列(Message Queue),后文简称MQ,来规避微服务存在的缺陷,实现金融级数据服务。如下是一些使用场景和心得。架构
先来看一个当前的真实业务场景。框架
对于经过信息流获客的企业而言,当用户注册时,因业务需求会调用用户服务,而后执行一系列操做,注册 -> 初始化帐户信息 -> 邀友奖励发放 -> 发放优惠券 -> ... -> 信息流数据上报。异步
用户服务的开发人员压力很是大,由于须要调用很是多的服务,业务耦合严重。若是当时帐户服务正在执行发版操做,那么初始化帐户动做会失败。然而平台通过不断的迭代更新,后续又新增了一个签到业务,新注册用户默认签到一次。这就须要修改用户服务,增长调用签到服务的接口。每当遇到此种状况,开发用户服务的同窗就很是不爽了,为何老是我?新增签到业务和用户服务又有什么关系?分布式
为解决此类重度依赖的问题,咱们在架构层面引入了 MQ,用来规避微服务之间重度耦合调用的弊端。新架构以下图:微服务
用户完成注册动做后,只须要往 MQ 发送一个用户注册的通知消息,下游业务如须要依赖注册相关的数据,订阅注册消息的 topic 便可,从而实现了业务的解耦。性能
看完上述真实的案例后,你们可能产生疑惑,到底什么是 MQ,使用 MQ 又有什么好处?适合使用 MQ 的场景和不适合使用 MQ 的场景有哪些不一样?spa
简单来讲,MQ(MessageQueue)是一种跨进程的通讯机制,用于上下游传递消息。3d
适合使用 MQ 的场景有:
一、上游不关心下游执行结果,例如上述案例中用户注册后,咱们并不关心帐户是否初始化,是否上报了信息流等;
二、异步返回执行时间长:例如上述案例中,当邀友奖励发放,须要经历不少风控规则,执行时间比较长,可是用户并不关注奖励什么时候发放。
不适合使用MQ场景
调用方实时关注执行结果,例如用户发起注册动做后,须要马上知道,注册结果是成功仍是失败,这种须要实时知道最终执行结果的场景,就不适合使用MQ。
一、解耦
二、可靠投递
三、广播
四、最终一致性
五、流量削峰
六、消息投递保证
七、异步通讯(支持同步)
八、提升系统吞吐、健壮性
目前业内比较主流的 MQ 包括 RocketMQ、ActiveMQ、RabbitMQ、Kafka等,关于性能、存储、社区活跃度等各方面的技术对比已经不少,本文再也不重复。
但咱们发现经过简单的选型对比,很难抉择到底选择哪款MQ产品。由于金融行业对于数据一致性以及服务可用性的要求很是高,因此任何关于技术的选项都显得尤其重要。
经调研,如微众银行、民生银行、平安银行等国内知名的互联网银行和直销银行表明,都在使用 RocketMQ,且 RocketMQ 出生在阿里系,经受过各类生产压力的考验,很是稳定。而且,目前此项技术已经捐增给 Apache 社区,社区活跃度很是高。另外 RocketMQ 开发语言是Java,开发同窗遇到解决不了的问题点,或者不清楚的概念,能够直接 Debug 源码。通过多方面的比较,咱们选择 RocketMQ 做为规避微服务弊端的利器。
MQ 是一种跨进程的通讯机制,用于上下游传递消息,目前信用算力将 RocketMQ 应用于解耦、流量削峰、分布式事务的处理等几个场景。
一般解耦的作法是生产者发送消息到 MQ,下游订阅 MQ 的特定 topic,当下游接收到消息后开始处理业务逻辑。
那么,消息发送方到底应该是由谁来承担?是服务提供者在处理完RPC请求后,根据业务需求开始发送消息吗?但此刻开发人员就会抱怨为何老是我?为何处理完业务后须要发送 MQ?
为此,在解耦的过程当中经过订阅数据库的 BinLog 日志,开发了一套 BinLog 日志解析模块,专门解析日志,而后生成 JSON 字符串后发送消息到 MQ,下游订阅 MQ 便可。流程以下:
目前全部须要依赖下游服务的业务线,其数据变更都采用此方案。
方案优缺点:
优势:
一、服务之间依赖彻底解耦,任何基于注册行为的业务变动,都无需依赖上游,只需订阅MQ便可;
二、系统的稳定性和吞吐量增长了,用户注册的响应时间缩短了;
缺点:
一、引入MQ后系统复杂性增长,维护成本增长;
二、从注册开始到所有数据初始化结束的总体时间增长了;
每逢遇到会员日的时候,平台会发送大量的会员福利活动通知,以短信、站内信、PUSH 消息的方式通知注册用户。全部的消息会在很短的时间所有推送到消息中心,同时正常的业务通知任然有大量业务消息推送到消息中心。为保障平台的稳定性和可靠性,在消息中心前置了多种 topic,如短信、推送、站内提醒。消息中心接收到消息后会所有写入不一样 topic 的 MQ,多个消费者来消费并把信息推送给终端用户。
用户在平台上支付他订购某种业务的时候,须要涉及到支付服务、帐户服务、优惠券服务、积分服务,在单体模式下这种业务很是容易实现,经过事务便可完成,伪代码以下:
然而,在微服务的状况下,本来经过简单事务处理的却变得很是复杂,若引入两阶段提交(2PC)或者补偿事务(TCC)方案,则系统的复杂程度会增长。
信用算力的作法是经过本地事务 + MQ 消息的方式来解决, 虽然 RocketMQ 也支持事务消息,可是其余主流 MQ 并无此项功能,因此综合考虑采用以下方案:
方案优缺点:
优势:
一、用最小的代价实现分布式事物,以达到数据最终一致性;
二、方案很是灵活,任何环节均可以人为控制;
缺点:
一、复杂性增长了,业务操做的时候须要写入 tc_message 表以及发送 MQ,同时还须要考虑状态超时未变动的补发机制以及告警处理机制;
二、用户看到的数据,存在有短暂不一致的状况;
使用 RocketMQ 3年多了,整体来讲运行的很是稳定,基本上没有发生过生产事故,下面说说这几年使用下来的心得体会:
一、一个应用尽量用一个 Topic,消息子类型用 tags 来标识。Topic 名称和 Tags 名称能够自行设置。Producer,Consumer都须要规范,要作到见名知意。发送消息时候必须携带 Tags,消费方在订阅消息时,才能够利用 Tags 在 Broker 作消息过滤。
二、每条消息在业务层面有惟一标识码,方便在系统出现异常的状况,能够经过业务维度查询。举个栗子,当用户在平台注册成功后,会以 Topic 和 UserID 做为惟一标识码(topic_user_10011),服务器会为每一个消息建立索引,该消息会持久化入库,以防未来定位消息丢失等问题。下游收到消息后会以 Topic+Key 方式来记录消费行为,包括消息日期、当前机器IP地址、处理结果等;也能够经过 Topic+Key 的方式来查询这条消息内容,包括消息被谁消费,以及这条 MQ 在每一个环节的处理状态。
三、消息发送成功或者失败,都须要记录 log 日志,且必须打印 sendresult、MsgID、惟一标识码。
四、因为上游会作消息重试机制,因此下游消息必需要作幂等处理。
五、须要封装 MQ 的 API 在封装后,API 需屏蔽底层 MQ 的特性,开发人员无需关注究竟是用的哪一个 MQ 来支持本地分布式事物、MQ 消息自动入库、自动打印日志,减小开发人员操做成本。
总的来讲,MQ 是一个互联网架构中常见的解耦利器,在这3年中,信用算力在微服务中一直使用 MQ 来为金融客户提供高质量的数据服务。虽然 MQ 不是惟一方案,可是从目前阶段来看,的确是一种很是不错的解决方案。
原文连接 本文为云栖社区原创内容,未经容许不得转载。