云片RocketMQ实战:Stargate的前世今生
RocketMQ消息队列,专业消息中间件,既可为分布式应用系统提供异步解耦和削峰填谷的能力,同时也具备互联网应用所需的海量消息堆积、高吞吐、可靠重试等特性,是应对企业业务峰值时刻必备的技术。
云片由于业务特点,对消息队列的使用十分频繁,由此云片服务号从本期推文开始将发布“云片RocketMQ实战”系列文章,讲述云片根据短信业务的特点,运用RocketMQ消息队列实战经验。
本期推文《Stargate的前世今生》,由云片资深Java开发工程师周凯帆提供。
本文字数3025,预计需要阅读20分钟
云片由于其业务特点对应消息队列的使用十分频繁,这里以云片短信业务为例,短信业务的逻辑十分简单,我们只看主流程,本质就是接受用户请求,寻找合适的通道,使用cmpp/smpp协议提交给运营商。
我们可以发现,用户的每次请求要一直等待运营商的响应,这样主要的问题是:
云片的服务器再运营商返回时需要一直维护http连接
运营商的处理速率直接限制了云片的处理速率
云片的最大并发为所有供应商并发之和
这种情况下我们无法提供稳定的服务。
实际上对于用户来说并不关心具体流程他们只需将短信提交给云片即可,所以我们可以异步的处理这些发送过程,确认收到短信后就可以给用户返回结果以提高响应速度。
日常情况我们的系统流量会是一个比较平稳的值X,所以我们提供能满足的当前流量的消费能力,这样消息就不会积压。
不过随着流量的增加最终实践流量会超过我们的消费能力,这样就会出现短信送达延迟,图中虚线右边是我们不希望看到的。
所以我们在流量到达虚线前提高系统的消费能力。
我们可以看到云片对应消息队列的重度依赖,使得在微服务化的时候没有找到一个适合云片的好用的annotation组件,当时SpringCloud框架并没有对RocketMQ支持的相关组件,而RocketMQ官方github上仅有一个不成熟的项目。
对于目前重度依赖RocketMQ的短信业务我们需要一个简单易用并且能够与我们老项目中代码兼容的注解,同时还要满足各团队的不同需求,于是我们开始一个名为Stargate的组件来支持我们后续的服务化推进。
Stargate组件为什么出现?
事实上在有Stargate之前我们的项目中有一个对RocketMQ SDK的封装,它确实解决的许多问题,但是面对越来越多的生产者和消费者我们越来越难以维护,甚至于碰到不熟悉的代码我曾经花了半小时去找一个生产者的消费者在哪里,这个消费者被各种继承重写,生产者的topic是以一种极其复杂的规则生成的,而且各种配置文件散落在代码的各各角落。
然后旧的组件也十分难以迁移到新的微服务项目中,以至于有的业务线开始自己从新封装一套组件,而且他们生产者的消息难以被其他团队的消费。于是我希望做一套能够避免这些不良使用习惯的组件,并且提供强大的兼容性让大家迁移过来。
设计Stargate的目标是?
所以在设计Stargate的时候主要考虑以下几点:
简单易用
注解的方式相比直接使用RocketMQ更加清晰,上手更快,更易用,避免各种不良写法。
扩展性强
SG1提供的扩展插件能够丰富Stargate的功能,而且这个插件的开发能力是开放的,后续会提到。实际上插件功能是在2.0增加应为我发现在限制大家的使用方式后,我需要定制许多的注解来兼容各种使用场景,于是我开放了这部分能力让大家选择性的开发和使用自己需要的功能。
兼容各种老项目
通过编解码器我们可以兼容各种不同的老项目,不需要修改老项目的代码。
单元测试更方便
另外再单元测试和开发阶段,无需对外部依赖可以方便的进行mock。
Stargate组件的价值
最初的时候我简单的认为这个组件的价值在于提供了一个更方便使用RocketMQ的方式,但后续的开发中慢慢的我发现并不是这样,目前来说我认为最有价值的两点在于:
服务间异步调用的“规范”
由于它的扩展性和兼容性被各各业务线团队采用,似乎成了一个“规范”,服务之间的通信多了一种可选项。我们可以把自己的StargateProducer接口定义放在一个jar包中提供给其他人
“使用心得”的分享中心
插件的开发能力使得大家会把自己的使用模式封装成一个注解发布出来,这样许多十分巧妙的使用方法会被发布出来,而且这些都是开箱即用的,使用者只需要知道这个注解能实现什么,在发布要求上让开发者符上文档,这样就能形成一个生态,把大家的经验使用沉淀下来。
另外,Stargate对于代码结构方面的帮助也是巨大的,现在我们可以很快速的找到一个生产者的消费者在什么地方,后续甚至考虑提供IDE插件来更好的维护这些代码。
Stargate的初始化
那么我们接下来,看一下Stargate的这些设计目标是如何实现的,首先我们来看一下组件的入口,我们如何初始化Stargate的。
在应用启动时我们处理部分注解获得一个Bean的配置信息,然后向Spring注册这些Bean,我们为Producer生成代理类,创建Consumer客户端监听消息并且调用StargateConsumer处理这些消息。
生成这些的Bean的入口是从一个工厂类开始的,通常一个StargateProducer|StargateConsumer的创建会经过以下几个步骤:
事实上Stargate并不负责初始化这些生产者消费者bean,Stargate仅仅提供了创建的过程,我们把这些bean注册到Spring中然后提供一个工厂方法,由spring在适当的时候创建这些bean,维护这些bean。
这样我们在spring中就有了这些生产者接口的实例,我们可以把他注入到任何地方然后使用它们发送消息。监听他的消费者就会调用事先配置好的StargateConsumer。
编解码器
每个发送者和消费者都会在收发消息前进行编解码,这也是兼容原有项目的关键。大家可以思考一下,所有项目的都是使用RocketMQ的,本质的直接调用SDK的Send方法就能发送消息,但是老项目对于如何将一个消息变成二进制数组这是不一样的,所以我们提供编解码器的接口让大家可以替换这些转换过程的实现。
扩展接口
但是消息的编解码只能实现兼容性但是对于扩展能力的需求无法满足,所以我们再初始化过程和发送消费过程中抽象出了6个接口,让用户可以扩展自己的逻辑。
这个些接口主要用于处理”注解解析“,”RocketMQ Client创建“,”消息加工“,我们可以从下图中看到,工厂在返回一个bean前会调用这些接口的实现。消息收发阶段也会调用相应的实现。
通常情况下我们实现一个新的注解@DemoModel有这么几个流程:
实现注解处理器处理注解数据
实现Client处理器,根据注解解析的数据加工Client
实现消息处理器,根据注解解析的数据加工消息
上下文
这时会有另一个问题,我们通常的流程在解析注解获得的数据需要保存给另外两个处理器使用,我们当然不希望让用户自己处理这些数据,这会增加用户的使用成本。
于是我们定义了一个上下文的概念,上下文有这几个特点:
每个生成消费者有自己的上下文
上下文是会被继承的
举一个例子,假如我们现在所有的生产者的topic加上一个公共前缀,那么我们只需要在生产者根上下文中的topic加上这个前缀的内容,所有的生产者都会有这个前缀。
事实上在Stargate2.0开始提供扩展功能后,我停止了对core项目的功能迭代,所有的新功能以插件方式在一个名为SG1的项目的发布,而每个用户也可以扩展自己的插件上传到SG1中,以此期望形成一个生态。
另外在云片国际版YCloud上线之后我们又有一些新的挑战,YCloud主要服务海外客户我们的服务器并不在国内,但是我们的消息需要提交回国内节点消费,而且MQ都部署在国内,从香港节点到国内节点的延时让人无法接受,因为这个延时是用户能感知到的,所以我的目标是把这个延时交给消费者来承担。
如果简单的在部署一套集群或许实施起来是最快的,但是这样成本非常大,而且消费者1和消费者2的负载通常是不均衡的,如果有了第三的机房,难道每个消费者都要部署3套?
所以我们的方向是在香港节点部署一个broker,重写客户端的队列选择器,让生产者找出离自己最近的broker中的队列,而消费者消费所有队列。
其实这里对应消费者也是一样的,我们可以通过改变消费者的客户端负载均衡器来消费指定的队列,这样我们就能实现一个隔离的环境。
在后续的发展中我们将消费者使用同样的方式去指定消费指定的broker上的队列,于是就形成了图中这样的隔离的环境,这样做的好处是:
多个环境隔离正常消息不互通,达到隔离的目标
多个环境的broker仍然是一体的,如果一个消费者出现故障,另一个消费者可以代替
如果发现消费者1出现异常的话,可以临时让消费者2代替消费者1的工作保证功能正常,但是目前来说这部分功能仍然无法实现,应为我们需求有一个指挥中心告诉消费者2去消费环境1的消息。
为了实现生产者消费者之间的协作,我们需要一个指挥中心,去收集和协调全部Stargate应用的工作。
StargateCommand会充当一个指挥中心,但是它只是一个协调机制,如果没有它Stargate应用仍然会按照其原型设定的方式去运行。
云片RocketMQ实战:Stargate的前世今生的更多相关文章
- RocketMQ实战快速入门
转自:https://www.jianshu.com/p/824066d70da8 一.RocketMQ 是什么 Github 上关于 RocketMQ 的介绍:RcoketMQ 是一款低延 ...
- RocketMQ实战:生产环境中,autoCreateTopicEnable为什么不能设置为true
1.现象 很多网友会问,为什么明明集群中有多台Broker服务器,autoCreateTopicEnable设置为true,表示开启Topic自动创建,但新创建的Topic的路由信息只包含在其中一台B ...
- RocketMQ 实战之快速入门
原文地址:https://www.jianshu.com/p/824066d70da8 最近 RocketMQ 刚刚上生产环境,闲暇之时在这里做一些分享,主要目的是让初学者能快速上手RocketMQ. ...
- RocketMQ系列实战
RocketMQ实战(一)RocketMQ实战(二)RocketMQ实战(三):分布式事务RocketMQ实战(四)
- RocketMQ ACL使用指南
目录 1.什么是ACL? 2.ACL基本流程图 3.如何配置ACL 3.1 acl配置文件 3.2 RocketMQ ACL权限可选值 3.3.权限验证流程 4.使用示例 4.1 Broker端安装 ...
- RocketMQ吐血总结
RocketMQ吐血总结 架构 概念模型 最基本的概念模型与扩展后段概念模型 存储模型 RocketMQ吐血总结 User Guide RocketMQ是一款分布式消息中间件,最初是由阿里巴巴消息中间 ...
- RocketMQ扫盲篇
本篇博客主要参考: <浅入浅出>-RocketMQ 敖丙 APACHE-RocketMQ Gitee RocketMQ官方文档 RocketMQ 实战与进阶 GitChat 又是好久没有写 ...
- 面渣逆袭:RocketMQ二十三问
基础 1.为什么要使用消息队列呢? 消息队列主要有三大用途,我们拿一个电商系统的下单举例: 解耦:引入消息队列之前,下单完成之后,需要订单服务去调用库存服务减库存,调用营销服务加营销数据--引入消息队 ...
- 精华!一张图进阶 RocketMQ
前 言 大家好,我是三此君,一个在自我救赎之路上的非典型程序员. "一张图"系列旨在通过"一张图"系统性的解析一个板块的知识点: 三此君向来不喜欢零零散散的知识 ...
随机推荐
- 树链剖分 [JLOI2014]松鼠的新家
[JLOI2014]松鼠的新家 时间限制: 1 Sec 内存限制: 128 MB 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达, ...
- [ERROR]:INST-07008: Oracle 主目录(O) 位置的验证失败。用户没有创建主目录/实例位置的权限
安装weblogic12.1.3.0时,输入的安装命令是: 老是报这个错误. 百度半天好像没人报过这错……看来只有我这么粗心了…… 后来发现wls.rsp里面的Oracle_HOME指向目录错误,修改 ...
- 字符串翻转demo
1.利用char数组 public class stringfanzhaun { public static void main(String[] args) { String str="1 ...
- 看MySQL的参数调优及数据库锁实践有这一篇足够了
史上最强MySQL参数调优及数据库锁实践 1. 应用优化 1.2 减少对MySQL的访问 1.2.1 避免对数据进行重复检索 1.2.2 增加cache层 1.3 负载均衡 1.3.1 利用MySQL ...
- Storm 实时读取本地文件操作(模拟分析网络日志)
WebLogProduct 产生日志类 package top.wintp.weblog; import java.io.FileNotFoundException; import java.io.F ...
- IP地址/掩码/网关/DNS的设置与工作原理(转)
现在互联网飞速发展,工作中生活中上不了网的计算机是不可想象的,而电脑系统网络设置中的IP地址.子网掩码.默认网关及DNS服务器,怎么理解,它们是如何工作的,下面做个简单介绍. 通常的上网方式,是打开I ...
- FTP文件传输服务器原理
FTP服务器,全称File Transfer Protocol Server,是在互联网上提供文件存储和访问服务的计算机,它们依照FTP协议提供服务.FTP,文件传输协议(File Transfer ...
- ironic+nova详解
ironic+nova详解 说明: Openstack 的安装步骤省略,按照社区的文档即可搭建出一套相对稳定的使用环境.本文档基于Newton版本. 假设现在已经有一套可用的Newton环境, 以下的 ...
- mongodb的索引原理
首先说一下为什么要有索引,大家都知道mongdb是非关系型文档类型数据库,用过的人都有同一种感受,查询的效率太低,当你想提高查询效率的时候可以就需要使用索引了. 哈哈,本来想写一篇的,在网上看到了一篇 ...
- 2015.11.10 asn1学习笔记
Openssl : OpenSSL 是一个强大的安全套接字层密码库,囊括主要的密码算法.常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用. 在OpenSSL被曝出现严 ...