写在前面

2016 年 11 月 11 号, 对阿里巴巴中间件消息团队来说,有着极其特殊的意义。这一天,在光明顶上奋战的小伙伴们见证了 RocketMQ 低延迟存储架构的成功试水,完成了保障双十一如丝般顺滑的既定目标。在另一个战场,历时 3 个月的开源重塑之后,Apache RocketMQ Champion Bruce 代表团队正式启动了 Apache 捐赠工程。至此,RocketMQ 开启了迈向全球顶级开源软件的新征程。

截止今天,RocketMQ 进入 Apache Incubator 已经 7 个月有余。在这半年多的时间里,团队走过很多路,也经历了很多事。

  • 第一次按照 Apache Way 走通 Apache 软件发布流程,完成了在整个 IPMC 都极为罕见的 Rc3 发布壮举,体现了中国团队的严谨、高效,赢得了社区的赞誉。
  • 第一次吸纳外籍 Committer - 日本博士 Roman。2 个月时间里,他提交近 20 个 Pull Request,推动 RocketMQ 跟 Apache 其它顶级社区项目合作,对社区起步做出了卓越贡献。
  • 第一次面向社区举办编程马拉松。PMC 成员全程跟进,帮助参赛选手评审设计、Review 代码。
  • 第一次吸纳 PMC 成员。在 RocketMQ 社区,PMC 是对 Committer 持续贡献的进一步 Merit。
  • 第一次向 Apache 社区昭告 OpenMessaging 标准的愿景。紧接着, ASF Director Jim 毛遂自荐,加入到 RocketMQ 超强豪华的全球 Mentor 阵营中。
  • 第一次面向国内社区举办了大型 MeetUp。全球图文现场直播,5 场纯技术 Messaging & Streaming 干货分享,传达了团队誓将做好社区,搞好生态的决心。
  • 第一次......

人生就是一场跋涉,走久了,才知心酸,才知艰难,才有坚韧,才有渴望。前方的路,尽管遥远,尽管颠簸。但脚步依然,追求依然,方向依然。

2017 年 8 月 3 号,团队正式发起了冲击 TLP 的讨论。接下来的一个月时间里,讨论和投票,几乎成了每天的必修课。终于,抢在 Java 9 发布之前,RocketMQ 正式通过董事会决议,结束了在 Apache 上的孵化,正式成为 Apache 340 多个顶级项目中的一员。这一刻,完全出自中国团队,来自阿里巴巴的分布式消息引擎成为全球互联网中间件、大数据领域璀璨的新星。下一站,等待它的将是在国际舞台上与世界顶级老牌消息中间件的激烈角逐。相信在 Apache 先进的社区理念指引下,RocketMQ 社区生态会继续蓬勃发展,完成我们所赋予它的光荣使命。

接下来,我们从产品、社区、生态这三个维度,分别回顾一下 RocketMQ 这半年多的 Apache 孵化历程。

产品篇章

与 Apache 大多数顶级项目不同,RocketMQ 在进入 Apache 之前,Open Source 之路已经走过了 3 个春秋。历经多次双十一洗礼,在国内积累了一定的口碑,社区也有不错的 Active Contributors,但这些还远远不够。在正式开启捐赠之前,团队对 RocketMQ 甚至包括社区做了大量重塑工作。如国际化方面,在 Github 上利用 sidebar 特性重新设计编排了文档。如今,User Guide, Quick Start, Architecture & Design, How to contribute, Community, FAQ 这些几乎成为了团队新产品标配的文档结构。

代码层面更是进行了比较“激进”地优化。如去除 GBK 字符,全面拥抱 UTF-8。重写 API JavaDoc。清理代码,优化代码结构。利用 JDepend 优化组件之间的抽象依赖关系。利用 Findbugs 扫描代码漏洞,指导规范编码。交付方面,规范 Release 流程,New Features、Improvement and Bug 分类 Release note。社区层面则开启了全英式互动,发布问问题的技巧。

