Skip to content

Latest commit

 

History

History
77 lines (57 loc) · 6.5 KB

preface.md

File metadata and controls

77 lines (57 loc) · 6.5 KB

构建实时流计算系统

大概但凡写序,应该是在夜深人静的时候吧。

回顾来沪四年,思绪一下子回到了到沪的第一天。

这是我第一次来上海。没有小马哥勇闯上海滩的豪情万丈,但似乎也并未十分惆怅。 只身拖着行李箱去新公司报到,当时住的地方尚未找好,新公司的名字竟也还不到三分确定。 报到的新公司,真的是一家"新"公司,刚刚成立不久,办公室在一个略显陈旧的大楼内,后来才知道那个办公室内还有另外一个公司的人员在那办公。 当时是辉哥接待了我,交给我一个Mac电脑,给我讲了下公司的业务和系统现状。 那是我第一次用Mac电脑,操作还十分生疏。而现在,我正用着这台电脑,写着这篇序。 后来海阳到了,他给我展示和讲解了公司当时的产品。再后来,他还教了我怎样用Mac电脑。 下午的时候我提前下班,拖着行李箱找住的地方去了。 那天当我忙完一切后躺到床上时,意识到真的一切都是新的开始了。 新的城市、新的公司、新的同事、新的业务、新的领域和新的工作内容。

之后就是正式的工作了。 因为是做Java开发的,所以花一天半学了Django,之后接手了Python后台开发。 因为是做Java开发的,所以花一天装了Android Studio,开始了SDK与后台的适配。 因为是做Java开发的,所以Java后台服务更是当仁不让了。 因为是做Java开发的,所以也要负责业务核心算法的开发。 因为是做Java开发的,所以DevOps也得负责推进吧。 因为是做Java开发的,所以...... 那应该是我最专心做开发的一段时间吧。甚至在一年之后的公司年会上还因此获得了一个"最佳沉默奖"。 其实并非我不说话,而是每次市场部的同事看到我时,都是在座位上写程序,好像我从来没离开过座位。 是的,我一直在开发着,但是却并不感到忙碌和紧迫。因为有充足的时间去思考问题、验证猜想并最终解决问题。

从2015年开始,公司因为业务需要,开始涉及实时流计算领域。当时流计算技术远非像现在这样普及。 Flink还没有在国内流行起来,Spark Streaming处于半吊子状态,Storm则还是简单的TopologyBuilder。 不过最主要的问题还是,当时公司虽然意识到我们要使用实时流计算技术,但没有人真正理解实时流计算系统到底该怎么用, 应该怎样将流计算真正贴切地运用到我们的业务需求中去。

在这种情况下,作为后台开发的我开始了自己的思考和探索。 其实解决问题的思路非常简单,用最自然、最贴切、最实际、最节省资源的方式去解决真实的业务问题。 最开始我们选择了Akka来作为流计算框架,可是因为部分同事对Akka的特性理解不到位,导致后来开发出的程序出现各种bug。 比如在actor中光明正大地sleep,不管反向压力导致程序运行一段时间后就OOM,错误使用Akka Cluster导致集群脑裂等等。

在程序开发过程中,我是一个谨小慎微的人,对于任何不确定性的因素,只要想到了就一定会尽力去避免,即使当时别人不理解。 所以从一开始,我就在自己负责的模块中,对Akka添加上了反向压力的支持,就是为了避免执行步调不一致时导致的OOM。 从后来的结果来看,当时的做法是非常正确的。

虽然在Akka中添加了反向压力的支持,可是回看起来实现得过于复杂。虽然保证了反向压力带来的程序稳定性, 可是50行的代码,只有1行是涉及业务处理的。这种解决方案显然非常不明智。

当时,我还在极力尝试着尽可能提高程序的性能,并希望充分榨干机器的CPU和IO资源,以尽可能降低硬件成本。 经过一段时间的调研和思考,我逐渐发现,NIO和异步才是彻底榨干CPU和IO资源的关键所在。 虽然纤程(或协程)也是一种充分利用资源的完美手段,但可惜JVM领域尚无一个公开好用的完美纤程实现方案。 那个时候,我开始隐隐约约地意识到,似乎"流"是一种非常好的编程模式。

首先,"流"与"异步"不谋而合。"流"的各个节点通过队列传递消息,不同节点的执行正好就是完全异步的。 并且由于有队列隔离,不同节点的执行完全不用考虑并发安全的问题。

其次,如果"流"的执行节点间使用的是阻塞队列,那么整个流的各个执行环节就天然地带有了反向压力能力,不需要像之前在Akka中非常复杂的实现。

再次,"流"能够非常自然地描述业务执行的流程。不管是大到整个产品线的各个服务模块,还是小到每个服务模块中的具体实现步骤。 就像分形一样,流能够做任意细力度的划分。这是一种非常普遍的描述事情发生过程的模式。

最后,通过Kafka这种消息中间件的隔离,我可以非常清晰地定义好自己负责开发模块的责任边界,与其他同事的程序隔离开来,避免纠缠不清。 当然这是种自私的想法,但是从设计模式中高内聚、低耦合的角度来看,又何尝不是一种非常不错的实践呢? 更何况Kafka这种好用到爆的消息队列,真的是让人爱不释手呢。

于是说干就干,我花了一个周末的时间,编写了第一个版本的流计算框架。

之后又经过几次大大小小的调整和改进,最终,这个流计算框架进入到了公司所有产品的主要业务模块中。

再后来,我又在这个流计算框架上开发了一个特征引擎,支持DSL和脚本,可以非常灵活、方便、快速地在流数据上,即写即算地实现各种特征计算。 所有特征计算都是并发处理,并且自动解析特征依赖、优化执行过程,可以说还是有一丁点小小的惊艳了。

四年的时光转瞬即逝。其实这四年还有太多太多的事情,从后台到前端、从开发到运维、从数据到系统、从服务器到嵌入式等等, 编写程序、负责项目、担当系统工程师,一路走来,有太多的收获。 真心感谢四年中遇到的许多同事,从他们身上,我学到了太多太多,这些知识会让我受用终身!

但我最想说的是,这四年,我的心变得踏实而不再彷徨。 明年就是而立之年,即将开始人生的下一篇章。而此时的我,已然心有猛虎。

2018年4月6日 于 上海,松江