共计 15647 个字符,预计需要花费 40 分钟才能阅读完成。
Apache Storm 最近成为了 ASF 的顶级项目,这对于该项目和我个人而言是一个重大的里程碑。很难想像 4 年前 Storm 只是我脑海中的一个想法,但现在却成为了一个有着大社区支持并被无数企业使用的繁荣项目。在此我将在本文中回首 Storm 的成长历程及其经验教训。
我会根据我当初必须要克服的主要挑战来涵盖 Storm 历史的相关主题。本文前 25% 是关于 Storm 是如何构思并初创的,所以主要讨论促使我开发这个项目的技术问题。其余部分是关于 Storm 的发布并由活跃用户和开发者社区将其发展成一个广泛使用的项目的发展过程。本文主要讨论了 Storm 的营销,传播和社区的发展。
任何成功的项目都要满足两个条件:
1. 它解决了一个实用的问题
2. 你有足够的能力说服很多人使他们相信你的项目是解决他们问题的最佳方案。
我认为很多开发者难以理解的是实现第二个条件与构建项目本身一样困难和有趣。我希望在阅读 Storm 的历史时能给你一些启发。
Storm 来源
Storm 来自于我在 BackType 的工作. 在 BackType 我们的工作是产品分析以帮助用户实时的了解他们的产品对社交媒体的影响, 当然也能查询到历史记录. 在 Storm 之前, 实时部分的实现用的是标准的队列和 worker 的方法. 比如, 我们向一个队列集合里面写入 Twitter firehose, 再用 Python worker 从这个队列集合读取 tweets 并处理他们. 通常情况下这些 worker 需要通过另一个队列集合向另一个 worker 集合发送消息来进一步处理这些 tweets.
我们非常不满意这种处理方式. 这种方法不稳定 – 我们必须要保证所有的队列和 worker 一直处于工作状态 – 并且在构建 apps 它也显得很笨重. 我们写的大部分逻辑都集中在从哪发送 / 获取信息和怎样序列化 / 反序列化这些消息等等. 但是在实际的业务逻辑里面它只是代码库的一小部分. 再加上一个应用的正确逻辑应该是可以跨多个 worker, 并且这些 worker 之间是可以独立部署的. 一个应用的逻辑也应该是自我约束的.
初探
在 2010 年 12 月,我完成了第一个重大实现。也就是在那时我想出了将 ”stream” 作为分布式抽象的想法。stream 会被并行地产生和处理,但它们可以在一个程序中被表示为一个单独的抽象。这使我产生了 ”spout” 和 ”bolt” 的想法-spout 生产全新的 stream, 而 bolt 将产生的 stream 作为输入并产出 stream。这就是 spout 和 bolt 的并行本质,它与 Hadoop 中 mapper 和 reducer 的并行原理相似。bolt 只需简单地对其要进行处理的 stream 进行注册,并指出接入的 stream 在 bolt 中的划分方式。最后,我所想到的顶级抽象就是 ”topology”-由 spout 和 bolt 组成的网络。
我在 BackType 测试了这些抽象的用例,并且它们之间契合地非常好。我对于它的结果非常满意:我们之前需要处理的繁重工作-发送/接收消息,序列化,部署等都能通过这些新的抽象实现自动化。
在开始构建 Storm 之前,我想用更广泛的用例集来验证我的想法。所以我发了这条微博:
我正在研究一个全新的流处理系统。如果你对这个感兴趣请联系我,我需要你的用例。
— Nathan Marz (@nathanmarz) December 14, 2010
有一群人回应了我,并且我们通过邮件来相互交流。很明显,我的抽象非常非常合理。
然后我开始了 Storm 的设计。在我尝试找出 spout 和 bolt 间传递消息的方式时我很快就被卡住了。我最初的想法是模仿我们之前采用的队列和工人方法并使用一个像 RabbitMQ 的 消息代理来传递中间消息。我实际花费了大量时间来研究 RabbitMQ 用于此目的的方案和操作上的影响。但是,为中间消息使用消息代理的想法似乎并不好,于是我决定暂时搁置 Storm 直到我能想到更好的方法。
再探
我认为需要那些中间消息代理的原因是为数据的处理提供保障。如果一个 bolt 处理消息时失败了,它可以从取得该消息的代理中重试。但是对于中间消息代理,有很多问题困扰着我:
它们是部署于 Storm 之外的巨大,复杂的可移动部分
它们创建了不合适的环境,例如当重新部署 topology 时该如何处置. 这些代理中很可能还有与新版本 topology 不兼容的中间消息。所以这些消息需要以某种方式清理或忽略掉。
它们复杂化了容错性。不仅要指出当 Storm worker 崩溃时的处理方式,我也要指出在某一代理崩溃时该如何做。
它们很慢. 消息不是直接在 spout 和 bolt 间传递的,而是经过了第三方的代理,此外消息还要保存到磁盘上。
直觉告诉我,还有一种不使用中间消息代理也能实现消息处理保障的方式。所以我花费了很长时间思考在 spout 和 bolt 间直接传递消息时该如何保障消息的处理。不便用中间消息持久化,这意味着需要从消息来源 (spout) 中进行重试。棘手的是失败可能发生在 spout 下游的任何地方或另一台服务器上,并且这些失败需要精准检测到。
在苦思冥想了几周后我突然灵光一现。我开发了一个基于随机数和异或运算的算法,它只需大约 20 字节就可以跟踪每个 spout tuple, 不论下游触发了多少处理过程。它是我研究出的最优算法之一,它也是在我生涯中有限的几次,可以说 如果没有接受良好的计算机科学教育我是不会想出的算法。
在想出这个算法之后,我知道我已经取得了重大突破。因为避免了上面提及的所有问题,所以它大大简化了 storm 系统的设计,并提供了一种更加高效的方式。(有趣的是,在我想出这个算法的当天,我还有一个跟最近认识的女孩的约会。但我对该发现是如此激动以致于在整个约会期间我都心不在焉。不用说,我对不住那女孩.)
构建第一个版本
在下面的的 5 个月里,我构建了 Storm 的第一个版本。从一开始我就知道我会开源,因此一开始我在心里就做了一些关键的决定。首先,我用 Java 实现了 Storm 的所有 API,但用 Clojure 来实现 Storm。通过将 Storm 的 API 100% 的 Java 实现,以确保它有一个非常大的潜在用户群体。而使用 Clojure 来实现,我能够更高效以使项目进展地更快。
一开始时我也计划在非 JVM 的语言中使用 Storm。拓扑被定义为 Thrift 的数据结构并提交了一个 Thrift 的 API。除此之外,我设计了一个协议使得 spouts 和 bolts 可以在任何语言中的实现。Storm 可以应用在其他语言让更多的人使用了项目。它让人们迁移到 Storm 中更容易,因为他们不必用 JAVA 重写现有的实时处理器。相反,他们可以迁移现有的代码运行在 Storm 的多语言的 API 上。
我是 Hadoop 的长期用户,用我已有的 Hadoop 经验来设计 Storm 使得 Storm 会更好. 比如, 在 Hadoop 的 workers 不关闭,所有的进程不做任何操作的情况下。这些”僵死进程“积累到一定程度用尽了所有的资源,最终会导致这个集群停止不能运作 –Hadoop 最严重的问题之一. 这个问题的关键在于 Hadoop 中关闭 worker 的工作是由它自身负责。但是有时会因为其他很多原因导致 worker 自我关闭失败. 所以在 Storm 的设计里面,我把关闭 worker 的任务交给第一次启动这个 worker 的 daemon 负责. 最后也证明 Storm 的这种设计比 Hadoop 更鲁棒, 也不存在”僵尸进程”的问题.
我在 Hadoop 中遇到的另一个问题就是如果 JobTracker 因为某种原因停掉, 那么在这个 JobTracker 跑的所有的任务都会终止. 真正让人着急的是已经跑了几天的任务就这样被停止了. 在 Storm 里面不会存在单个节点失败的问题,因为“topologies” 是一旦开始就不会停止的。因为设计 Storm 时就加入了”进程容错“机制:一个 Storm daemon 的停止和重启对一个正在运行的 topologies 绝对不会有影响. 当然这种考量会使设计面临更多的挑战,因为你必须要考虑到进程可能在任何时候用 kill - 9 强行停止和重启的情况, 但是这样也使它更健壮。
在开发阶段的早期我做的一个很关键性的决定就是让我们的一个实习生 –Jason Jackson– 在 AWS 上做一个 Storm 的自动部署工具. 这个工具在很大程度加快了 Storm 的开发,因为它能够让我很容易的测试不同大小的集群和配置,并且迭代更快.
被 Twitter 收购
2011 年 5 月,BackType 与 Twitter 谈收购问题. 从各方面来讲,这次收购对我们来讲非常的重要. 另外, 对我个人而言也很具有吸引力, 因为 Twitter 品牌效应的作用,由 Twitter 来发布 Storm 比由 BackType 发布更能让 Storm 有所作为.
在收购谈判期间, 我在 BackType’s 的科技板块发布了一篇博客向世界宣布了 Storm 的存在. 这篇博客的真正目的仅仅是为了在与 Twitter 的谈判中增加我们的谈判筹码. 它确实起到了作用:Twitter 对这项技术特别感兴趣,在做技能评测的时候,整个评测就演变成了一次大型的 Storm 演示.
这引发了其他令人惊讶的影响。在那篇博客上我不经意的提及 Storm 作为“实时的 Hadoop”,这句话就这样流行起来。直到现在人们还在使用它,甚至被许多人简洁地称为“实时 Hadoop”。这个意外的品牌是非常强有力的,也有利于推广。
开源的 Storm
我们在官方上加入 Twitter 是在 2011 年七月,之后我立即开始计划 Storm 的发布。
有两种方式你可以取得发布版的开源软件。第一种是“使之变大”,为项目做许多宣传,尽可能多地在发布的时候增加曝光率。这条途径会有风险(如果软件质量有缺陷或者你陷入困境,项目的人气就会与日递减)。那样就会杀死任何有可能成功的项目。
第二条途径是安静地发布代码并且让软件缓慢地获得认可。这避免了第一种途径的风险,(因为)它所拥有的风险与人们查看工程是无关紧要的,可以忽略。
更多详情见请继续阅读下一页的精彩内容:http://www.linuxidc.com/Linux/2014-10/108544p2.htm
我决定采用第一种方式。我知道 Storm 是一款高质量且实用的软件,并且因为我有发布第一个开源项目 Cascalog 的经验,我对 Storm 能否获得认可充满信心。
开始我计划通过一篇博文来发布 Storm,但后来我有个在大会上发布 Storm 的想法。在大会上发布可以:
1. 大会能帮助做营销和推广。
2. 我可以直接面向使用 Storm 的潜在早期使用者群体,他们可以通过博客 / 微博 / 电子邮件更大泛围的推广 Storm。
3. 我可以炒作这次会议,建起人们对此项目的渴望,这样在发布的那一天它一定会备受关注。
所以从多个角度考滤,在大会上发布似乎更好。巧合的是,我已经计划在 9 月的 Strange Loop 上讨论一个完全不同的主题。因为我计划在那时发布 Storm, 我给 Strange Loop 的组织者,Alex 发了封邮件,将我的会议改为 Storm 的发布. 正如你从会议简介上看到的,我会以 Twitter 的名义对 Storm 进行介绍。
然后,我开始炒作 Storm。在 2011 年 8 月,会议前的一个月,我在 Twitter 的科技博客板块发表了一篇文章,宣布我将在 Strange Loop 会议上发布 Storm。在那篇文章中,我通过展示 Storm 工作方式的很多细节、并给出示例证明 Storm 的优雅,以勾起人们对 Storm 的兴趣。文章达到了我想要的效果,Storm 让人们很兴奋。
第二天,我做了一些我认为比较聪明的事情。我在 Storm 邮件列表中写道:
如果你想继续了解 Storm 或者对 Storm 有疑问,请加入 Google 讨论组 http://t.co/S7TJlCB。— Nathan Marz (@nathanmarz) 2011 年 5 月。
这就是我认为聪明的原因。为了使项目获得认可,你必须解决的一个关键的问题是建立社会认同。社会认同以很多形式表现:项目的实际使用记录,Github 上关注者,邮件列表活动,邮件列表订阅者,Twitter 粉丝,项目相关的博客文章数量,等。如果我在发布项目时就发起邮件列表活动,那么当人们查看邮件时,邮件会显示没有相关活动且关注者很少。项目有可能会立刻变得很流行,邮件列表活动建立起了社会认同,但是对于这一点,我不敢保证。
在邮件列表发布之前, 我处在被仲裁的情况。开始时人们问问题和订阅, 然后我在建立社会认同感。如果什么事都没有发生, 这并不重要, 因为项目还没有公布。
我在最初的那些日子里犯了一个错误, 从我是在 Twitter 上工作这是奇异的, 不是为项目而注册一个 Twitter 账号。Twitter 的一个很棒的方式让人们保持关注最新的项目以及不断的展示人们的项目(通过转发)。我没有意识到我应该有一个 Twitter 帐户, 直到后来发布, 但幸运的是它证明没有什么大不了的。如果我能再做一次我就会在我的邮件列表上一天内开始 Twitter 帐户。
我写在 Twitter 上的科技博客和奇怪的循环的开始的时间之间, 我花了我的大部分的时间为 Storm 编写文档。为这个项目这是我做的最重要的事情之一。我写了约 12000 字的仔细考虑过得文档——教程, 引用,API 文档等等。很多开源开发者不知道文档是多么的重要: 如果人们不理解你的软件,他们就不会使用你的软件。写好的文档是痛苦的, 耗时的, 但绝对必要的。
项目发布在 2011 年 9 月 19 日进行。在发布时我感觉很高兴。我以“我一直在争论是否开源 Storm”为话题开始了我的演讲,伴随着一声巨响演讲开始,我在观众的惊叹中结束了演讲。在演讲进行到一半时,我说我决定开源 Storm 来做到两全其美。并且告诉观众,如果未来我没有开源 Storm,请在网上大声地喊出来。此时,伴随着观众的尖叫,我发布了 Storm。
一切按照计划进行。Storm 获得了大量的关注,发布的第一天,Github 上的粉丝就超过 1000 人。Storm 立刻登上了 Hacker News 网站的头条。演讲结束,我上网回答 Hacker News、邮件列表活动、Twitter 上人们提出的问题。
发布之后
四天之内,Storm 成为了 Github 上最受关注的 Java, Scala 与 Clojure 领域的项目。两周之内,spider.io 宣布已将 Storm 用在了产品中。我认为那是让人难以置信的,做出高质量的项目与文档的发布承诺,。
Strom 一经发布,我就开始获取用户的反馈。在第一周,我制作了三个最小化的发布,用来解决用户遇到的生命周期的质量问题。尽管他们很小,但我尽可能确保每人都有最佳体验。同时,我也在 Strom 中加入了大量的额外日志,使用户在邮件列表中列出问题时,能够向我提供更多遇到的信息。
我没预料到回答邮件列表里的问题会花费多少时间。邮件列表里有很多的活动,我每天花一到两个小时回答问题。使邮件列表这么耗时的一部分原因是大多数人的提问很糟糕。经常有人问下面的问题:“我使用时元组报很多错误。为什么??“大部分情况下,原因很简单:用户在使用 Storm 时,运用了一些奇怪的配置。但是我不得不花费大量的时间问后续的问题,以获取问题的详细信息,这样我才能帮助他们。用户做了奇怪的操作却不告诉你,你会对这类事情发生的频率感到吃惊,比如同时运行多个版本的 Storm,手动修改本地磁盘上 Storm 的守护进程,运行他们自己修改后的 Storm 版本,或者为 Storm 守护进程配置共享网络驱动器。回答邮件列表上的问题变得越来越耗时(尤其当时我正在 Twitter 上建立一个全新的团队),一年多的时间里我都没有从中解脱。
在接下来的一年里,我在会议上、聚会上、公司里做了大量的 Storm 的演讲。我确信我进行了超过 25 次演讲。我已经达到闭上眼睛就可以介绍 Storm 项目的境界。所有这些演讲使 Storm 越来越有名气。
营销有了回报,Storm 很快获得了产品用户的支持。我在 2012 年 1 月做了一个调查,发现 Storm 已有 10 个产品用户,另有 15 个用户计划将要在他们的产品中使用 Storm,另有 30 家企业对 Storm 进行了试验。在发布后的 3 个月内拥有那么多的产品用户,这对于一个大型的基础型项目来说是非常有意义的。
我建立了一个 Storm“技术支持”页面,以获得最后一张社会认同通行证。用户列表中不仅仅展示公司,我请求每个人把自己加入到列表中,并附上他们如何使用 Storm 的简短说明。这可以让人们在浏览页面时了解 Storm 不同的使用场景和使用力度。对于那些想出现在用户列表的人,我提供了一个我邮箱的链接。像我进行技术演讲一样,这个页面会一直地增长和发展。
填充一个项目的 ”Powered By” 页面有点让人心烦,因为可能有很多人使用你的项目但你却不知道。我记得有一次我收到一封世界上最大的中国公司的邮件,要对将它加入 Storm 的 ”Powered By” 页。那时他们已经用 Storm 超过一年,但我却全然不知道。即使现在,我不知道让别人告诉你他们正在使用你的软件的最佳途径是什么。除了对 Storm”Powered By” 页上我的电子邮件链接外,我用的方法是通过 Twitter 和邮件列表接受提交来填充 ”Powered By” 页面。
Storm 的技术演进
Storm 相比它刚发布时更为先进。发布时它主要是面向我们在 BackType 的需求,当时我们还没意识到各大公司对主要基础设施的需求。在 Twitter 上广泛部署经过一年半的发展后发布了它。
大公司的技术需求与初创公司的是不同的。在初创公司里,一个小团队管理着整个栈,包括所有操作与部署,而在大公司里,这些 功能 一般分配给多个团队。我们从 Twitter 中最先得知的是,人们并不想运行自己的 Storm 簇群,他们只想要一个由他人管理的 Storm 簇。
这预示着我们需要能够拥有一个巨大的、共享的簇,用来运行许多独立的应用。我们需要确保这些应用能够得到足够多的资源,确保在同一簇中一个应用 出毛病 时无法影响到其他的。这就是所谓的“多租户”。
我们也遭遇过进程问题. 当我们扩建共享簇时,注意到相当多的人在构建拓扑时,占用了超出他们实际需要的大量资源。这导致簇的使用非常低效。问题出在没人主动优化自己的拓扑,他们只想运行自己的东西,使它们工作起来,因此在他们眼里没理由不必去占用大量的资源。
我通过开发的“分离调度器“解决了这些问题。这是一个相当简单的用于多租户的解决方案,创建了促使人们高效利用资源的激励机制,允许单簇共享产出与工作负载。
随着越来越多的 Twitter 用户使用 Storm,我们也发现他们需要控制他们的带度量的拓扑,而不是 Storm 默认捕做的。这致使我们开发了 Storm 的优秀的度量 API,允许用户彻底地收藏定制的、任意度量,并发送给任何控制系统。
Apache Storm 最近成为了 ASF 的顶级项目,这对于该项目和我个人而言是一个重大的里程碑。很难想像 4 年前 Storm 只是我脑海中的一个想法,但现在却成为了一个有着大社区支持并被无数企业使用的繁荣项目。在此我将在本文中回首 Storm 的成长历程及其经验教训。
我会根据我当初必须要克服的主要挑战来涵盖 Storm 历史的相关主题。本文前 25% 是关于 Storm 是如何构思并初创的,所以主要讨论促使我开发这个项目的技术问题。其余部分是关于 Storm 的发布并由活跃用户和开发者社区将其发展成一个广泛使用的项目的发展过程。本文主要讨论了 Storm 的营销,传播和社区的发展。
任何成功的项目都要满足两个条件:
1. 它解决了一个实用的问题
2. 你有足够的能力说服很多人使他们相信你的项目是解决他们问题的最佳方案。
我认为很多开发者难以理解的是实现第二个条件与构建项目本身一样困难和有趣。我希望在阅读 Storm 的历史时能给你一些启发。
Storm 来源
Storm 来自于我在 BackType 的工作. 在 BackType 我们的工作是产品分析以帮助用户实时的了解他们的产品对社交媒体的影响, 当然也能查询到历史记录. 在 Storm 之前, 实时部分的实现用的是标准的队列和 worker 的方法. 比如, 我们向一个队列集合里面写入 Twitter firehose, 再用 Python worker 从这个队列集合读取 tweets 并处理他们. 通常情况下这些 worker 需要通过另一个队列集合向另一个 worker 集合发送消息来进一步处理这些 tweets.
我们非常不满意这种处理方式. 这种方法不稳定 – 我们必须要保证所有的队列和 worker 一直处于工作状态 – 并且在构建 apps 它也显得很笨重. 我们写的大部分逻辑都集中在从哪发送 / 获取信息和怎样序列化 / 反序列化这些消息等等. 但是在实际的业务逻辑里面它只是代码库的一小部分. 再加上一个应用的正确逻辑应该是可以跨多个 worker, 并且这些 worker 之间是可以独立部署的. 一个应用的逻辑也应该是自我约束的.
初探
在 2010 年 12 月,我完成了第一个重大实现。也就是在那时我想出了将 ”stream” 作为分布式抽象的想法。stream 会被并行地产生和处理,但它们可以在一个程序中被表示为一个单独的抽象。这使我产生了 ”spout” 和 ”bolt” 的想法-spout 生产全新的 stream, 而 bolt 将产生的 stream 作为输入并产出 stream。这就是 spout 和 bolt 的并行本质,它与 Hadoop 中 mapper 和 reducer 的并行原理相似。bolt 只需简单地对其要进行处理的 stream 进行注册,并指出接入的 stream 在 bolt 中的划分方式。最后,我所想到的顶级抽象就是 ”topology”-由 spout 和 bolt 组成的网络。
我在 BackType 测试了这些抽象的用例,并且它们之间契合地非常好。我对于它的结果非常满意:我们之前需要处理的繁重工作-发送/接收消息,序列化,部署等都能通过这些新的抽象实现自动化。
在开始构建 Storm 之前,我想用更广泛的用例集来验证我的想法。所以我发了这条微博:
我正在研究一个全新的流处理系统。如果你对这个感兴趣请联系我,我需要你的用例。
— Nathan Marz (@nathanmarz) December 14, 2010
有一群人回应了我,并且我们通过邮件来相互交流。很明显,我的抽象非常非常合理。
然后我开始了 Storm 的设计。在我尝试找出 spout 和 bolt 间传递消息的方式时我很快就被卡住了。我最初的想法是模仿我们之前采用的队列和工人方法并使用一个像 RabbitMQ 的 消息代理来传递中间消息。我实际花费了大量时间来研究 RabbitMQ 用于此目的的方案和操作上的影响。但是,为中间消息使用消息代理的想法似乎并不好,于是我决定暂时搁置 Storm 直到我能想到更好的方法。
再探
我认为需要那些中间消息代理的原因是为数据的处理提供保障。如果一个 bolt 处理消息时失败了,它可以从取得该消息的代理中重试。但是对于中间消息代理,有很多问题困扰着我:
它们是部署于 Storm 之外的巨大,复杂的可移动部分
它们创建了不合适的环境,例如当重新部署 topology 时该如何处置. 这些代理中很可能还有与新版本 topology 不兼容的中间消息。所以这些消息需要以某种方式清理或忽略掉。
它们复杂化了容错性。不仅要指出当 Storm worker 崩溃时的处理方式,我也要指出在某一代理崩溃时该如何做。
它们很慢. 消息不是直接在 spout 和 bolt 间传递的,而是经过了第三方的代理,此外消息还要保存到磁盘上。
直觉告诉我,还有一种不使用中间消息代理也能实现消息处理保障的方式。所以我花费了很长时间思考在 spout 和 bolt 间直接传递消息时该如何保障消息的处理。不便用中间消息持久化,这意味着需要从消息来源 (spout) 中进行重试。棘手的是失败可能发生在 spout 下游的任何地方或另一台服务器上,并且这些失败需要精准检测到。
在苦思冥想了几周后我突然灵光一现。我开发了一个基于随机数和异或运算的算法,它只需大约 20 字节就可以跟踪每个 spout tuple, 不论下游触发了多少处理过程。它是我研究出的最优算法之一,它也是在我生涯中有限的几次,可以说 如果没有接受良好的计算机科学教育我是不会想出的算法。
在想出这个算法之后,我知道我已经取得了重大突破。因为避免了上面提及的所有问题,所以它大大简化了 storm 系统的设计,并提供了一种更加高效的方式。(有趣的是,在我想出这个算法的当天,我还有一个跟最近认识的女孩的约会。但我对该发现是如此激动以致于在整个约会期间我都心不在焉。不用说,我对不住那女孩.)
构建第一个版本
在下面的的 5 个月里,我构建了 Storm 的第一个版本。从一开始我就知道我会开源,因此一开始我在心里就做了一些关键的决定。首先,我用 Java 实现了 Storm 的所有 API,但用 Clojure 来实现 Storm。通过将 Storm 的 API 100% 的 Java 实现,以确保它有一个非常大的潜在用户群体。而使用 Clojure 来实现,我能够更高效以使项目进展地更快。
一开始时我也计划在非 JVM 的语言中使用 Storm。拓扑被定义为 Thrift 的数据结构并提交了一个 Thrift 的 API。除此之外,我设计了一个协议使得 spouts 和 bolts 可以在任何语言中的实现。Storm 可以应用在其他语言让更多的人使用了项目。它让人们迁移到 Storm 中更容易,因为他们不必用 JAVA 重写现有的实时处理器。相反,他们可以迁移现有的代码运行在 Storm 的多语言的 API 上。
我是 Hadoop 的长期用户,用我已有的 Hadoop 经验来设计 Storm 使得 Storm 会更好. 比如, 在 Hadoop 的 workers 不关闭,所有的进程不做任何操作的情况下。这些”僵死进程“积累到一定程度用尽了所有的资源,最终会导致这个集群停止不能运作 –Hadoop 最严重的问题之一. 这个问题的关键在于 Hadoop 中关闭 worker 的工作是由它自身负责。但是有时会因为其他很多原因导致 worker 自我关闭失败. 所以在 Storm 的设计里面,我把关闭 worker 的任务交给第一次启动这个 worker 的 daemon 负责. 最后也证明 Storm 的这种设计比 Hadoop 更鲁棒, 也不存在”僵尸进程”的问题.
我在 Hadoop 中遇到的另一个问题就是如果 JobTracker 因为某种原因停掉, 那么在这个 JobTracker 跑的所有的任务都会终止. 真正让人着急的是已经跑了几天的任务就这样被停止了. 在 Storm 里面不会存在单个节点失败的问题,因为“topologies” 是一旦开始就不会停止的。因为设计 Storm 时就加入了”进程容错“机制:一个 Storm daemon 的停止和重启对一个正在运行的 topologies 绝对不会有影响. 当然这种考量会使设计面临更多的挑战,因为你必须要考虑到进程可能在任何时候用 kill - 9 强行停止和重启的情况, 但是这样也使它更健壮。
在开发阶段的早期我做的一个很关键性的决定就是让我们的一个实习生 –Jason Jackson– 在 AWS 上做一个 Storm 的自动部署工具. 这个工具在很大程度加快了 Storm 的开发,因为它能够让我很容易的测试不同大小的集群和配置,并且迭代更快.
被 Twitter 收购
2011 年 5 月,BackType 与 Twitter 谈收购问题. 从各方面来讲,这次收购对我们来讲非常的重要. 另外, 对我个人而言也很具有吸引力, 因为 Twitter 品牌效应的作用,由 Twitter 来发布 Storm 比由 BackType 发布更能让 Storm 有所作为.
在收购谈判期间, 我在 BackType’s 的科技板块发布了一篇博客向世界宣布了 Storm 的存在. 这篇博客的真正目的仅仅是为了在与 Twitter 的谈判中增加我们的谈判筹码. 它确实起到了作用:Twitter 对这项技术特别感兴趣,在做技能评测的时候,整个评测就演变成了一次大型的 Storm 演示.
这引发了其他令人惊讶的影响。在那篇博客上我不经意的提及 Storm 作为“实时的 Hadoop”,这句话就这样流行起来。直到现在人们还在使用它,甚至被许多人简洁地称为“实时 Hadoop”。这个意外的品牌是非常强有力的,也有利于推广。
开源的 Storm
我们在官方上加入 Twitter 是在 2011 年七月,之后我立即开始计划 Storm 的发布。
有两种方式你可以取得发布版的开源软件。第一种是“使之变大”,为项目做许多宣传,尽可能多地在发布的时候增加曝光率。这条途径会有风险(如果软件质量有缺陷或者你陷入困境,项目的人气就会与日递减)。那样就会杀死任何有可能成功的项目。
第二条途径是安静地发布代码并且让软件缓慢地获得认可。这避免了第一种途径的风险,(因为)它所拥有的风险与人们查看工程是无关紧要的,可以忽略。
更多详情见请继续阅读下一页的精彩内容:http://www.linuxidc.com/Linux/2014-10/108544p2.htm
Storm 另一个大的技术跳跃是发展中的Trident,一个 Storm 之上微混合的 API,其提供了精准的一次性处理语义。这使 Storm 可以被应用到许多新的使用案例。
除了所有这些重大的改进之外,这个改进中还有许多生态的改善和大量的性能提升。我们所做的所有工作让我们能够发布许多版本的 Storm–那之后的一年中我们平均一个月发布至少一个版本。频繁的版本发布在项目的成长的初期是非常重要的,因为每个发布都会在人们谈论它时提高知名度。它也向人们展示了项目在不断发展,而且如果他们遇到了问题,项目也将迅速响应他们。
构建开发者社区版
创建开源项目最艰难的部分是构建开发者社区版以促进项目发展。这绝对是让我吃力的部分。
在发布后起初的一年半里,我驱动整个 Storm 的开发。所有的变更都要经过我。以我为中心的发展有优点也有缺点。
通过控制项目的每个细节,我可以保证项目有很高的质量。因为我了解项目的各个环节,我可以预料任何变更对整个项目的影响。因为我有一个项目发展的愿景,我可以防止任何会改变该愿景(或一致的修改)的变更。我可以确保项目始终有一致的设计及体验。
不幸的是,“愿景驱动开发”有一个主要的缺点:这种项目建立一个积极热闹的开发社区非常困难。首先,其他人加入进来并作出贡献很难,因为我控制一切。第二,我是所有开发的一大瓶颈。当达到一定规模是跟上的请求进来的速度(别忘了,与此同时我还在 Twitter 组件了一个全新的基础设施团队)太困难了。所以当反馈 / 合并周期延长时有些人感到气馁了。
围绕自己开发的另一个缺点是,人们视我为一个项目失败的单点。不断有人提醒我如果我被车撞了会发生什么。这个问题确实限制了项目,超出了你的预想,像 Storm,已被许多大公司所采用,但却以我为开发中心,它们包括 Yahoo!、Groupon、天气频道,WebMD、Cerner、百度,阿里巴巴、淘宝以及许多其他公司。
最后,以自己为开发中心最糟糕的情况是我个人觉得负担很大。确实有巨大的压力,休息都很困难。然而,我依然很犹豫是否扩大项目开发控制给别人,因为我担心项目质量。没有其他人会像我一样对整个代码库有深入的了解,而且不可避免的,一下改变会带来意外后果。然而,我开始意识到这是扩展开发者社区时你要必须面对的。但我意识到这并不想我担心的那样是个大问题。
离开 Twitter
当我在 2013 年三月离开 Twitter 去追求我的新起点时,我仍然身处 Storm 开发的中心。几个月后,这成为一个需要优先删除的项目瓶颈。我觉得在共识驱动的发展模式下,Storm 会更好发展。
我认为当项目还没有得到充分的探讨解空间“愿景驱动开发”是最好的。因此 Storm 包含我所有的决定,我们构建的多用户、自定义的度量、Trident 以及主要性能重构都是好事。主要的设计问题只能由对整个项目有深入了解的人解决。
我离开 Twitter 的时候,我们已经绘制了 Storm 所能解决问题的模型。这并不是说没有更多创新的可能–Storm 自那之后有了很多提升–但这些创新的改进并不一定是令人惊讶的。许多工作,自从我离开 Twitter 后 Storm 从 ZeroMQ 转为 Netty,实现了安全 / 认证,提高了性能 / 可扩展性,提升了拓扑的可视化,等等。这些都是可怕的改进,但都是 2013 年三月时预期的改进方向。换句话说,我认为当问题解决空间仍具有很大不确定性时“愿景驱动开发”是必要的。当问题解决空间比较好理解时,“愿景驱动开发“的价值显著减少。然后会出现个人成为瓶颈而严重抑制项目的成长。
大约离开 Twitter 四个月的时候,Yahoo! 的 Andy Feng 强烈建议我将 Storm 提交到 Apache。那时我刚刚开始思考如何确保 Storm 的未来,Apache 似乎是个有趣的想法。我会见了 Hadoop 的创造者 Doug Cutting,获取他对 Apache 的看法以及 Storm 转移到 Apache 的潜在风险。Doug 给我说了 Apache 如何工作的概述,坦诚地谈了 Apache 的利弊。他告诉我说,孵化器有些混乱,这最可能是过程中最痛苦的(但在实际中,过程却令人难以置信的平滑)。Doug 的意见是非常宝贵,他真实帮我了解了共识驱动的开发模型。
在共识驱动开发中,至少包括其如何为许多 Apache 项目使用的,变更需要项目组“提交人员”的投票。通常一个变更需要至少两个 + 1 同意并且没有 - 1 反对票。这就意味着每个提交人员都有否决权。在一个共识驱动的项目中,不是每个人都会对代码有全面的了解。许多开发者会专注于代码的不同部分。随着时间的推移,一些参与者将学习到更多部分的代码并更深入的了解一切是如何配合的。
当 Storm 首先转移到共识驱动模型时,大多数的参与者对代码的理解不成整体比较有限,有的是不同专注领域的理解。这完全是因为我一直占主导开发地位的原因–没有人曾经被赋予他们需要学习更多以做出正确决定的责任。通过给其他人更多的权力和并退后一步,我希望别人能填补这一空白。这就是确切发生的。
当转移到共识驱动开发时我的一个担忧是开发质量会下降。而事实上,我们的转换中的一些变化导入了 bug。但这没什么大不了的。因为你会得到错误报告,并在下个版本中解决这个问题。如果问题真的是很大,你可以放出一个紧急版本供他人使用。当我独自一人做所有开发决定时,我会自己彻底测试,并利用我对整个代码库的了解去释放高质量的代码。但即使这样,我的代码有时仍有 bug,我们要在下个发布时解决它们。所以共识驱动开发也没有什么不同,除了变更的问题可能需要更多的迭代来解决这个不同。没有软件是完美的–重要的是,要有一个积极负责的开发社区,去迭代和解决出现的问题。
提交到 Apache
回到 Storm 的历史,离开 Twitter 几个月后我决定将 Storm 转换为共识驱动开发模式。我很专注于我的新起点,我也希望 Storm 有长期的住所会给用户的信心:Storm 会有兴起的日子。我考虑所有的选项时,提交 Storm 到 Apache 似乎是最好的选择。Apache 会给 Storm 带来强大的品牌,强大的法律基础以及我希望项目拥有的完全的共识驱动模型。
通过运用我从 Doug Cutting 的所学,我小心翼翼地将 Storm 往 Apache 转移:着手之前事先甄别孵化过程中可能引起的任何法律问题。Storm 使用 ZeroMQ 库用于内部进程间通信,但不幸的是,ZeroMQ 许可与 Apache 基金会的政策不相容。Yahoo! 的一些开发者(他们后来成为 Storm 的提交者)推进并基于 Netty 创建了一个替代。
在形成 Storm 的初始提交者名单时,我选择了不同公司并对项目有较大贡献的开发者。一个人我超级高兴能够邀请到的是者是 Taylor Goetz,他当时在健康科学市场(Health Market Science)工作。我犹豫是否邀请他是因为他那时他还没有贡献代码。然而,他在社区和邮件列表上非常活跃,所以我决定在他身上试一下。成为体检者后,Taylor 采取了大量的行动,分担了许多项目的管理负担。孵化期间他处理大部分细节的东西(比如顾及某些法律的事情,弄清楚如何将网站迁移到 Apache,如何进行提交者的权限管理,管理发布,呼吁投票,等)。Taylor 后来去了 Hortonworks 为 Storm 全职工作,他做了出色的工作来帮助 Storm 通过孵化器,他现在是该项目的 PMC。
2013 年九月,在 Yahoo! Andy Feng 的帮助下,我正式宣布 Storm 在 Apache 孵化。因为我们预先准备好了,建议中只有一些小的修改需要。
Apache 孵化
孵化过程中,我们必须证明我们能够保证发布,发展用户社区,并扩大项目的提交者。完成这所有内容我们没有遇到任何问题。一旦 Storm 孵化成功,我不再是瓶颈,开发迅速加速。提交补丁的迅速反馈促使了更多的贡献。我们鉴定大家贡献的重要性并邀请他们成为提交者。
因为孵化后我像其他提交人员一样只是提交者,投票的比重也是一样的。我集中精力关注影响 Storm 核心的任何问题,或那些有困难的设计决策。这样更有效地利用我的时间,能够审查每个小小的变化也是项巨大的安慰。
Storm 在 2014 年 9 月 17 日正式步入顶级项目的行列,在开源后短短的三年后。
结论
构建 Storm 并发展到现在是段不易的旅程。我认识到创建一个成功的项目需要的不仅仅是产生好的代码来解决重要的问题。文档,营销,以及社区的发展也同样重要。特别是在早期的时候,你必须要有创意并想出清晰的方法来起始项目。我所做的是利用 Twitter 的品牌,从邮件列表开始直到发布前几个月,并做一个最大限度地曝光。此外,参与建设一个成功的项目还有很多繁琐费时的工作,如写文档,回答无休止邮件列表上的问题,培训宣讲。
我看到的最惊人的事情是 Storm 对行业大范围的影响。在 Powered By 页上,有医疗保健,天气,新闻,分析,拍卖,广告,旅游,报警,金融等诸多领域的应用。阅读该页回顾大量工作我觉得对 Storm 的投入是值得的。
讲述这个故事的过程中我无法包括每个细节(毕竟三年是段很长的时间)。所以我想通过列出那些对 Storm 今日的所成重要的人物。我对所有这些人非常感激:Chris Aniszczyk, Ashley Brown, Doug Cutting, Derek Dagit, Ted Dunning, Robert Evans, Andy Feng, Taylor Goetz, Christopher Golda, Edmund Jackson, Jason Jackson, Jeff Kaditz, Jennifer Lee, Michael Montano, Michael Noll, Adrian Petrescu, Adam Schuck, James Xu 以及那些曾为项目贡献过补丁、部署过生产环境,写使用经历或推介过它的人。
Apache Storm 的详细介绍:请点这里
Apache Storm 的下载地址:请点这里