乐趣区

关于阿里云:RocketMQ-50无状态代理模式的探索与实践

本文作者:金吉祥,Apache RocketMQ PMC Member,阿里云智能高级技术专家

背景

首先,让咱们来看下是遇到了哪些痛点问题,促使咱们去摸索一种无状态代理的 RocketMQ 新架构的;

RocketMQ 领有一套极简的架构,多语言客户端通过自定义的 Remoting 协定与后端 NameServer 和 Broker 建设 TCP 长连贯,而后进行音讯的路由发现以及残缺的音讯收发。这套架构的劣势是:架构极简,客户端 与 Broker 通过 TCP 直连的模式,领有较高的性能以及较低的提早。同时,这套架构采取的是队列模型,非常适合基于队列批量高速拉取音讯的场景。

同时,RocketMQ 在上云过程中面临了各种各样的挑战。

首先,云上用户须要更为丰盛的业务语义音讯,包含事务、定时、程序以及死信等。为了满足用户的业务侧需要,须要在原先架构的客户端侧和 Broker 侧别离进行开发,用户必须降级客户端之后能力享受新性能。

其次,上云过程须要面对更为简单的网络环境,不同场景下须要不同类型网络的接入。有些用户为了便捷性,冀望可能交付公网的接入点,让不同地区的消费者、发送者都能连贯到同一个音讯服务;而另一种用户为了安全性,须要内网接入点来隔离一些非法的网络申请;RocketMQ 原先的架构在应答多网络类型的接入诉求时,老本是比拟高的,多网络类型的接入必须同时笼罩 NameServer 和 Broker 的每一台机器才行。比方咱们须要对外部 Broker 进行扩容场景下,如果原先的 Broker 领有多种类型的网络接入诉求,那么新扩容的 Broker 也须要额定绑定上多种类型的网络接入点之后能力失常对外交付。

做下总结,面对上云的挑战,此前的架构逐步暴露出了如下诸多痛点:

① 富客户端状态:客户端蕴含了大量企业级个性。用户必须降级客户端能力享受新性能,过程非常漫长。且同样的性能交付必须在多个多语言版本里都进行适配能力满足多语言客户端的接入,工作量微小。

② 客户端与 Broker 所有节点的直连模式满足多类型网络接入的老本较高。

③ 依照队列进行负载平衡和音讯拉取,后端扩缩容时会触发客户端 rebalance,导致音讯提早或反复生产,消费者会有显著的感知;此外,基于队列的模型非常容易导致一个用户饱受困扰的问题:单个故障消费者生产卡住会导致音讯在服务端大量沉积。

RocketMQ5.0 无状态代理模式

为了解决上述痛点,RocketMQ 5.0 提出了无状态代理模式。

新架构在原先的客户端和 Broker 两头插入了代理层。策略上是将客户端的无状态性能尽可能下移到代理层,同时也将 Broker 侧的无状态性能尽可能上移到代理层。在这里,咱们将客户端的原有的负载平衡机制、故障隔离、push/pop 生产模型下移到了代理层,将 Broker 的访问控制、多协定适配、客户端治理以及 NameServer 的音讯路由能力上移到了代理层,最终打造出的代理层的丰盛能力,蕴含访问控制、多协定适配、通用业务能力、治理能力以及可观测性等。

在构建代理层的过程中,咱们必须保持的一个准则就是:客户端和 Broker 往代理层迁徙的能力必须是无状态的,这样能力保障后续代理层是能够随着承接的流量大小进行动静扩缩容的。

在引入无状态代理层后,RocketMQ 原先客户端、Broker 的直连架构就演变为上图的无状态代理模式架构:

从流量上看,代理层承接了客户端侧所有流量,Broker 和 NameServer 不再间接对用户裸露,用户惟一能看到的组件只有代理层(Proxy)。

这里,Proxy 的职责包含以下几个方面:

  • 多协定适配: Proxy 具备解析和适配不同协定的能力,蕴含 remoting、gRPC、HTTP 以及后续可能衍生进去的 MQTT 和 AMQP 等协定。Proxy 对不同协定进行适配、解析,最终对立翻译成与后端 Broker 和 NameServer 之间的 remoting 协定。
  • 流量治理和流量散发: Proxy 承接了客户端侧所有流量,因而可能很轻松地基于某些规定辨认出以后流量的个性,而后依据肯定的规定将流量散发到后端不同的 Broker 集群,甚至进行精准的流量管制、限流等。
  • 性能扩大:包含访问控制比方容许哪个用户拜访后端 Broker 集群中的哪个 Topic、音讯轨迹的对立收集以及整体的可观测性等。
  • Proxy 能表演 NameServer,交付给客户端查问 TopicRoute 的能力。
  • Proxy 可能无缝兼容用户侧的 Pop 或者 Push 生产模式:在 Proxy 和 Broker 侧采纳 Pop 生产模式来防止单个队列被锁导致音讯在服务端沉积的历史遗留问题。