经过这些精心的准备,RocketMQ 完成了从 3.0 到 4.0 的悄然升级。而 4.0 是个过渡版本(和 3.0 相比,架构层面没有较大的改变),也是在 Apache 开启孵化的版本。通过孵化,团队重新认识了软件研发流程的重要性,尤其是像精细设计,代码 Review,编码规约,分支模型,发布规约等容易被忽略的过程。无以规矩不成方圆,尤其是当你置身于并领导一个全球协作的开源项目时,这些都显得是尤为重要。

编码规约

RocketMQ 的编码规约是比较宽松的,至少在 4.0 这个版本上。与其它 Apache 顶级项目不同,我们并没有从编码细节上去做过多约束,如静态变量如何使用,日志怎么打,异常怎么捕获、处理。而主要通过 Code Style, Copyright, Code Template 3 块来进行一些大方向上的约束。为了防止不遵循规约的代码合并仓库,我们通过 PR Checklist, checkstyle 和持续集成来自动化校验行为。因为我们相信,凡是有人介入的地方,就存在 check 的必要。凡是有人介入的地方,就存在自动化的可能。

研发流程

RocketMQ 的开源模式不是传统意义上的开放内核模式,而是和 Apache Hadoop 和 OpenStack 这一类开源平台模式类似,我们尝试把开源世界和专有世界最好的结合起来,在真正意义上的协作平台上生产专有产品。我们希望 Redhat,CentOS 和 Fedora 这样的产品簇协同发展效应也能体现在 RocketMQ 未来的演进中。为了迎接这样的挑战,团队必须从软件研发流程方面做出改变,构建能够同时支撑内部、开源社区以及商业化的生态体系。

分支模型

RocketMQ 在设计之初就曾设想过未来 One Kernel 这样的产品形态。这些年下来,围绕着它,团队打造了 AliwareMQ、MetaQ、以及 Notify 3.0 等内部、商业化产品。随着 RocketMQ 进入 Apache,代码的演进变得愈加复杂,而传统的 Master 分支模型很难满足开源、商业化、集团内部和公有云、私有云共用一个 RocketMQ 内核这样的需求。通过不断的思考与实践,我们通过引入镜像仓库机制解决了这一难题。具体讲,就是通过在每个仓库配置 master 和 develop 分支,不同的仓库直接由镜像节点进行转换和特性缓冲。这样下来,在 Apache 上孵化的特性可以一路合并至内部甚至输出到公有云、私有云,在内部孵化的特性也能以 PATCH 的方式反哺到开源社区。如下图所示:


阿里RocketMQ是怎样孵化成Apache顶级项目的?_java


借助 Travis 和 Jenkins,我们搭建了两套基础设施。在 Github 上,Travis 会对所有 commit,所有 PR 触发持续集成,这是它的一个强大之处。除此之外,它还支持跨 JDK,跨平台的 Matrix 验证(不过很可惜,OSX 平台似乎一直都有问题)。在内部,利用 Jenkins 2.0 的 Pipeline 实现了持续集成,持续压测,持续交付(Docker,Pandora 以及 AWS Cloud,Azure Cloud)。如下图所示:


阿里RocketMQ是怎样孵化成Apache顶级项目的?_java_02

由上图可知,整个持续集成分为代码静态检测,单元测试,集成测试,Sonar 质量评测这个几个 Stage。对于单元测试,不仅要覆盖核心逻辑,而且要快(内置 3 分钟阈值,超过就报错和发邮件)。无数实践告诉我们,如果不够快,就会有更多的同学在本地编译时选择跳过单测,久而久之,单测就慢慢失去了意义,变得愈发不可维护。要全,要快,还要可维护性。这对单测编写者来说无疑是个巨大挑战,这就要求多线程之间的交互尽量避免依赖 sleep,自底向下的尽可能 Mock 依赖,动宾状结构的优雅命名,断言异常而不是抛出异常。


进入 Apache 后,尤其在孵化阶段,学习并遵循 Apache 发布流程显得尤为重要。


阿里RocketMQ是怎样孵化成Apache顶级项目的?_java_03

