豌豆荚邓草原:如何实现实时响应式平台

jopen 9年前

编者注:本文为Typesafe采访豌豆荚平台架构师邓草原关于如何使用Akka来实现实时响应式平台的经验文章。以下为全文:

今 天刊出的是一篇令我们十分振奋的访谈,访谈对象是豌豆荚平台架构师邓草原先生,内容是探讨 Akka 在中国移动内容搜索平台豌豆荚中所担纲的角色。在我们的采访中,邓草原讨论了如何使用Akka来实现实时响应式平台 (Reactive Platform),表达了他对 Actor 模式的欣赏,并分享了一路走来所遇到过的相关优点和问题。而对于未来的计划以及期待从 Typesafe 看到的改进,他也给出了自己的反馈意见。

Typesafe:请您首先介绍一下自己吧。

邓草原:我从事编程有25年了。我是 NetBeans 的 Scala 插件的作者,前些年也写了一个分布式、并行的实时金融计算和股票交易平台,这个平台是基于 Akka 的 Actor 模式写的,与 Reactive Platform 的理念恰好一致。在用 Scala 和 Akka 编程之前,我也写过大量的 Erlang 代码,也为 NetBeans 写过一个 Erlang 语言的插件(只是这些年没有时间去更新了)。就在一年前,我加入豌豆荚。

Typesafe:那么接下来请您介绍一下豌豆荚。

邓草原:豌豆荚 诞生于2009年12月, 是中国领先的移动内容搜索,主要面向移动娱乐内容领域,是中国的移动互联网行业具有广泛影响力的创新企业。迄今豌豆荚安装量超过4.2亿次,每天新增安装 量超过80万。豌豆荚通过应用内搜索技术,索引了超过1000万内容,涵盖应用、游戏、影视剧和综艺节目、电子书、主题、电影票、问答、旅游等内容类别。

Typesafe:Akka 在豌豆荚扮演了什么角色?

邓 草原:现在每天会有千万级数量的移动设备连到我们的系统。我们希望通过实时响应式平台随时随地、以及更好地为这些设备服务。在互联网时代,网络正在成为一 个实际上折射了每个人的日常生活的“真实”的虚拟世界,或者说,在网络时代,网络将融为每个人的生活本身,而非只是他们生活中的一部分。我相信,从长远来 看,响应式平台将导向这样的一个虚拟世界。

为了实现这种实时性的响应式平台,我们先要创建了一个持久的连接通道,将每台设备与我们的后端, 即“系统”(The System) 相连接。“系统”持续不断地接收来自这些设备的大量事件,并做出即时的响应甚至主动性的“变形”。这正是 Akka 的用武之地。我一直认为 Actor 是最适合并行及增量计算的最小颗粒,想像一下,每个 Actor 对接收到的事件或变化做出相应反应,改变状态,然后传递出新的事件或变化,而并行行为则是大量 Actors 的个体行为的整体表现。如果我们遵循这样一种 Actor 模式,那么每台设备都可以映射成一个 Actor,每个用户也正好是一个 Actor,诸如此类,不一而足,由此组成一个由事件流驱动、并行运行的虚拟世界,它正好是现实世界的映射,像现实世界一样精彩。Akka为这一构想提供 了解决之道。

Typesafe:您能再介绍一些Akka技术在豌豆荚的用例吗?

