Apache RocketMQ 的 Service Mesh 开源之旅

头图.png

作者 | 凌楚   阿里巴巴开发工程师

导读:自 19 年底开始,支持 Apache RocketMQ 的 Network Filter 历时 4 个月的 Code Review(Pull Request),于本月正式合入 CNCF Envoy 官方社区(RocketMQ Proxy Filter 官方文档),这使得 RocketMQ 成为继 Dubbo 之后,国内第二个成功进入 Service Mesh 官方社区的中间件产品。

Service Mesh 下的消息收发

主要流程如下图:

1.png
图 1

简述一下 Service Mesh 下 RocketMQ 消息的发送与消费过程:

  • Pilot 获取到 Topic 的路由信息并通过 xDS 的形式下发给数据平面/Envoy ,Envoy 会代理 SDK 向 Broker/Nameserver 发送的所有的网络请求;
  • 发送时,Envoy 通过 request code 判断出请求为发送,并根据 topic 和 request code 选出对应的 CDS,然后通过 Envoy 提供的负载均衡策略选出对应的 Broker 并发送,这里会使用数据平面的 subset 机制来确保选出的 Broker 是可写的;
  • 消费时,Envoy 通过 request code 判断出请求为消费,并根据 topic 和 request code 选出对应的 CDS,然后和发送一样选出对应的 Broker 进行消费(与发送类似,这里也会使用 subset 来确保选出的 Broker 是可读的),并记录相应的元数据,当消息消费 SDK 发出 ACK 请求时会取出相应的元数据信息进行比对,再通过路由来准确将 ACK 请求发往上次消费时所使用的 Broker。

RocketMQ Mesh 化所遭遇的难题

Service Mesh 常常被称为下一代微服务,这一方面揭示了在早期 Mesh 化浪潮中微服务是绝对的主力军,另一方面,微服务的 Mesh 化也相对更加便利,而随着消息队列和一些数据库产品也逐渐走向 Service Mesh,各个产品在这个过程中也会有各自的问题亟需解决,RocketMQ 也没有例外。

有状态的网络模型

RocketMQ 的网络模型比 RPC 更加复杂,是一套有状态的网络交互,这主要体现在两点:

  • RocketMQ 目前的网络调用高度依赖于有状态的 IP;
  • 原生 SDK 中消费时的负载均衡使得每个消费者的状态不可以被忽略。

对于前者,使得现有的 SDK 完全无法使用分区顺序消息,因为发送请求和消费请求 RPC 的内容中并不包含 IP/(BrokerName + BrokerId) 等信息,导致使用了 Mesh 之后的 SDK 不能保证发送和消费的 Queue 在同一台 Broker 上,即 Broker 信息本身在 Mesh 化的过程中被抹除了。当然这一点,对于只有一台 Broker 的全局顺序消息而言是不存在的,因为数据平面在负载均衡的时候并没有其他 Broker 的选择,因此在路由层面上,全局顺序消息是不存在问题的。

对于后者,RocketMQ 的 Pull/Push Consumer 中 Queue 是负载均衡的基本单位,原生的 Consumer 中其实是要感知与自己处于同一 ConsumerGroup 下消费同一 Topic 的 Consumer 数目的,每个 Consumer 根据自己的位置来选择相应的 Queue 来进行消费,这些 Queue 在一个 Topic-ConsumerGroup 映射下是被每个 Consumer 独占的,而这一点在现有的数据平面是很难实现的,而且,现有数据平面的负载均衡没法做到 Queue 粒度,这使得 RocketMQ 中的负载均衡策略已经不再适用于 Service Mesh 体系下。

此时我们将目光投向了 RocketMQ 为支持 HTTP 而开发的 Pop 消费接口,在 Pop 接口下,每个 Queue 可以不再是被当前 Topic-ConsumerGroup 的 Consumer 独占的,不同的消费者可以同时消费一个 Queue 里的数据,这为我们使用 Envoy 中原生的负载均衡策略提供了可能。

2.png
图 2

图 2 右侧即为 Service Mesh 中 Pop Consumer 的消费情况,在 Envoy 中我们会忽略掉 SDK 传来的 Queue 信息。

