转载

《Spotify的入云之旅》系列之二

写在之前

当Spotify的用户打开客户端听歌或者搜索音乐人,用户的任何一个触发的事件都会传送回Spotify的服务器。事件传输系统(也即,日志收集系统)是个有趣的项目,确保全球用户使用Spotify客户端所产生的事件都完全、安全的发送到数据中心。在本系列文章中,将讲述Spotify在这方面所做过的工作,而且会详细解说Spotify新的事件传输系统架构,并回答“为什么Spotify会基于Google云平台管理建立自己的新系统?”。

在第一篇文章里,讲述了Spotify旧事件传输系统是如何工作的,以及一些经验总结。在本篇文章,将阐述Spotify新事件传输系统的设计,并解释为什么Spotify公司选择Google云发布/订阅组件作为所有事件的传输机制。

Spotify新事件传输系统的设计

从旧事件传输系统运行过程中获取的经验给我们设计新事件传输系统提供了很大的帮助。新事件传输系统选用创新的复杂设计,比如每台事件生产机器都进行文件结束标记的传播和确认;旧系统中对于失败的情况不能进行自动恢复,对于大面积失败的情况,每个生产日志的机器进行手动人工干预会耗费很大的操作成本。在新系统中进行了简化处理,每台日志生产机器都会把自己的事件移交到一小部分机器上,选择的这些机器是在网络上尽可能离下一步处理更近的机器。

还有一个注意的地方是,需要一个事件传输系统或者队列来保障事件传输的稳定性,以及持久化在队列中未传输完的消息。我们应该做到生产者以较高的频率来转移事件到最近的其它生产者机器上,并要求低延迟的回传收到的确认信息。

另外变化的地方是,每个事件类型有自己的频道(channel)或者topic;在事件处理的早期就转化成结构化的数据。把转化数据格式的工作放在事件生产者的好处在于缩短数据清洗(ETL)任务的时间。建立独立的topic是为了提高后续在实时处理的效率。新事件传输系统设计成可以和现有旧系统并行运行,生产者端和消费者端的接口都可以匹配当前系统。这样可以在切换系统前进行新系统的性能等校验。

(点击放大图像)

《Spotify的入云之旅》系列之二

图1 新事件传输系统的设计

新事件传输系统主要包含四个组件:File Tailer,Event Delivery Service,Reliable Persistent Queue和ETL job。

  • File Tailer功能比旧系统中的Produce有所收缩,它跟踪日志文件的尾部监控新事件的插入,并转发新事件信息到Event Delivery Service组件,然后File Tailer得到事件传输完成的确认消息。
  • Event Delivery Service组件从Tailer接收事件数据,转化他们成最终需要的结构化数据格式并转发到队列Queue中。Event Delivery Service是一个RESTful风格的微服务,用 Apollo微服务框架 和 Helios自动化部署平台 开发,使得各服务间解耦。

  • 队列Queue是新事件传输系统的核心,对爆发增长的数据可以快速扩展。为了应对Hadoop集群可能出现的故障,需要能稳定保存数天的消息。

  • 清洗任务(ETL job)能够保证稳定、可重复运行,并能从队列Queue导出事件到HDFS上的小时桶(Spotify的数据是按小时分桶)。ETL job需要保证桶的所有数据被消费完才可以把一个桶的数据传输到下游消费者。

在图1中,你可以看到一个标有“Service Using API directly”的图框,它是syslog的API,当新事件传输系统上线后,“Service Using API directly”可以直接与Event Delivery Service通信。

选择可靠的持久化队列Queue

Kafka 0.8

建立一个可靠的持久化队列系统处理Spotify事件是一个艰巨的任务。事件传输系统是数据架构的一个基础部件,它的安全性、稳定性非常重要。我们首选是Kafka 0.8。

全球范围内有很多公司成功的使用了Kafka 0.8,它在当前系统中是个极大的改善。Kafka 0.8提供了可靠的持久化存储。 Mirror Maker项目 提供各数据中心的镜像, Camus项目 用来导出Avro格式的事件到HDFS的小时桶。

(点击放大图像)

《Spotify的入云之旅》系列之二

图2 使用Kafka 0.8作为持久化的事件传输系统设计

为了测试Kafka 0.8是否与预期一样工作,Spotify发布了测试系统,如图2。在Event Delivery Service嵌入简单的Kafka Producer是非常容易的。为了确保事件传输系统能够正确的端对端传输,从Event Delivery Service到HDFS,我们在持续集成和传输中嵌入各种测试。

遗憾的是,这种设计的系统启动不久就出现生产者阻塞,唯一稳定的组件是Camus(由于此次测试并没有push大量的数据,所以并不能压测出Camus的性能如何)。

Mirror Maker让人头疼,刚开始假设它会稳定的镜像不同数据中心的数据,但是实际情况并非如此。如果目的端集群出现状况,Mirror Maker会丢失数据但却向源集群报告数据已成功镜像(这个Bug在Kafka 0.9中修复了)。Mirror Maker偶尔会出现“脑裂”,这是数据中心见的镜像过程将停止。