同时,咱们也能够看到 Proxy 具备以下两大个性:

① 无状态,可依据用户以及客户端的流量进行程度扩缩容。

② 计算型,比拟耗费 CPU,因而在部署时须要尽可能给 Proxy 调配多些 CPU。

做下总结,无状态代理模式解决了原先架构的多个痛点:

① 将客户端大量业务逻辑下移到代理层,打造出轻量客户端。同时,依靠于 gRPC 协定的标准化以及传输层代码主动生成的能力,可能疾速适配多种语言的客户端。

② 客户端只会与 Proxy 层连贯,针对多网络类型接入的诉求,能够将多网络类型绑定到 Proxy 层,因为 Broker 和 NameServer 不再间接对客户端裸露,转而只需对 Proxy 裸露内网的连贯即可,多网络类型接入的诉求能够只在 Proxy 这个组件就关闭掉;同时,Proxy 的无状态的个性保障了多类型网络接入是与集群规模无关的。

③ 生产模式进行了无感知切换,无论客户端侧抉择的是 Pop 还是 Push 生产模式,最终对立替换为 Proxy 与 Broker 侧的 Pop 生产模式,防止单个客户端生产卡住导致服务端音讯沉积的历史问题。

RocketMQ 无状态代理模式技术详解

新架构在客户端和 Broker 之间引入了代理层,客户端所有流量都须要多一跳网络、多经验一次序列化 / 反序列化的过程,这对端到端音讯提早敏感的用户是极其不敌对的,因而咱们设计了合并部署状态。

合并部署状态下,Proxy 和 Broker 依照 1:1 的形式对等部署,且 Proxy 和 Broker 实现过程内通信,满足低提早、高吞吐的诉求。同时,Proxy 依然具备多协定适配的能力,客户端会与所有 Proxy 建设连贯进行音讯收发保障可能生产到所有音讯。

代码实现上,咱们通过结构器来实现合并部署和拆散部署的两种状态。用户可自行抉择部署状态。如果用户抉择合并部署的状态,则在构建 Proxy 处理器之前,会先结构 BrokerController,并向 Proxy 的处理器注册, 实质上是为了告知 Proxy 处理器:后续的申请往我这个 BrokeController 发;如果用户抉择拆散部署模式,则毋庸构建 BrokerController,间接启动 Proxy 处理器即可。

对于这两种部署模式的比拟,首先,合并部署和拆散部署同时具备了多协定的适配能力,都可能解析用户侧和客户端侧的多协定申请;且具备模型形象,可能解决富客户端带来的一系列痛点。

部署架构上,合并部署是一体化的架构,易于运维;拆散部署是分层的架构,Proxy 组件独立部署,Proxy 和 broker 按业务水位别离进行扩缩。

性能上,合并部署架构少一跳网络和一次序列化,有较低的提早和较高的吞吐;拆散部署多一跳网络和一次序列化,开销和提早有所增加。提早具体减少多少次要依赖于 Proxy 和 Broker 之间的网络提早。

资源调度上,合并部署状态下比拟容易取得稳固的老本模型,因为组件繁多;拆散部署状态下 Proxy 是 CPU 密集型,Broker 和 NameServer 也逐步进化成存储和 IO 密集型,须要调配比拟多的内存和磁盘空间,因而须要进行细粒度的调配和资源布局,能力让拆散部署状态资源的利用率达到最大化。

多网络类型接入老本上,合并部署老本较高,客户端须要与每一个 Proxy 正本都尝试建设连贯,而后进行音讯收发。因而,多网络接入类型场景下,Proxy 进行扩缩容时须要为每台 Proxy 绑定不同类型的网络;拆散部署模式老本较低,仅须要在独立部署的 Proxy 层尝试绑定多网络类型的接入点即可,同时是多台 Proxy 绑定到同一个类型的网络接入点即可。

针对业务上的选型倡议:

如果对端到端的提早比拟敏感,或冀望应用较少的人力去运维很大集群规模的 RocketMQ 部署,或只须要在繁多的网络环境中应用 RocketMQ 的,比方只需内网拜访,则倡议采纳合并部署的模式。

如果有多网络类型接入的诉求比方同时须要内网和公网的拜访能力或想要对 RocketMQ 进行个性化定制,则倡议采纳拆散部署的模式,能够将多网络类型的接入点关闭在 Proxy 层,将个性化定制的革新点也关闭在 Proxy 层。