弹内海量的 Topic 路由信息

在集团内部,Nameserver 中保存着上 GB 的 Topic 路由信息,在 Mesh 中,我们将这部分抽象成 CDS,这使得对于无法预先知道应用所使用的 Topic 的情形而言,控制平面只能全量推送 CDS,这无疑会给控制平面带来巨大的稳定性压力。

在 Envoy 更早期,是完全的全量推送,在数据平面刚启动时,控制平面会下发全量的 xDS 信息,之后控制平面则可以主动控制数据的下发频率,但是无疑下发的数据依旧是全量的。后续 Envoy 支持了部分的 delta xDS API,即可以下发增量的 xDS 数据给数据平面,这当然使得对于已有的 sidecar,新下发的数据量大大降低,但是 sidecar 中拥有的 xDS 数据依然是全量的,对应到 RocketMQ ,即全量的 CDS 信息都放在内存中,这是我们不可接受的。于是我们希望能够有 on-demand CDS 的方式使得 sidecar 可以仅仅获取自己想要的 CDS 。而此时正好 Envoy 支持了 delta CDS,并仅支持了这一种 delta xDS。其实此时拥有 delta CDS 的 xDS 协议本身已经提供了 on-demand CDS 的能力,但是无论是控制平面还是数据平面并没有暴露这种能力,于是在这里对 Envoy 进行了修改并暴露了相关接口使得数据平面可以主动向控制平面发起对指定 CDS 的请求,并基于 delta gRPC 的方式实现了一个简单的控制平面。Envoy 会主动发起对指定 CDS 资源的请求,并提供了相应的回调接口供资源返回时进行调用。

对于 on-demand CDS 的叙述对应到 RocketMQ 的流程中是这样的,当 GetTopicRoute 或者 SendMessage 的请求到达 Envoy 时,Envoy 会 hang 住这个流程并发起向控制平面中相应 CDS 资源的请求并直到资源返回后重启这个流程。

关于 on-demand CDS 的修改,之前还向社区发起了 Pull Request ,现在看来当时的想法还是太不成熟了。原因是我们这样的做法完全忽略了 RDS 的存在,而将 CDS 和 Topic 实现了强绑定,甚至名称也一模一样,关于这一点,社区的 Senior Maintainer [@htuch ]() 对我们的想法进行了反驳,大意就是实际上的 CDS 资源名可能带上了负载均衡方式,inbound/outbound 等各种 prefix 和 suffix,不能直接等同于 Topic 名,更重要的是社区赋予 CDS 本身的定义是脱离于业务的,而我们这样的做法过于 tricky ,是与社区的初衷背道而驰的。

因此我们就需要加上 RDS 来进行抽象,RDS 通过 topic 和其他信息来定位到具体所需要的 CDS 名,由于作为数据平面,无法预先在代码层面就知道所需要找的 CDS 名,那么如此一来,通过 CDS 名来做 on-demand CDS 就更无从谈起了,因此从这一点出发只能接受全量方案,不过好在这并不会影响代码贡献给社区。

route_config:name: default_routeroutes:- match:topic:exact: meshheaders:- name: codeexact_match: 105route:cluster: foo-v145-acme-tau-beta-lambda

上面可以看到对于 topic 名为 mesh 的请求会被 RDS 路由到 foo-v145-acme-tau-beta-lambda 这个 CDS 上,事先我们只知道 topic 名,无法知道被匹配到的 CDS 资源名。

如今站在更高的视角,发现这个错误很简单,但是其实这个问题我们直到后续 code review 时才及时纠正,确实可以更早就做得更好。

不过从目前社区的动态来看,on-demand xDS 或许已经是一个 roadmap,起码目前 xDS 已经全系支持 delta ,VHDS 更是首度支持了 on-demand 的特性。

Mesh 为 RocketMQ 带来了什么?

A service mesh is a dedicated infrastructure layer for handling service-to-service communication. It’s responsible for the reliable delivery of requests through the complex topology of services that comprise a modern, cloud native application. In practice, the service mesh is typically implemented as an array of lightweight network proxies that are deployed alongside application code, without the application needing to be aware.