Kafka Producer也会出现严重的稳定性问题。如果同一个集群的一个或者多个broker被移除或者重启,它将进入一种不能恢复的状态。当出现这种情况时,Kafka Producer不能生产任何事件,唯一的解决方案是重启整个服务。以上的问题没有解决,我们将有许多工作要做才能进行上线,定义Kafka Broker和Mirror Maker的发布策略,对所有系统组件都要做容量模型和计划,并要对性能指标进行监控。

Spotify进入一个十字路口,我们需要投入巨大的投资和修复Kafka?还是再试试其它的?

Google云发布/订阅

当我们在Kafka上进行徘徊的时候,其它Spotify团队开始实验Google云产品。他们发现一个有趣的产品 Google云发布/订阅 ,它似乎可以满足我们的基本需求:可靠的持久化队列,能保存未消费的数据长达7天,提供应用级别的可靠性,和至少消费一次(at-least-once)的语义。

在满足基本需求外,Google云发布/订阅带来了额外的惊喜:

  • 全球化可用性:作为一个全球化的服务,Google云发布/订阅能在 Google云适用的所有地区 使用;
  • 简单化的REST风格的API:如果不喜欢Google提供的客户端库,你可以自己开发;
  • 处理操作是Google提供:无需你关心容量、发布策略或者监控和警报等。

基于Apache Kafka的方案虽不是完美,但也凑合。并且有了之前的经验理论上讲也可以解决所有出现的问题。迁移一个服务意味着我们不得不去相信其它组织的操作,Google云发布/订阅是作为一个Beta版推广的,除了Google本身没有其它公司使用。

考虑到这些,我们需要对Google云发布/订阅进行压测,看下是否满足所有的要求。

Producer载荷压测

首先提上日程的是Google云发布/订阅能否处理预期的负载。当前负载峰值大约700k 事件/每秒,为了考虑今后的增长和可能出现的灾难性崩溃后的恢复,我们设定压测负载值为2M 事件/每秒。我们从每个数据中心发布2M 事件/每秒的事件,所有的请求会打到同一区域的Google云发布/订阅机器。我们假设Google云服务区域是独立的,每个区域可以处理等量的数据,理论上,如果我们能push 2M的信息到单个区域,那总共可以发布number_of_zones * 2M信息。我们希望在服务不降级到情况下,Google云发布/订阅能够在生产者端和消费者端都能长时间处理这种负载。

测试初期遇到一个问题:Google云发布/订阅Java客户端不能很好的工作。后来Spotify开发了 自己的库 ,为了更好的利用资源,采用Java异步。在开发新的客户端库同时,我们已经开始进行高负载压测了。数据经过路由按7:3的比例分发给两个Google发布/订阅topic。为了达到2M 事件/每秒的负载,我们用29台机器来跑Event Seervice。

(点击放大图像)

《Spotify的入云之旅》系列之二

图3 所有数据中心每秒发送到Google发布/订阅组件到成功请求数

(点击放大图像)

《Spotify的入云之旅》系列之二

图4 所有数据中心每秒发送到Google发布/订阅组件到失败请求数

(点击放大图像)

《Spotify的入云之旅》系列之二

图5 Event Service机器网络进出量

Google发布/订阅组件通过压测,我们在没有任何服务降级的情况下发布2M事件,并且Google发布/订阅后台几乎未收到服务器错误。

(点击放大图像)

《Spotify的入云之旅》系列之二

图6 Google云可视化监控所有的发布到Google发布/订阅组件的消息

(点击放大图像)

《Spotify的入云之旅》系列之二

图7 Google云可视化监控每个topic发布到Google发布/订阅组件的消息

Consumer稳定性测试

第二个测试关注点在消费端。我们进行了5天的高负载端对端系统延迟测试,测试期间发布平均 800k 事件/每秒。为了模拟真实情况下的负载变化,发布速率随着一天的时间变化。为了验证并发使用多topic,将所有的数据按7:3的比例发布。

Google发布/订阅组件需要在消息被持久化前进行订阅:不订阅,数据不保存。所有的订阅独立存储数据,并且一个订阅不限制消费者个数。Consumer在服务器端调度,所有服务器公平分配所有的请求数据。

(点击放大图像)

《Spotify的入云之旅》系列之二

图8 消费者测试

在本次测试中,创建了一个订阅,一个小时后进行消费数据。在测试期间中等延迟——包括日志恢复,大概有20秒,并且没有发现任何日志丢失。

最后的决定

基于以上的测试,我们决定使用Google发布/订阅组件,其有低延迟和一致性,唯一的缺点是容量限制。简而言之,使用Google发布/订阅组件比Kafka 0.8更适合新的事件传输系统。

(点击放大图像)

《Spotify的入云之旅》系列之二

图9 采用Google发布/订阅组件后的事件传输系统设计

下一步

事件在Google发布/订阅组件中安全地持久化后,接下来是导入到HDFS。接下来会讲解Google的另外一个服务Dataflow。

感谢杜小芳对本文的审校。

给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ,@丁晓昀),微信(微信号: InfoQChina )关注我们。

原文  http://www.infoq.com/cn/articles/spotify-cloud-part02
正文到此结束
Loading...