上面这幅图描述的是 Apache 孵化项目的发布流程。快、稳,这是 RocketMQ 团队第一次发布传达给社区的信息。纵观所有 Apache 孵化项目,能够在这么短的时间内,用这么少的次数 (RC3) 学习并走完发布,用行动证明中国人同样具备严谨且专业地做事态度。当然,我们也是幸运地,幸运地碰到了 Justin 和 Bruce 这两位热心、专业的 Mentor。这里,需要强调下 Release 生成的几个重要文件,如下图:


阿里RocketMQ是怎样孵化成Apache顶级项目的?_java_04

源码 (src) 和二进制文件 (bin) 被分别打包。asc 是一个签名文件,committer 使用自己的私钥对分发包进行签名,任何人可以用我们对外公布的 512 位的公钥进行验证。

另外,还有一个不得不提的事情。Apache 对 License 进行了严格的分类,比如 Apache License 2.0/1.1,BSD,MIT/X11 等属于 Category A,这些协议与 Apache License 是兼容的,可以放心地引入。对于 Category B 中的 License,比如 EPL 1.0,MPL 1.0/1.1/2.0 等能够以 binary 的形式引入。对于 Category X 中的 License 如 GPL,LGPL 则不能引入到产品当中。

针对 License 的问题,RocketMQ 在首次发布的时候,在社区里进行了充分讨论。如何处双重 License 的依赖,如何区分 Source 和 Binary Release 依赖的 License 问题,如何处理 NOTICE。这些知识被我们“现学现卖”的用在了指导社区贡献上面,既加强了记忆,又很好地传承给了社区。


这是一个 RocketMQ way 的具体体现。针对 PR,我们设计了一套 Checklist,如下图所示:


阿里RocketMQ是怎样孵化成Apache顶级项目的?_java_05

所有 PR 必须有 3+ Committer Review,Committer 提交的 PR,尽量不要自己 Merge。另外,PR 的合并是个费时费力的工作,团队成员通过研究,编写了一个自动化 Python 脚本,巧妙地将原先几分钟的常态工作缩减到了几秒钟,一定程度上体现了中国工程师“懒中求胜”的匠心精神。而 Jira,我们强调 component,每个 component 都有 2 到 3 位 committer or maintainer 把持。Jira 的处理一般是需要经过 Resolve 阶段,最后才是 Close,并且详细标明受影响的版本,在哪个版本修复掉。

社区篇章

在产品篇章里,我们主要从编码规约,分支模型,持续交付,发布规约等环节回顾了这半年来可喜的变化。接下来的社区篇,我们将聚焦社区,重点介绍 Apache Way,RocketMQ Way,以及社区成熟度模型。至于品牌 & 社区的 Building,业界也有很多实践,如 DevRel,JUG 等。这里,放张图感受一下。


阿里RocketMQ是怎样孵化成Apache顶级项目的?_java_06

Apache Way

在 Apache 社区,一个很重要的理念,Community over Code。社区是判断一个孵化项目能否毕业的重要考核标准。但这并不意味着 Code 就不重要。仔细回想一下,在你接触过的所有 Apache 顶级项目中,有没有给你留下深刻印象的 Code(请允许我拿代码来说事,代码就像一面镜子,是工程师的门面,也是工匠荣辱的最直接体现)。相信那些研究过大量 Apache 顶级项目的同学,一定有和我一样的感受。Apache 在大力强调社区的今天,很容易给大家让大家误解 - 设计不重要了,代码不重要了。试想下,如果产品的设计,产品的质量不过硬,又怎么指望会有一个健康多元的社区呢?所以,我们重视社区,但也重视设计,重视代码质量,重视产品带给用户的体验。


阿里RocketMQ是怎样孵化成Apache顶级项目的?_java_07