这是 Service Mesh 这个词的创造者 William Morgan 对其做出的定义,概括一下:作为网络代理,并对用户透明,承担作为基础设施的职责。

3.png
图 3

这里的职责在 RocketMQ 中包括服务发现、负载均衡、流量监控等职责,使得调用方和被代理方的职责大大降低了。

当然目前的 RocketMQ Filter 为了保证兼容性做出了很多让步,比如为了保证 SDK 可以成功获取到路由,将路由信息聚合包装成了 TopicRouteData 返回给了 SDK ,但是在理想情况下,SDK 本身已经不需要关心路由了,纯为 Mesh 情景设计的 SDK 是更加精简的,不再会有消费侧 Rebalance,发送和消费的服务发现,甚至在未来像消息体压缩和 schema 校验这些功能 SDK 和 Broker 或许都可以不用再关心,来了就发送/消费,发送/消费完就走或许才是 RocketMQ Mesh 的终极形态。

4.png
图 4

What's Next ?

目前 RocketMQ Filter 具备了普通消息的发送和 Pop 消费能力,但是如果想要具备更加完整的产品形态,功能上还有一些需要补充:

  • 支持 Pull 请求:现在 Envoy Proxy 只接收 Pop 类型的消费请求,之后会考虑支持普通的 Pull 类型,Envoy 会将 Pull 请求转换成 Pop 请求,从而做到让用户无感知;
  • 支持全局顺序消息:目前在 Mesh 体系下,虽然全局顺序消息的路由不存在问题,但是如果多个 Consumer 同时消费全局顺序消息,其中一个消费者突然下线导致消息没有 ACK 而会导致另一个消费者的消息产生乱序,这一点需要在 Envoy 中进行保证;
  • Broker 侧的 Proxy:对 Broker 侧的请求也进行代理和调度。

蜿蜒曲折的社区历程

起初,RocketMQ Filter 的初次 Pull Request 就包含了当前几乎全部的功能,导致了一个超过 8K 行的超大 PR,感谢@天千 在 Code Review 中所做的工作,非常专业,帮助了我们更快地合入社区。

另外,Envoy 社区的 CI 实在太严格了,严格要求 97% 以上的单测行覆盖率,Bazel 源码级依赖,纯静态链接,本身无 cache 编译 24 逻辑核心 CPU 和 load 均打满至少半个小时才能编完,社区的各种 CI 跑完一次则少说两三个小时,多则六七个小时,并对新提交的代码有着极其严苛的语法和 format 要求,这使得在 PR 中修改一小部分代码就可能带来大量的单测变动和 format 需求,不过好的是单测可以很方便地帮助我们发现一些内存 case 。客观上来说,官方社区以这么高的标准来要求 contributors 确实可以很大程度上控制住代码质量,我们在补全单测的过程中,还是发现并解决了不少自身的问题,总得来说还是有一定必要的,毕竟对于 C++ 代码而言,一旦生产环境出问题,调试和追踪起来会困难得多。

最后,RocketMQ Filter 的代码由我和@叔田 共同完成,对于一个没什么开源经验的我来说,为这样的热门社区贡献代码是一次非常宝贵的经历,同时也感谢叔田在此过程中给予的帮助和建议。

相关链接

  • Official docs for RocketMQ filter
  • Pull request of RocketMQ filter
  • RocketMQ filter's issue
  • On-demand CDS pull request for Envoy
  • First version of RocketMQ filter's proposal

阿里巴巴云原生中间件团队招人啦

这里有足够多的业务场景、足够大的消息生态、足够深的分布式技术等着大家前来探索,如果你满足:

  • 至少精通一种编程语言,Java 或 C++;
  • 深入理解分布式存储理论,微服务优化实践;
  • 计算机理论基础扎实,例如对操作系统原理、TCP/IP 等有比较深入的理解; 
  • 具有独立设计一款生产环境高可用高可靠的中间件能力,例如 RocketMQ; 
  • 熟悉高并发、分布式通信、存储、开源中间件软件等相关技术者更佳。 

欢迎加入并参与新一代云原生中间件建设!简历提交地址:yangkun.ayk@alibaba-inc.com。

课程推荐