邓草原:在豌豆荚,作为完整的响应式平台的第一步,我们先现实一套连接和状态服务集群(基于我们的开源项目:https://github.com/wandoulabs/spray-socketio)。该集群可概述为:

  • 无状态的连接层
  • 有状态的状态层
  • 用于业务逻辑的事件流接口
豌豆荚邓草原:如何实现实时响应式平台

上图是架构。连接层保持着每台设备的持久连接。每台设备的状态由状态层的 Actor 对应以保持每个连接设备的状态。Distributed Region 和 Distributed Mediator 则是业务逻辑的接口,其中 Region 根据 ID 来访问每个状态 actor,而所有事件和消息则发布到 Mediator 并最终装换成到 RxScala 的实时事件流,业务层则只需订阅这一事件流。通过上述架构,不同设备可共享和查询状态,双向推送事件和消息,获得实时通知,并且实际上实现了所有设备之间 的连接。

Typesafe:到目前为止,您可以看到 Akka 带来了哪些优势?

邓草原:带来了许多的优势,下面着重列出其中的一部分:

  • 开发效率:在实现 Spray-socketio 之前,我们先完成了Spray-websocket (https://github.com/wandoulabs/spray-websocket), 这是一个基于 Akka 及 Spray 的 WebSocket 协议实现,它通过了所有 Autobahn WebSocket 的测试用例,已经可用于生产环境。基于 Akka 及 Spray 带来的优势,我和我的同事陈兴润 (cowboy129@github) 在三个月的时间里就完成了Spray-websocket 和 Spray-socketio 两个项目的代码。在这期间,兴润还为 Akka 贡献了 DistributedPubSubMediator消息模式的代码。
  • 稳定一致的集群:因为 Actor 模式是同时适用于分布式和并行计算的最佳粒度,所以很容易从向单一服务器转换为向一个集群来部署同样的功能,Akka 本身也即是一个非常棒的具水平扩展、在线均衡调整和在线升级能力的集群平台。
  • 性 能:对于我们的应用场景来说,迄今为止的性能足够好了。我们正在运行的集群现在用 4 个节点维持100万以上的持久连接,每个节点约25万。集群里另外3个状态节点则处理每秒5万次以上的设备心跳,以及另外每秒2万次的状态请求。根据我们 所做的性能测试和估算,集群的能力大约为:每个连接节点可轻易处理100万以上长连接,每个状态节点则可处理1.5万次的状态请求。我们预计,随着更多节 点逐渐增加到集群中,在不久的将来我们可以达到千万级甚至数亿的长连接,每秒处理的消息数则可达数十万条。

Typesafe:是否遇到过一些阻碍?

邓 草原:最主要的阻碍是缺乏 Akka 的最佳实践指引。我们在3个月里开发了整个系统,但是又花了近 2 个月的时间来调整。在最初的发布阶段,我们遇到了节点状态经常出现 Unreachable 的问题,我和兴润几乎每天都要收到监控系统的报警和撰写分析报告。Akka 集群与时间间隔相关的可调参数就有一堆,比如:监控集群节点在线状态的心跳间隔、监测远程传输端口的心跳间隔、监测 Remote Actor 的心跳间隔以及集群 Gossip 协议的发送间隔等等。由于缺乏前人的使用经验,我们只好逐个调整、逐个排除以缩小范围。最后我们发现,问题来自 Remote Actor 的监测。在初期的设计中,状态节点上的 Actors 会一对一地远程监测连接节点上的 Actors,从而产生了每秒数百万的远程监测心跳,这也太多了,对吧。找到问题后我们用了另一种设计从而去掉了这个远程监测,现在集群每天都稳定舒畅地 运行,3 个月来再也没有重启过。从这里学到的是,对于跨节点的大量的 Actors 的远程监测 ,一定要慎重;而从更一般的理念来看,一个基于对等关系的非集权“社会”(Akka集群看上去的样子),如果沟通成本太过高昂,就可能突然陷入混沌无序的 状态,也即失去了对扰动的弹性。但是,这样的对等“社会”,一旦调整到位,就会优雅顺畅地运转。

Typesafe:您最想看到 Typesafe 和 Akka 团队的哪方面的进展?

邓 草原:最让我兴奋的是可以分片部署带状态的 Actors 的 Sharding Cluster 特性。这个特性是 Akka 在今年 3 月份才发布的。它的功能十分强大,可以用在分布式计算的多个领域。例如,在我看来,它可以直接就是一个 Redis 的替代者(每个 key 对应一个 actor), 也可以是实现一套像 AMQP 这类消息队列的很好的起点(每个 queue 对应一个 actor )。从作为 Redis 的替代的角度,我们已经有了一些初步的尝试,即用分片集群来分布式地存储基于 AVRO 格式的记录,数据也是全部保持在内存中。为此,我们还实现了一个类似于 XPath 的表达式,称为 AvPath ,这一表达式可根据路径和条件查询、插入、更新或删除数据。这些都得益于 Akka 的分片集群特性,因为它本身就支持在线均衡调整和水平扩展。我们会在今年晚些时候将 AvPath 开源。

我们还将跟踪 Reactive Streams 的进展,并及时把 Spray-websocket 和 Spray-socketio 迁移到 Akka Streams 。

Typesafe:您期待 Typesafe 和 Akka 有哪些改进?

邓草原:Akka 从分布式计算的学术研究和最佳实践中汲取并融合进了很多内容,我们非常欣赏 Akka 的进展和理念。对于后续的产品和发布,我们期待:

  • 运行时性能改进。运行时的性能显然还有进一步优化的空间。在计划发布的 Akka HTTP 模块中,我们已经看到了parboiled2,它应该会带来更好的性能。我们希望看到 Akka 社区对性能进行更多的剖析,以了解和解决实际应用中的性能瓶颈。
  • 持久化的最佳实践指引。我们也在尝试各种持久化技术,包括 HBase 和 Cassandra 等等,想好好了解对于 Journal Store 和 Snapshot Store 的最适用法。我们希望分享和看到社区中有更多更好的实践案例。
  • 部 署和监控工具。我们希望有一个顺畅的方式来保证集群部署的一致性,而不需要各初去处理、绑定太多预定义的配置参数。我们不确定是否有比 Zookeeper 等更好的方式。此外,我们希望能更容易地定位集群的瓶颈。我们试了Kamon,但是到现在为止还没有成功用在 Akka 集群上。

Typesafe原文链接