本文质量: 3 / 10(对Message Queue有一定了解读会比较好)
本文修改次数: 0
阅读时长: 10 min
前言
本篇对RocketMQ Connect 以及 OpenMessaging中文文档里的部分概念,术语做了一个整理。笔者的理解可能有些偏差,如有错误还请指出。
OpenMessaging, Rocket Connect以及 Message Connector
原文的行文思路有点不直观,OpenMessaging和Message Connector的解释交叉进行,导致有些概念不是很清晰。我们先来说OpenMessaging
OpenMessaging 是一套消息中间件领域的规范
这个规范有点类似于容器领域的标准cri,以及容器网络领域的标准cni。规范希望市面上所有的Message Queue 的实现,比如Kafka,RabbitMQ,RocketMQ可以遵循同样一套标准。这样的一个好处(只是其中一个好处)应用程序不用为每个Message Queue的实现都写一个接入的插件。比如MongoDB想要给Kafka发送数据的话,可能要写一个叫Mongo-connect-Kafka的插件,如果之后换到RocketMQ又要写Mongo-connect-RocketMQ。这肯定加大了开源社区的工作量。如果Kafka,RocketMQ都去实现OpenMessaging这个规范,重复造轮子就可以避免了。
那么OpenMessaging Connect 是所有OpenMessaging 规范里的一个子集,这个子集能够解决我们重复造轮子的问题。另外一个OpenMessage Runtime 也是OpenMessaging 规范里的一个子集。
我们接下来的讨论都是关于OpenMessaging Connect和OpenMessaging Runtime这两个规范。
OpenMessaging Connect规范的架构里,有三个组件
-
Source Connector
: 负责把数据从Source 系统,比如MySQL,读到某一种Message Queue中,可以是RocketMQ -
Sink Connector
: 从某一种Message Queue中读取数据到目标系统中,比如一个Postgres -
Task
: 可以是Source Task或者Sink Task,Connector会创建Task的定义,然后交给OpenMessaging Runtime去跑这个Task
期间两种Connector会负责数据格式转换。
这样的设计对于数据库同步的使用场景非常有用,不过这不代表OpenMessaging只能用于数据库同步,它当然也可以用于普通的Producer/Consumer场景。不同的是,Producer不直接连接到某一个Message Queue集群,而是去访问对应Source Connector,Consumer同理。(这一段不是很确定,我可能说错了)(如果不是某种数据系统的同步场景的话,connector似乎有点多此一举?)(为什么数据库同步场景适合用Connector?这是个很有趣的问题,之后把我的一些疑问搞懂之后再来写)
Open Messaging Runtime 为 Source Connector
以及 Sink Connector
提供运行环境。当然它还有些其他的功能,比如
OpenMessaging Runtime为其上运行的各种类型Connector及其关联的Task任务提供统一的运行时环境(包括负载均衡,实例间的调度,配置管理以及集群管理)。 因此,在RocketMQ的消息路由的特性设计与实现中,依然不会将涉及消息复制和同步的逻辑渗透至OpenMessaging Runtime层,该层仍然是一个具体Connector实现无关且高度抽象统一的中间层。这里,只需要将runtime 组件进行一定的参数可配置化改造即可。
最后总结一下
- Source onnector和Sink Connector分别去连两端的数据源
- Open Messaging Runtime 是用来跑Connector的,因此可以在多个平台(go,Java)上实现
- Source Connector 从源数据系统读数据并发到一个Message Queue,Sink Connector从Message Queue里读数据再写入到目标数据系统里。
接下来是RocketMQ Connect
先看官方的解释
RocketMQ遵循Message Connector的设计理念,依托RocketMQ进行实现。
简单理解RocketMQ Connect就是借RocketMQ从其他系统获取数据发送到RocketMQ,然后从RocketMQ消费消息写入到其他系统。主要由Source Connector,Sink Connector,Runtime组成。
这段话其实可以暂时忽略Message Connector,写成
RocketMQ Connect实现了OpenMessaging,依托RocketMQ进行实现。
简单理解RocketMQ Connect使用Source Connector 从其他系统获取数据发送到RocketMQ,然后从RocketMQ消费消息写入到其他系统。主要由Source Connector,Sink Connector实现以及RocketMQ Connect Runtime组成。
所以我理解的是
- RocketMQ Connect Runtime是 OpenMessaging Runtime的一个实现
- RocketMQ Connect 应该能够使用各种已经实现OpenMessaging Connect规范的Connector,而不用自己另外写。
最后是Message Connector。当我看了RocketMQ Connect 和 OpenMessaging之后,我觉得Message Connector的很多概念和OpenMessaging是重合的,所以我决定暂时不管Message Connector的概念,因为Message Connector是和RocketMQ cluster 之间的消息同步相关的,而我发现不用Message Connector的概念也能把RocketMQ cluster 消息同步讲清楚。
RocketMQ Connect 和 RocketMQ Connector
这是两个完全不同的东西,RocketMQ Connect已经讲过了,是使用RocketMQ
对OpenMessaging规范的实现。而关于RocketMQ Connector,官方解释是
Replicator是RocketMQ Connector的别名,用于RocketMQ集群之间的信息同步,Replicator是运行在RocketMQ Runtime上的RocketMQ 集群消息同步Connector,其主要实现了Connector的机制,能够同步两个独立的RocketMQ集群之间的消息。
原文中有几处混用,对开发者造成了一定的困扰,等我整理完了可以交个PR改一下。(不过我不知道这个GitBook在哪里==
RocketMQ Connector只有Source Connector。和Connector一样,都是从某一个数据系统读数据(通常是备份数据),只不过对于Rocket MQConnector来说,要读的源数据系统也是RocketMQ。
Source 和 Sink Connector
目前我能在rocketmq-externals里找到的大多数Connector都是Source Connector,只有rocketmq-connect-jdbc同时实现了Source/Sink Connector。
我们可以注意到,很多的Source Connector都是用来备份数据或者同步数据的,有的实现方式是去监听数据库的修改事件(比如MySQL Connector就去模拟一个备份数据库,所有对这个Fake Database的修改都会被MySQL Connector监听到并记录并通过Message Queue发到另一个集群再做相应的处理)。
这里就引出了之前说的Message Connector所想要实现的功能。目前来说RocketMQ Connect可以都是用于数据系统数据备份或者同步,比如RocketMQ Connector就是用来在多个region的RocketMQ之间同步消息。
这里有几个小疑问,
- 是否Source Connector 可以单独使用?(即没有Sink Connector,我猜答案是可以的,但是不知道具体实现)
- X Source Connector必须和X Sink Connector一起用吗, 也就是说,我可以用MySQL Source Connector 以及 Cassandra Sink Connector把数据从MySQL 转移到Cassandra里吗?如果可以,那说明所有的数据都必须先被转换成某一种中间格式,我觉得不是很可行。如果不可以,那Source 和 Sink Connector就必须就数据转换达成共识,这种coupling似乎也不是很好。之后解决了问题会更新在下面。
问题
我注意到了一个很奇怪的地方,那就是目前所有rocketmq-externals
里的Connector都叫rocketmq-connect-xxx
,可是想到我之前写Connector的部分,所有的Connector应该是实现了OpenMessaging Connect的规范的Connector,那这也就意味着,他们应该是Message Queue无关的。也就是不应该绑定某个Connector到RocketMQ上。而实际上无论从命名,还是coding上Connector的实际实现都依赖于RocketMQ,这也就意味着我们并不能实现“一种Connector,所有Message Queue都能用”的最初设想。
所以我十分怀疑我对Connector的理解有问题,所以还是得继续读源码或者问问RocketMQ的开发者。
后记和一些杂谈
我没有仔细深入研究RocketMQ 和 Kafka在设计上有什么取舍(RocketMQ 因为用于蚂蚁金服和淘宝,对消息可靠性要求肯定比Kafka高,所以性能上也肯定有折损),但是RocketMQ能扛住国内双11真挺厉害的。我比较感兴趣的是像OpenMessaing这样的某一领域内的标准。因为我之前实习用了很多Kubernetes, 所以知道一些容器领域的标准比如cri,cni。为什么要去争夺这么一个标准制定者的地位,我想的还不是特别的透彻,懂的朋友可以私戳我给我科普一下嘿嘿。
关于Message Queue领域能不能制定一个类似的标准,其实要考虑的方面很多。一是,像Kafka这样的市场占有率巨头没有必要去制定标准,它的方向肯定是向Kubernetes学习,让自身成为某一个领域的标准,直接把其他的产品排挤出去。二是(我不是很懂这一点,所以可能有些基础性的知识错误)对于Message Queue这样的performance-critical的产品,让一个已经有的Message Queue 去适配一个新的标准是否会引入额外的开销。
之后应该会写一些关于共识算法的文章,之前看了很多遍Paxos但是一直感觉要自己将给别人还是很难。网上的中文资料有一大半是错的,还有一些说得很模糊的(虽然Paxos工程实现本身就挺模糊的LOL)。我争取写一个能让我室友看懂的版本出来。