RocketMQ 5.0 多语言客户端的设计与实现
本文作者:古崟佑,阿里云中间件开发。
RocketMQ 5.0 版本拥有非常多新特性,比如存储计算分离、 batch 能力的提升等,它是具有里程碑意义的版本。
提到新版本,我们往往会首先想到服务端架构的设计变动,很容易忽略客户端的设计理念。客户端也是消息产品的必要组成部分,许多特性需要 client 与 server 两端互相协作,才能更好地实现。
轻量化、云原生以及统一模型是 RocketMQ 5.0 客户端的三个设计理念。
01 轻量化
轻量化的重点在于轻逻辑、轻流程,化繁为简,减少多语言生态发展的阻碍。
上图列举了 RocketMQ 4.x 版本和 RocketMQ 5.0 版本的差异。
①4.x 版本的序列化使用 JsonCodecs 和 RocketMQCodecs,5.0 版本使用的则是标准的 Protobuf 协议。多语言发展的阻碍包括许多不规范,比如 RocketMQ 自定义序列化对于其他的语言需要自己实现一套协议以实现正反序列化解析。而 Json 作为标准序列化协议,基本可以实现所有语言的正反序列化,但缺点也非常明显,冗余信息过多,体积占用太大,因此更多用于 restful 架构等前后端交互的场景。此外,消息中间件场景无需关心传输数据时是否可读。因此, Protobuf 成为了选择,它原生支持多语言,且传输时体积占用非常小,成熟且标准。
②此前客户端使用 consumer 消费信息时,会存在计算逻辑比如重平衡 以及系统级 topic 处理。但是 RocketMQ 5.0 版本将所有计算逻辑上移到了服务端,客户端只需简单地调用 Receive 接口,也无需额外处理系统级 topic ,整体逻辑变得非常轻量。
③4.x版本的实现和维护成本非常高,因此5.0版本并没有基于4.x进行迭代和更新。设计之初有一种思路为直接在4.x客户端上增加 gRPC 协议,迭代升级成为5.0,但这相当于扛着历史包袱往前走,也违背了轻量化原则,因此被否定。
02 云原生
云的弹性、高可用性以及交互运维能力在 RocketMQ 5.0 客户端中均有体现,分别对应极致弹性伸缩、低耦合以及云端一体。
上图为 4.x版本和5.0版本的客户端。在4.x版本中, 一个 Queue 最多对应一个 consumer,增加 consumer 不一定能提升消费并发,其弹性有上限。但在 RocketMQ 5.0,每一个 consumer 可以向所有 broker 发起 Pop 请求。此前为 push 模式,现在改为 pop 请求。提升 consumer 数量能够提升消费并发,即使只有一个队列,也可以生成数百数千个消费者统一拉取队列消息。
比如购物网站突发退货流量高峰,此前最简单有效的方式为增加业务应用数量、增加处理并发,比如增加退货系统和客户系统核心的应用数据。但如果一开始队列数设置并没有这么多,则需要先扩容队列,再扩容核心业务数。同时,扩容后也仅对新入队的消息处理速度有提升,已经造成堆积的队列消费速度依然缓慢。此时会出现一种情况,先提交的退货申请后被处理,会对用户体验造成影响。
而 RocketMQ 5.0 的 pop 消费模型只需直接增加业务处理节点数即可解决问题。
已堆积队列无法通过扩容的方式加速消费,与低耦合场景相似。比如在4.x版本中,假如某消费节点发生 FullGC ,消费比较慢,但是没有完全下线,依然与服务端保持着心跳。因此队列依然会被分配至该节点,分配队列逐渐堆积可能会引发一系列问题。
但在 RocketMQ 5.0,如果某节点发生 FullGC,分配粒度会从队列退化为消息,分配的消息消费缓慢,不会产生堆积。
因此,从极致弹性和低耦合上可以看出 RocketMQ 5.0 之后使用 Pop 协议的优越性,只需要简单地在消费能力不足时扩容、富余时缩容,单一节点故障也不会影响到全局。
云可以理解为远在机房的服务端,端则嵌在业务 SDK。此前,在控制台上进行运维操作时,只能控制服务端,对客户端的掌控非常有限,使用体验非常割裂。比如更改服务端配置,除了白屏也可以通过命令工具轻松修改配置,且及时生效。但如果客户端修改配置,则会涉及到业务发布,很容易出现问题。
RocketMQ 5.0 采用 telemetry 遥测协议与服务端进行协同。遥测协议的作用为使云和端之间通过 telemetry 进行交互,包括但不限于限流策略、重试策略、发布和订阅关系管控、可观测开关、接入点信息、堆栈信息等。主要实现方式为直接由 SDK 向服务端发起 telemetry 请求,然后往 observer 读写上图所示的指令即可。
指令类型包括设置、打印堆栈、验证消息、消费以及事务消息回查,其中比较关键的能力为可观测开关以及 OTLP 接入点信息。
以往的可观测是基于消息轨迹实现,在发送消息和消费消息时,将上下文中的参数添加进轨迹消息,在后台攒批异步发送。上图为发送消息的所有 context,包括MessageQueue、MessageID 、IP 等信息。
上图为消费时的 context 。对于单个 MessageID ,端对端会产生三条轨迹消息,分别为发送后、消费前和消费后。如果想要跟踪消息轮转轨迹,可以通过查询轨迹的消息数据找到它,因其将 MessageID 作为 key 值插入到 topic 。而此前需要在控制台根据 MessageID 查询轨迹消息。
RocketMQ 此前已经具备可观测能力,但自定义可观测方式无法很好地对接现有的可观测产品和能力。而5.0版本拥有了标准化的可观测协议,可以使用更丰富、更专业的分析和展示工具,让可观测数据有了更高的价值。
Telemetry 遥测协议是将可观测开关以及接入点下发到客户端,Proxy 会默认将接入点信息设置为自己,可以将客户端上报的所有可观测消息在服务端做收敛,再统一使用标准的 OpenTelemetry 和 Opencensu 两个协议上报到 SLS , SLS 再通过 TLog 的方式与 Prometheus、Grafana 进行对接。
Tracing 的数据链路比较复杂,也需要先经过 proxy 将可观测数据导到 proxy 上。而Tracing 的数据量较大,此前也曾考虑过直接通过用户自定义配置导出接入点,不经过 proxy ,但这会引发其他问题,比如4.x用户希望接入 RocketMQ 5.0 服务端使用可观测能力,则需要通过轨迹消息解码进行解析再通过标准化可观测协议输出。
多语言方面,最新出的 OpenTelemetry 支持不一定足够全面,因此也会需要一些旧的可观测协议比如 Opencensu,但整体来说,它们都是标准的协议。
03 统一模型
此前的 RocketMQ API 缺乏精心设计的消息模型,很多概念没有明确的定义。比如发送消息时有两个 ID ,分别是用户自己定义的 MessageID 和服务端下发的 offsetID 。但是在消费时,下发的 offsetID 又变成了 MessageID ,模棱两可的定义使得预测客户行为变得更加困难。并且,此前大多以执行为导向,对开发者并不友好,许多功能是基于实现而不是接口。因此用户需要触及到很多细节,需要面对过多冗余和复杂界面,出错概率极大。
另外,发展多语言生态时,也需要统一模型引导多语言的发展实现。
主题类型是其中一个明显的改变。
此前,客户端不做 topic 类型校验,任何一种类型消息都可以发往 topic 。但是在RocketMQ 5.0 之后会对 topic 类型做校验,真正从 topic 主题类型上做了区分,比如顺序消息 topic 只能发顺序消息。此前的 delay 消息为分级别延时消息,而现在为支持毫秒级精度的定时消息,可以支持任意时间精度。
同时,模型定义了各种各样的消费者,有不同的消费者实现,比如 PushConsumer 、PullConsumer 以及 SimpleConsumer ,底层均使用 pop 协议实现。比如以前的PushConsumer 是基于手动拉的方式,而现在采用了 pop 方式。
SimpleConsumer 的使用方法非常简单,直接调用 receive message 接口,获取到消息之后进行消费,消费成功则进行 Ack;如果消费失败,则更改可见时间。整体流程非常直观,完全基于接口定义。
新版本的启动流程增加了准备工作,为了能够更早地捕捉到明显的错误以及异常,比如尝试从服务端获取设置,可以对此类设置进行热更新,称为服务器和客户遥测,任何准备失败都会导致客户端启动失败,而以往可以强行将客户端拉起,然后不断进行重试。
增加了准备工作后,配置问题或本身网络问题可以提前被发现,比如 topic 路由信息不存在,启动时会先对 bonding topic 做检查,每一个发送者、生产者可以提前设置预留 topic 信息,再根据错误信息进行检查,判断是否可以启动。
RocketMQ 5.0 多语言客户端的设计与实现的更多相关文章
- CAT 3.0 开源发布,支持多语言客户端及多项性能提升
项目背景 CAT(Central Application Tracking),是美团点评基于 Java 开发的一套开源的分布式实时监控系统.美团点评基础架构部希望在基础存储.高性能通信.大规模在线访问 ...
- RocketMQ 5.0 POP 消费模式探秘
作者:凯易&耘田 审核校对:白玙 编辑&排版:雯燕 前言:随着 RocketMQ 5.0 preview 的发布,5.0 的重大特性逐步与大家见面.POP Consumer 作为 5. ...
- Redis学习之路(008)- Redis C语言客户端库hiredis文档翻译
Hiredis是Redis数据库一个轻量的C语言客户端库. 之所以轻量是由于它只是简单的提供了对redis操作语句支持的接口,并没有实现具体的操作语句的功能.但正是由于这种设计使我们只要熟悉了通用的r ...
- RocketMQ详解(四)核心设计原理
专题目录 RocketMQ详解(一)原理概览 RocketMQ详解(二)安装使用详解 RocketMQ详解(三)启动运行原理 RocketMQ详解(四)核心设计原理 RocketMQ详解(五)总结提高 ...
- 基于云基础设施快速部署 RocketMQ 5.0 集群
本文作者:蔡高扬,Apache RocketMQ Committer, 阿里云智能技术专家. 背景 上图左侧为 RocketMQ 4.x版本集群,属于非切换架构.NameServer 作为无状态节点可 ...
- 娓娓道来c指针 (0)c语言的梦魇:c指针
(0)c语言的梦魇:c指针 序 c语言中有一个重点:c指针.它也是一个难点.当然,这是一句废话:重点往往也是难点.在c标准中,对指针的定义是这种: 指针的类型是derived from其他类型,也就是 ...
- C语言程序设计课程设计自查表格
课程设计自查表格 序号 项目 完成与否(完成打勾) 1 格式是否符合标准(缩进是否规范) 2 是否模块化设计(使用函数分解系统功能) 3 函数名否易懂(不得使用f1(int a1,int a2)这样的 ...
- ShoneSharp语言(S#)的设计和使用介绍—数值Double
ShoneSharp语言(S#)的设计和使用介绍 系列(5)- 数值Double 作者:Shone 声明:原创文章欢迎转载,但请注明出处,https://www.cnblogs.com/ShoneSh ...
- ShoneSharp语言(S#)的设计和使用介绍系列(4)— 入门概述
ShoneSharp语言(S#)的设计和使用介绍 系列(4)- 入门概述 作者:Shone 声明:原创文章欢迎转载,但请注明出处,https://www.cnblogs.com/ShoneSharp. ...
- ShoneSharp语言(S#)的设计和使用介绍系列(3)— 修炼工具
ShoneSharp语言(S#)的设计和使用介绍 系列(3)- 修炼工具 作者:Shone 声明:原创文章欢迎转载,但请注明出处,https://www.cnblogs.com/ShoneSharp. ...
随机推荐
- ubuntu18.04系统环境下使用vs code安装pylint检查python的代码错误
相关: Ubuntu18.04 系统环境下 vscode中忽略pylint某些错误或警告 ============================================ python的代码错 ...
- 模仿学习算法:Data Aggregation Approach: DAGGER算法——Mixing policy
论文: <A Reduction of Imitation Learning and Structured Prediction to No-Regret Online Learning> ...
- boulanni / theano-hf
https://github.com/boulanni/theano-hf https://people.duke.edu/~hpgavin/ExperimentalSystems/lm.pdf ht ...
- 如何将 Vim 剪贴板里面的东西粘贴到 Vim 之外的地方? (Ubuntu18.04系统亲测)
主要参考内容: https://www.zhihu.com/question/19863631 在vim中剪贴中的内容是难以在vim之外使用的,那么怎么修改这个问题呢? =============== ...
- ρars/ey 题解
给个链接:ρars/ey. 我们考虑一个树上背包. 设 \(f_{u,i}\) 表示在 \(u\) 号节点的子树内删除 \(i\) 个点的最小代价.显然有答案为 \(f_{1,siz_1-1}\). ...
- 痞子衡嵌入式:探析i.MXRT1050在GPIO上增加RC延时电路后导致边沿中断误触发问题(上篇)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT1050在GPIO上增加RC延时电路后导致边沿中断误触发问题探析. 前段时间有一个 RT1052 客户反馈了一个有趣的问题, ...
- AtCoder Beginner Contest 315
AtCoder Beginner Contest 315 A - tcdr (atcoder.jp) 一次遍历 #include<bits/stdc++.h> using i64 = lo ...
- GPL前世今生
从事Linux开发的朋友一定都听过GPL,那么到底什么是GPL呢?他有什么作用呢?本文给大家做详细讲解. 一.GNU/GPL 在讲解GPL之前,我们必须先了解什么是GNU? 1. 什么是GNU GNU ...
- 网络/命令行抓包工具tcpdump详解
概述 用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具. tcpdump可以将网络中传送的数据包的 ...
- JAVA——拆分位数
2024/07/09 题目: 解题: import java.util.Scanner; public class Main { public static void main(String[] ar ...