社区新推出的 PopConsumer 生产模式和原先的 PushConsumer 生产模式存在较大区别。PushConsumer 是基于队列模型的生产模式,但存在一些遗留问题。比方单个 PushConsumer 生产卡住会导致服务端侧音讯沉积。新推出的 Pop 生产模式是基于音讯的生产模型,PopConsumer 会尝试和所有 broker 连贯并生产音讯,即使有一个 PopConsumer 生产卡住,其余失常的 PopConsumer 仍然能从所有 broker 里拉取到音讯进行生产,不会呈现音讯沉积。

从 Proxy 代理层角度看,它可能无缝适配 PushConsumer 和 PopConsumer,最终将两种生产模式都映射到 Pop 生产模式,与后端 Broker 建设生产连贯。具体来看,PushConsumer 里的 pull 申请会被转成 PopConsumer 生产模式里的 pop 申请,提交位点的 UpdateConsumeOffset 申请会被转换成音讯级别的 ACK 申请,SendMessageBack 会被转换成批改音讯的不可见工夫的申请,以达到从新被生产的目标。

Proxy 最上层为协定的适配层,通过不同的端口对客户端裸露服务,不同协定通过不同端口申请到 Proxy 之后,协定适配层会进行适配,通过通用的 MessagingProcessor 模块,将 send、pop、ack、ChangeInvisibleTime 等申请转换成后端 Remoting 协定的申请,与后端的 Broker 和 NameServer 建设连贯,进行音讯收发。

多协适配的劣势有以下几个方面:

① 减速了 RocketMQ 的云原生化,比方更容易与 Service Mesh 相结合。

② 基于 gRPC 的规范性、兼容性及多协定多语言传输层代码的生成能力,打造 RocketMQ 的多语言瘦客户端,可能充分利用 gRPC 插件化的连贯多路复用、序列化 / 反序列化的能力,让 RocketMQ 客户端更加轻量化,将更多精力聚焦在音讯畛域的业务逻辑。

做下技术计划的总结:

无状态代理模式通过客户端下移、Broker 侧上移无状态的能力到代理层,将访问控制、客户端治理、流量治理等业务收敛到代理层,既可能满足疾速迭代的诉求,又能对变更进行收敛,更好保障整个架构的稳定性:有了分层架构之后,更多业务逻辑的开发会聚焦在 Proxy 层, 下一层的 Broker 和 NameServer 趋于稳定,能够更多地关注存储的个性。Proxy 的公布频率远远高于底层 Broker 的公布频率,因而问题收敛之后,稳定性也失去了保障。

多协定适配,基于 gRPC 的规范性、兼容性以及多语言传输层代码生成的能力打造 RocketMQ 的多语言瘦客户端。

Push 到 Pop 生产模式的无感知切换,将生产位点的保护收敛到 Broker,解决了繁多消费者卡住导致音讯沉积的历史遗留问题。

另外,咱们也尝试摸索了可分可合的部署状态,保障同一套代码可分可合,满足不同场景下对性能部署老本、易运维性的差异化诉求。在大部分的场景下,仍然倡议抉择合并部署的状态。如果有对多网络类型接入的诉求,或对 RocketMQ 有极强的定制化诉求,则倡议抉择拆散部署的状态,以达到更好的可扩展性。

代理层无状态的个性,极大升高了适配多类型网络接入诉求的老本。

将来布局

将来,咱们冀望 RocketMQ 底层的 Broker 和 NameServer 更多聚焦在存储的个性上,比方业务型音讯存储的事务、定时、程序等,疾速构建音讯索引、打造一致性多正本晋升音讯可靠性、多级存储来达到更大的存储空间等。

其次,对无状态代理层按照可插拔的个性开发,比方对访问控制、形象模型、协定适配、通用业务能力、治理能力等按模块进行划分,使语义更丰盛,可依照不同场景的诉求可插拔地部署各种组件。

最初,咱们冀望这一套架构可能反对阿里云上的多产品状态,致力于打造云原生音讯十分丰盛的产品矩阵。

退出 Apache RocketMQ 社区

十年铸剑,Apache RocketMQ 的成长离不开寰球靠近 500 位开发者的积极参与奉献,置信在下个版本你就是 Apache RocketMQ 的贡献者,在社区不仅能够结识社区大牛,晋升技术水平,也能够晋升集体影响力,促成本身成长。

社区 5.0 版本正在进行着热火朝天的开发,另外还有靠近 30 个 SIG(兴趣小组)等你退出,欢送立志打造世界级分布式系统的同学退出社区,增加社区开发者微信:rocketmq666 即可进群,参加奉献,打造下一代音讯、事件、流交融解决平台。

微信扫码增加小火箭进群

另外还能够退出钉钉群与 RocketMQ 爱好者一起宽泛探讨:

钉钉扫码加群

关注「Apache RocketMQ」公众号,获取更多技术干货

退出移动版