上面这幅图节选自之前 MeetUp 上的分享,是我们对于 Apache Way 的理解。

  • Community - Over Code,首先要认识社区,社区包罗万象,有 Developers,Writers,Testers,Sysadmins,Devops,Users 等等,但不需要 Employee。由 Employees 打造的社区是不健康的,不可持续的,缺乏多元化。国际上一些大公司,早期参与 Apache 项目,一味想着控制社区,殊不知 Apache 社区理念的精髓在于与社区,与其它企业,其它个人贡献者,培养协作,加速项目与个人的成长。社区不会凭空产生,不是把项目往 Github 上一丢就是开源了,然后社区就会自动产生。一个社区的经营是需要花费心思的,发展一个社区成员,争取一个国际贡献者,这些都是一个长期经营的过程。RocketMQ 社区的第一个国际贡献者,我们整整跟进、鼓励了近 2 个月。当然,还有不少老外也表达出了贡献社区的兴趣,万丈高楼平地起,先从最基本的工作做起,让社区看到你的努力,看到你持续跟进、贡献社区的决心,Apache Committer(认证程序员)自然离你不远。
  • Merit - Recognizing Your Work,参与社区的建设能获得什么,一个 Contributor 在社区的所有努力是有目共睹和有迹可循的,提交了多少 Issue 和 PR?参与了多少 Code Review,邮件列表里是否总有真知灼见冒出来,这一切都在 Github、JIRA、和邮件列表里进行了沉淀,在得到社区的认可后,Contributor 变成为了 Committer,Committer 变成为了 PMC Member。一步一步,社区认可了你的贡献,你也获得了不错的成长。
  • Open Development - For Everything,社区一切都是开放的,特别是对于开发,每个人都可以参与到每行代码中,从开发前的 DISCUSS,再到 Pull Request 中的 Code Review,甚至作为 User 使用方面的 Feedback。所有的讨论,思想的碰撞,甚至是争论,都是 Public 的。对于国内社区,我们一直在鼓励所有线下 (包括 QQ) 的重要讨论,在邮件列表里都能有所体现,一切都是开放与透明的,没有私下的决定。
  • Decision Making - Consensus & Votes,绝对的开放也会带来一定的弊端,如流程上的繁琐与拖沓。在社区做决议,首先需要通过在邮件列表中发起讨论,达成一致后,需要再发起一次投票,并至少等待 72 小时(考虑全球时区)后才能宣布投票结果。流程虽繁,但决议一旦通过,就坚决执行,这也是一种社区执行力的体现。

在学习和实践 Apache Way 的过程中,团队也摸索出了一套我们称之为 RocketMQ Way 的最佳实践。

  • International Collaboration - 禁止中文注释,允许 User 邮件列表使用中文提问,但 Dev 邮件列表必须使用英文。关于几个邮件列表的用途,请参考官方说明。
  • PR Management - Pull Request 提交、合并需遵循一定的规约 (checklist);每个 PR 必须有足够的单元测试,集成测试,有增量的代码覆盖率要求;PR 的合并有 3+ +1,Committer 提交的 PR 不要自己 Merge。
  • Diversity Review - 对于 Committer 代码实施 CTR(Commit then Review) 策略,对于 Contributor 则是 RTC(Review then Commit) 策略。
  • Branch Model - 采用双主干模式(Master 与 Develop),秉持 One kernel 的理念。
  • Community CodeMarathon - 不定期的编程马拉松,挖掘社区活跃的贡献者,培养并辅导社区的深度参与者。
  • Ecosystem Assemble - 独立仓库,为社区项目安营扎寨。每个个体在贡献之前,首先要提交 Apache 的 ICLA。
  • One contributor, One Mentor - 每位 PMC 成员都有义务帮助社区 Contributor,辅导并带领他们熟悉 Apache Way,成为 Committer 甚至是 PMC Member。

网站流量的变化

半年多的时间里,我们陆续在云栖社区,CSDN,InfoQ 中文站、国际站发表了多篇技术文章,撰写国际论文,在 ApacheCon、LinuxCon 等国际顶级开源峰会发表主题演讲,全球图文同步直播 Meetup。通过这一系列国际输出,网站流量迎来了可喜变化。

通过这幅图可以看到,美国现在已经是 RocketMQ 全球第 2 大访问国。这对团队即将开展的 Aliware MQ 国际战略,奠定了良好的基础。同时,这种持续走高的流量也在不断鞭策着我们,写高质量代码,做高质量产品,向全球输出中国智 (质) 造。