为了更多开发者能够享受到 Serverless 带来的红利,这一次,我们集结了 10+ 位阿里巴巴 Serverless 领域技术专家,打造出最适合开发者入门的 Serverless 公开课,让你即学即用,轻松拥抱云计算的新范式——Serverless。

点击即可免费观看课程:https://developer.aliyun.com/learning/roadmap/serverless

“阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”

原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/515976.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

企业微信H5_网页jssdk调用 config和agentconfig的区别

文章目录一、文档阅读1. 企业微信JS-SDK作用2. config 接口注入权限3. agentConfig注入应用的权限二、二者区别1.引入js不同2. 参数个数不一样3. 获取应用的jsapi_ticket4. 支持的接口5. 效果演示三、源码分享3.1. 后端源码3.2. 前端源码一、文档阅读 1. 企业微信JS-SDK作用 …

阿里云飞天洛神2.0:开放弹性的云网络NFV平台

云网络架构 阿里云操作系统叫飞天,云网络平台称为洛神。作为飞天系统的核心组件,洛神平台支撑了超大规模租户、超大规模虚拟机的高性能云网络。 洛神平台由很多网络设备组成,在架构上主要可以分为两类:虚拟交换机AVS和各种网关设…

从沟通工具到打通 IoT 全场景,音视频沟通新玩法

据艾媒咨询数据显示,2019年中国智能移动办公市场规模达到288亿元,随着在线办公需求增长及用户习惯养成,预计2020年智能移动办公市场将达到449亿元。 今年被称为远程办公元年,远程办公趋势变革不仅带来办公工具的转变,…

深源恒际医疗票据OCR落地九省市 服务范围覆盖过半市场

近年来,我国健康险市场规模持续保持高增长。银保监会最新统计数据显示,2019年中国健康险业务原保险保费收入6564亿元,同比增长29.75%。同时,随着民众风险保障意识的不断提升,未来健康险仍有巨大的潜在增长空间。据天风…

企业微信H5_网页jssdk调用 agentconfig选人选照片等案例演示

文章目录一、验证域名归属校验1. 阅读文档2. 配置公网域名3. 登录企业微信管控台4. 选择自建应用5. 网页授权及JS-SDK6. 填写公网域名7.下载校验文件8. 校验文件移动9. 启动前端项目10. 浏览器校验11. 域名校验12. 应用主页二、前端代码实战2.1. 引入JS文件2.2.权限验证配置三、…

ByteArrayOutputStream和ByteArrayInputStream的简单使用

ByteArrayOutputStream和ByteArrayInputStream的简单使用 1.首先看下这两个IO流是什么? ByteArrayOutputStream:字节数组输出流.在内存中创建一个字节数组缓冲区,所有发送到输出流的数据保存在该字节数组缓冲区中。 ByteArrayInputStream:字节数组输入…

Flink 1.10 细粒度资源管理解析

相信不少读者在开发 Flink 应用时或多或少会遇到在内存调优方面的问题,比如在我们生产环境中遇到最多的 TaskManager 在容器化环境下占用超出容器限制的内存而被 YARN/Mesos kill 掉[1],再比如使用 heap-based StateBackend 情况下 State 过大导致 GC 频…

一文告诉你雾计算与云计算的区别及对物联网的价值!

作者 | Victoria Puzhevich翻译 | 风车云马,责编 | 晋兆雨出品 | CSDN云计算头图 | 付费下载于视觉中国雾计算是一种分布式计算结构。将数据和应用程序等资源放置在数据源和云之间的逻辑位置。雾计算的优点之一是让许多用户同时连接到互联网上。从本质上说&#xff…

企业微信H5_消息推送概述,发送应用消息示例

文章目录一、阅读和调试1. 文档阅读2. postman发送消息二、实战演练2.1. 发送消息2.2. 前端代码2.3. 后端代码2.4. 发送文本消息2.5. 接收消息三、源码分享3.1. 后端源码3.2. 前端源码一、阅读和调试 1. 文档阅读 文档链接:https://developer.work.weixin.qq.com/…

linux部署springboot项目及后台执行linux命令的两种方式

