阅读本文需要约 8 分钟。
在 The Hut Group( https://www.thg.com/ 以下简称 THG),我们 WMS(仓库管理系统)团队负责一个大型集成项目,研究了大量消息队列技术。本文介绍了我们对消息队列的技术选型和其它考量,以及我们如何回馈开源项目。
过去的消息队列曾是双雄鼎立的局面,大部分开发者基本在两个主要开源项目中做出选择——Apache ActiveMQ( http://activemq.apache.org/ ) 或 RabbitMQ( https://www.rabbitmq.com/ )。
在 THG,我们使用过 ActiveMQ 和 RabbitMQ 处理不同的工作负载,二者在单个数据中心都可靠和安全。
为了更好地支持全球运营,THG 的项目需要在世界各地的多个 DC 托管。我们需要高弹性能力,能根据不同仓库环境的需求,部署不同的配置。
我们有以下功能性和非功能性需求:
拥有开源许可证
支持队列和主题持久化
支持 Java 客户端库
支持 at-most-once 消息投递语义
支持大容量消息
Broker 集群支持扩展和多数据中心
运营负担和复杂性低
每个主题能处理几十万条消息,延迟在可控和可接受范围内
上图为消息量示例:12 月 1 日是黑色星期五,消息量骤增。
我们研究了现有多种消息系统,随着云基础架构的兴起和分布式系统的发展,研究的范围不断扩大:
上图为现有的流和消息技术(统计数据来自云原生计算基金会)。
此前我们已决定使用开源项目,所以未选择商业产品。我们比较了上图的开源项目,得出以下结论:
RabbitMQ:不能保证不发送重复的消息,而我们的应用程序使用 at-most-once 消息投递语义。
ActiveMQ:broker 集群的配置可能导致在某些场景下,只有在重启 broker 后,消息才会被发送。如需避免这种情况,则需使用至少跨越 2 个数据中心的存储。我们之前使用过 GlusterFS,它并未显示出足够的可靠性。主从集群配置能在 2 个数据中心同步提交数据,但不允许多个 broker 同时运行。
Apache Kafka:虽然 Kafka 是一个广受认可的发布-订阅系统,但它与消息持久性的非功能性需求不兼容。
Apache Spark 和 Apache Storm:依赖 HDFS 基础设施,运营负担重。
NATS 和 NSQ:目前基于 Go 语言的技术栈不能满足对持久化的需求,因此排除 NATS 和 NSQ。
ZeroMQ:需要重写整个技术栈。
Apache Hero:仍在孵化且专注于流式处理。
Apache NiFi:看起来很强大,但需要重新思考整个架构,将事件驱动系统转为基于流的模型。
Apache Flink:专注于流式处理,支持事件驱动应用程序。但研究了其官方用户案例后发现,它并不适合我们的需求。
OpenMessaging:是一种规范而非产品,我们无法直接使用。
Apache Beam:是一个处理框架,简化了基于分布式处理后端编写的批处理或流处理的过程。虽然它很有趣,但并没有解决我们对事件驱动系统的需求。
Apache Pulsar 和 Apache RocketMQ:两者皆声称可以解决我们的非功能性需求,并皆由大公司研发再开源。 我们测试了 Pulsar,发现它上手简单,一天内即可验证所需业务场景。 当然,这并不意味着 RocketMQ 不合适,只是我们认为 Pulsar 非常适合我们的需求。
确定 Pulsar 作为下一代消息平台后,我们将微服务与 Pulsar 客户端集成。
与其它企业级 Java 开发团队一样,WMS 团队通过 EIP 库使用 Apache Camel 与消息队列进行集成,这允许我们在微服务中的应用程序代码和底层消息传递技术之间进行抽象,即当需要更换消息提供者时,该抽象层能提供大量便利。
现在只剩下一个问题——Apache Camel 不支持 Apache Pulsar。为了解决该问题,我们提出了以下两种方案:
从我们的代码库中删除 Camel 库,并通过 Java 客户端库直接与 Pulsar 集成。
编写 Camel 集成组件,保留我们的技术抽象层。
方案 1 需要重写基于 Camel 语义的通用集成库,还需重新实现 Camel 路由语义(将 Camel 中的路由逻辑移植到我们的代码库);而方案 2 与方案 1 耗时相近,但方案 2 只是增加一个简单的依赖,无疑是更优的选择。
THG 与所有以 Java 为中心的公司一样,是开源软件(特别是 Apache Java 库和产品)的忠实拥护者和使用者。作为一家公司,我们却鲜有机会回馈开源社区。
为了更全面地评估消息队列平台,我提交了一些代码更改( https://github.com/apache/pulsar/pull/3812 ),以此评估 Pulsar 社区对外部开发者的开放程度。正如所料,Pulsar 社区热情友好,乐于助人。
对于完全来自于一家大公司的开源项目,核心贡献者可能会存在排他性,导致项目仅是名义上的开源。为了避免这种情况,ASF 要求所有项目(无论来源)必须经历“孵化期”。在孵化期,项目贡献者的来源必须丰富多样,并能扩大项目规模和推进项目可持续发展。
我提交了代码,通过代码审核与 Pulsar 核心研发团队进行了良好互动,这让我更轻松地向 WMS 团队推荐了 Pulsar。
每个开源项目都有不同的代码贡献规范和流程。Linux 内核开发过程与GitHub 项目(例如,Kubernetes)代码贡献流程不同。
之前我已参与了大量 Apache 开源生态系统。我联系了 Apache Camel 团队,基于 Camel 代码库,我们讨论与分配编写新 Camel 组件的任务。
上图为我们通过 Gitter 与 Apache Camel 团队联系,收获颇丰。
开源项目的开发可以分为两个阶段:pre-git 和 post-git。
在 Linus 编写 Git 之前,许多开源项目使用 CVS 或 SVN 进行代码控制,最著名的是 Linux 内核使用的 BitKeeper。
中心服务器方法(例如,SVN)可以限制谁能提交代码至服务器,并定义所有软件项目的代码审查等过程。
Apache 项目有“提交并审阅”的过程,提交至主分支的代码会被审阅,确认无误后会被合进主分支,只有 committer 才有权限合并代码。但对一个项目具备 commit 权限并不意味着对另一个项目也拥有相同权限。
虽然 SVN 有效,但并未吸引大量开发人员(只想更改少量代码来修复漏洞)的参与。SVN 只有少量提交者,他们花费更多时间将开发人员的补丁合入主分支。
随着 Git 和去中心化代码管理系统的出现,简化了补丁管理和代码对比,极大地提高了 Linux 内核团队的发展。Apache 为所有项目库使用 SVN,但很明显 Git 更胜一筹。Apache Infra 团队研究了如何调整流程和技术来保留 committer 或开发者部门。
开源项目的井喷式发展来自于基于 GitHub 的出现,该服务由 UX 团队构建,极大地简化了开发人员的操作。如需进行多人协作,开发人员也无需花费大量时间设置源码管理架构架构(GitHub)。
最近,ASF 已将 GitHub 作为所有 ASF 项目的主要托管方,同时在内部备份 Git 镜像。这是 GitHub 对开源社区的大力支持。
Chuks 和 Richard 团队已开始编写 camel-pulsar 组件的代码。
为了更好地发展开源项目,我们在 GitHub 上创建了 THG OpenSource
( https://github.com/OpenSource-THG )。
在 Camel 的分支完成核心功能后,我们提交了 Pull Request( https://github.com/apache/camel/pull/2866 ),等待审核并解决问题。
另外,我们未使用最新版本的 Camel,而使用了一个能轻松通过测试的版本。
为了兼容 2.x 和主分支(3.x),Camel 开发人员要求我们完成更多代码兼容性工作,但整个过程并未非常耗时。在审阅的过程中,Camel 开发人员针对代码风格、代码重构和代码缺失,提供了非常有价值的反馈。
最终,我们收到了代码通过的消息。
Camel 3 and Camel 2.24 支持 Apache Pulsar,特此鸣谢以下开发人员:
Chukwuedo Abuah @THG
https://github.com/AbuahK
Richard Sherman @THG
https://github.com/rshermanTHG
Andrea Cosentino
https://github.com/oscerd
Claus Ibsen
https://github.com/davsclaus
önder sezgin
https://github.com/onderson
如需实时讨论 Apache Camel,欢迎加入 Apache Camel Gitte( https://gitter.im/apache/apache-camel )。
作者 | Kev Jackson
审校 | Yijie
翻译 | Yu
编辑 | Irene
更多关于 Pulsar 的技术干货和产品动态,请关注 ApachePulsar 微信公众号。