成熟度评估

坦白说,RocketMQ 进入 Apache 之初,并没有针对这个模型做任何学习(讨厌应试教育)。我们希望通过自己的理解和践行,完成全球社区的构建,完成毕业。令人惊喜的是,当团队 8 月份开始正式审视毕业 TODO List 时,发现 Apache 的理论指导和我们的实践惊人的一致。理解万岁!下图是 RocketMQ 的社区成熟度评估。


阿里RocketMQ是怎样孵化成Apache顶级项目的?_java_08

阿里RocketMQ是怎样孵化成Apache顶级项目的?_java_09

生态篇章

作为国内首个非 Hadoop、Spark 大数据生态下的 Apache 顶级项目,我们在打造多元化社区的同时,也在努力构建以 Messaging 为 Core 的生态体系。之前提到过的,我们为社区生态贡献者提供了单独的 Apache 代码仓库。这一做法,现在也在纷纷被其它 Apache 顶级项目所效仿。截止目前为止,来自社区贡献的 RocketMQ-Console, RocketMQ-JMS, RocketMQ-Flume,RocketMQ-CPP 等生态项目已经在诸多公司内部进行了线上验证,像 RocketMQ-Druid,RocketMQ-Ignite,RocketMQ-Storm 等项目,代码更是被合并进对方仓库,这也使 RocketMQ 和其它顶级开源项目、社区之间有了更多连接。更多的生态项目介绍,请参考官网介绍。


阿里RocketMQ是怎样孵化成Apache顶级项目的?_java_10

Messaging 生态


阿里RocketMQ是怎样孵化成Apache顶级项目的?_java_11

上面这幅图是团队围绕着 OpenMessaging 标准而努力打造的生态体系。OpenMessaging 是团队多年来从事 Messaging 领域研究的一个经验提炼。经过半年多的发展,这套标准已经进入 Linux 基金会,接下来会进入到 CNCF,成为云计算不可或缺的标准之一。而这套 API 级的跨平台,跨语言标准,会尝试解决之前我们遇到但未曾彻底解决的所有问题。如下图所示,分布式事务,我们内部的产品 MateQ 和 Notify 也有类似的特性,但这种分布式事务更多的是发送者分布式事务,并不是真正意义上的分布式事务。负载均衡,在拉模式和推模式下策略会有所不同,消息本身的 sharding 也会因业务场景不同而不同。分布式追踪,主要是考虑 Linux CNCF 中的 opentracing。协议桥接,主要是考虑如何和现有的标准,如 JMS 进行无缝桥接。流计算,通过引入流计算算子,在消息投递过程中针对内容进行计算。Benchmark,类似 SPECJMS,把所有 Messaging Engine 拉到同一基调上做性能测试。


阿里RocketMQ是怎样孵化成Apache顶级项目的?_java_12

总结一下,基于 OpenMessaging 的下一代的消息引擎 RocketMQ 5.0 主要会在四个领域持续发力:电子商务,高并发下削峰填谷。物联网领域,海量连接同时在线。大数据领域,吞吐为王。金融领域,重要的是高可靠,数据冗余。

写在最后

最后,我们再来看一个大家比较关心的问题:团队在开源上到底投入了多少?

原则上,我们希望团队每个人投入一些时间(10%~20%)。时不时的复盘,我们惊讶地发现最终的投入要远远小于这个值。当然,这也是团队现实所决定的,除了开源,团队目前还有内部、公有云、私有云的研发支撑工作。除了 RocketMQ,团队还在 AliwareMQ,Kafka,中继等产品上持续耕耘。当然,更不能忘记 OpenMessaging,这一极具挑战的规范演进。自然而然的,团队纳新就成了迫在眉睫的事情,我们希望在分布式、大数据、多语言架构领域有较高造诣,有追求的同学加入团队,而团队也会努力为大家创造极具挑战的施展空间。我们重视成长,关注可持续发展。Apache RocketMQ 顶级项目的毕业只是一个开始。前路漫漫,未来可期!

始于 2017.8.03 晚,终稿于 2017.9.20 Apache 董事会决议前