linux部署springboot项目及后台执行linux命令的两种方式 1.将springboot项目打成jar包 这里推荐两种方法: 第一种:在idea的terminal窗口执行命令:mvn package spring-boot:repackage 第二种:在maven的Lifestyle中点击package打包 打好的jar包会在target目录下. 2.将jar包复…

FAST20 论文学习

BCW: Buffer-Controlled Writes to HDDs for SSD-HDD Hybrid Storage Server 原文地址 为了兼顾访问性能和硬件成本,目前有不少的存储系统都采用了混合存储(Hybrid Storage),使用 SSD 来提供微秒级访问,配合 HDD 来降…

企业微信H5_消息推送接收消息回调配置、内网穿透到本地

文章目录一、环境准备1. 阅读文档2. 登录管控台3. 编辑配置4. 内网穿透5. 测试案例6. 公网访问验证7. 保存配置8. 验证URL有效性二、源码分享2.1. 后端源码2.2. 前端源码一、环境准备 1. 阅读文档 官网文档:https://developer.work.weixin.qq.com/document/path/9…

Serverless 选型:深度解读 Serverless 架构及平台选择

作者 | 悟鹏 阿里巴巴技术专家 导读:本文尝试以日常开发流程为起点,分析开发者在每个阶段要面对的问题,然后组合解决方案,提炼面向 Serverless 的开发模型,并与业界提出的 Serverless 产品形态做对应,为开发…

CSDN 星城大巡礼,长沙“科技之星”年度企业评选正式开启

2020年,长沙市委主要领导发出“软件产业再出发”的号召,颁布了软件三年行动计划。今年5月,CSDN 作为专业的 IT 社区,与长沙高新区签约,将全国总部落户长沙,这一战略决策,让CSDN与长沙的联结进一…

企业微信H5_集成消息解密类,消息推送Get及Post回调处理

文章目录一、 验证URL有效性1. 阅读文档2. 文档分析3. 加解密方案说明4. 下载加解密算法5. 案例分析二、实战集成2.1. 工具类拷贝2.2. 依赖引入2.3. 案例1集成2.4. 参数处理2.5. 重启项目2.6. 验证URL有效性2.7. 验证三、消息接收与处理3.1. 文档阅读3.2. 案例2拷贝3.3. 参数处…

新一代高效Git协同模型AGit-Flow详解

【以下为分享实录,有删节】 Git工作流概述及AGit-Flow的优势 目前,Git已成为源代码管理的标准和基础设施。“为什么Git能这么成功”?Git的创建者Linux在Git十周年的一次采访中,道出了其中的奥秘: The big thing abo…

云原生人物志|APISIX温铭:让API网关“666”

云原生已无处不在,《云原生人物志》是CSDN重磅推出的系列原创采访,我们关注云原生中每一个技术人、公司的身影。知微见著,窥见云原生价值与趋势。 作者 | 宋慧 出品 | CSDN云计算 头图 | 付费下载于IC Photo 第一期,我们采访了唯…

xshell和Xftp连接Linux

xshell和Xftp连接Linux 简单介绍下这两种工具: Xshell :远程连接linux,执行命令行; Xftp :远程连接linux,可视化的实现windows和linux之间的文件传输; 2.关于如何获知linux的ip地址 在虚拟机中登录用户,输入用户名,密码: 此处注意一点:注意区分密码的大小写!!!,因为你在设置密…

数智化时代合格数据架构师如何养成?

文章将从云计算基建、大数据基建、数据构建、数据管理、数据应用5个角度,阐述数据架构师的必备技能和素养。 云计算基建 传统的IT架构已存在几十年,随着企业业务的快速发展,对于业务的可用性要求越来越高,对于成本的压力也越来大…

企业微信_客户联系,获取客户及客户群列表及详情

文章目录一、调试接口1. 阅读文档2. 权限配置3. 指定应用二、POSTMAN调试接口2.1. 获取配置了客户联系功能的成员列表2.2. 获取客户列表2.3. 获取客户详情2.4. 获取客户群列表2.5. 获取客户群详情三、实战演练代码拆解3.1. 获取配置了客户联系功能的成员列表3.2. 获取客户列表3…