Storm 系列(一)基本概念
Apache Storm(http://storm.apache.org/)是由 Twitter 开源的分布式实时计算系统。 Storm 可以非常容易并且可靠地处理无限的数据流。对比 Hadoop 的批处理, Storm 是一个实时的、分布式的、具备高容错的计算系统。
Storm 的使用场景非常广泛,比如实时分析、在线机器学习、分布式 RPC、ETL 等。Storm 非常高效,在一个多节点集群上每秒钟可以轻松处理上百万条的消息。 Storm 还具有良好的可扩展性和容错性以及保证数据可以至少被处理一次等特性。
图 1-1 中水龙头和后面水管组成的拓扑图就是一个 Storm 应用(Topology),其中的水龙头是 Spout,用来源源不断地读取消息并发送出去,水管的每一个转接口就是一个 Bolt,通过 Stream 分组的策略转发消息流。
一、 Storm 的基本组件
1.1 集群组成
Storm 的集群表面上看和 Hadoop 的集群非常像。但是在 Hadoop 上运行的的是 MapReduce 的作业(job),而在 Storm 上运行的是 Topology。 Storm 和 Hadoop 一个非常关键的区别是 Hadoop 的 Mapreduce 作业最终会结束,而 Storm 的 Topology 会一直运行(除非显式地杀掉它)。
在 Storm 的集群中有两种节点:主节点(Master Node) Nimbus 和工作节点(Worker Node) Supervisor:
Nimbus 的作用类似于 Hadoop 中的 Jobtracker, Nimbus 负责在集群中分发代码,分配工作给机器,并且监控状态。每个工作节点上运行一个 Supervisor 进程(类似于 TaskTracker)。
Supervisor 会监听 Nimbus 分配给那台机器的工作,根据需要启动/关闭具体的 Worker 进程。每个 Worker 进程执行一个具体的 Topology, Worker 进程中的执行线程称为 Executor,可以有一个或者多个。每个 Executor 中又可以包含一个或者多个 Task。Task 为 Storm 中最小的处理单元。一个运行的 Topology 由运行在一台或者多台工作节点上的 Worker 进程来完成具体的业务执行。
Storm 组件和 Hadoop 组件的对比参见表 1-1。
Nimbus 和 Supervisor 之间的通信依靠 Zookeeper 完成,并且 Nimbus 进程和 Supervisor 都是快速失败(fail-fast)和无状态的,所有的状态要么在 Zookeeper 里面,要么在本地磁盘上。这也就意味着你可以用 kill -9 来杀死 Nimbus 和 Supervisor 进程,然后再重启它们,它们可以继续工作,就好像什么都没有发生过似的。这个设计使得 Storm 具有非常高的稳定性。 Storm 的基本体系架构参见图1-2。
1.2 核心技术
Storm 框架的核心由 7 个部分组成,如图 1.3 所示,它们同时也是 Storm 的基本组成部分
(1) Topology(拓扑)
一个拓扑是一个图的计算。用户在一个拓扑的每个节点包含处理逻辑,节点之间的链接显示数据应该如何在节点之间传递。
(2) Strean(流)
流是 Storm 的核心抽象。一个流是一个* Tuple 序列, Tuple 可以包含整形、长整形、短整形、字节、字符、双精度数、浮点数、布尔值和字节数组。用户可以通过定义序列化器在本机 Tuple 使用自定义类型
(3) Spout(龙卷)
Spout 是 Topology 流的来源。一般 Spout 从外部来源读取 Tuple,提交到 Topology(如 Kestrel 队列或 Twitter API)。 Spout 可分为可靠的和不可靠的两种模式。 Spout 可以发出超过一个流。
(4) Bolt(闪电)
Topology 中的所有处理都在 Bolt 中完成成。Bolt 可以完成过滤、业务处理、连接运算、连接、访问数据库等业务。Bolt 可以做简单的流的转换,发出超过一个流,主要方法是 execute 方法。完全可以在 Bolt 中启动新的线程做异步处理。
(5) Stream grouping(流分组)
流分组用于在 Bolt 的任务中定义流应该如何分区。 Storm 有 8 个内置的流分组接口:随机分组(Shuffle grouping)、字段分组(Fields grouping)、部分关键字分组(Partial key grouping)、全部分组(All grouping)、全局分组(Global grouping)、无分组(None grouping)、直接分组(Direct grouping)、本地或者随机分组(Local or shuffle grouping)
(6) Task(任务)
每个 Spout 或者 Bolt 在集群执行许多任务。每个任务对应一个线程的执行,流分组定义如何从一个任务集到另一个任务集发送 Tuple。可通过 TopologyBuilder 类的 setSpout() 和 setBolt() 方法来设置每个 Spout 或者 Bolt 的并行度。
(7) Worker(工作进程)
Topology 跨一个或多个 Worker 节点的进程执行。每个 Worker 节点的进程是一个物理的 JVM 和 Topology 执行所有任务的一个子集。
二、 Storm 的优势
总结起来, Storm 具有如下优点。
(1) 集成多种技术
Storm 集成了一些消息队列系统和数据库系统, Storm 的 Spout 抽象使得它很容易集成些新的消息队列系统。消息队列集成主要有:
- Kestrel
- Rabbitmo/AMOP
- Kafka
- JMS
同样, Storm 也可以很容易地和数据库系统集成。简单打开一个数据库连接,就可以像平常一样进行读写, Storm 会自动完成并行化、分区、在失败时尝试连接等操作。
(2) 简单的 API
Storm 有简单且易于使用的 API。当使用 Storm 编程的时候,用户可以使用相应的 API 来操纵和变换 Tuple 的流。一个 Tuple 是一个命名的值列表。 Tuple 可以包含任何类型的对象,如果想使用一个 Storm 不知道的类型,可以通过序列化注册该类型,然后在程序中进行应用。
Storm 只有三个抽象类型: Spout、 Bolt 和 Topology。 Spout 是计算流的来源。通常在系统中 Spout 从 Kestrel、 RabbitMQ 和 Kafka 等消息队列进行读取,但 Spout 还可以生成自己的流或者从 Twitter 流的 API 的某个地方读取。 Spout 实现了现有的大多数队列系统。
Bolt 处理任意数量的输入流,并且产生任意数量的新的输出流。大多数的逻辑计算进入 Bolt,如功能、过滤、流连接与数据库交互等。
Topology 是一个由很多 Spout 和 Bolt 组成的网络,网络上的每条边代表了一个 Bolt 订阅的数据流,这些数据流包括从 Spout 或从 Bolt 输出的数据流。一个 Topology 实际上就是一个任意复杂的多级流计算过程。当 Topology 在服务器上部署完之后,它就会一直运行下去,直到用户禁止相应的进程。
Storm 有一个“本地模式”,用户可以在进程里面模拟一个 Storm 集群,然后进行类似实际集群上的开发工作。这种模式对于开发和测试十分有用。当用户准备好在一个真正的集群上提交 Topology 执行的时候,可以使用 Storm 命令行方便地从客户端提交一个 Topology 到集群。
(3) 可扩展的
Storm 的 Topology 是并行计算的,它运行在一个集群主机上面。可以对 Topology 的不同部分单独调整它们的并行扩展。 Storm 命令行客户端的 rebalance 命令可以调整并行运行的 Topology。
Storm 内在的并行度意味着它能以低延迟速度来处理高吞吐量的消息。根据 Storm 官方网站的资料介绍, Storm 的一个节点(Intel E5645@2.4Ghz 的 CPU,24GB 的内存)在 1 秒钟能够处理 100 万个 100 字节的消息。
(4) 容错的
Storm 是容错的。当 Worker 死亡, Storm 会自动重新启动它们。如果一个节点死亡, Worker 将在另一个节点上重新启动。
Storm 的守护进程 Nimbus 和 Supervisor 被设计为无状态和快速失败的,所以如果它们死亡,它们会重启,就像什么都没发生过。这意味着可以使用 kill -9 命令来强制杀死 Storm 守护进程而不影响集群或者 Topology 的健康。
(5) 保证数据处理
Storm 保证每一个 Tuple 都能被完全处理。 Storm 的核心机制之一是能够通过一种非常有效的 Topology 方式来跟踪 Tuple。
Storm 保证每个消息至少能得到一次完整处理。任务失败时,它会负责从消息源重试消息。
使用 Trident(一种在 Storm 的基本抽象上更高层次的抽象),用户可以实现一次且仅一次处理的语义。
(6) 可以使用任何语言
Storm 可与任何编程语言一起使用。 Storm 的核心是一个定义和提交 Topology 的 Thrift 定义。因为 Thrift 可以用于任何语言,所以 Topology 可以用任何语言进行定义并提交。
(7) 部暑和操作简单
Storm 集群是易于部署的,仅需要少量的安装和配置就可以运行, Storm 的“开箱即用”配置十分适合生产环境。
如果用户在 EC2 环境上开展业务,通过 storm-deploy 项目提供的简单方式就可以完成准备、配置和安装一个 Storm 集群的工作一一用户仅仅需要点击一个按钮。
此外, Storm 部署之后也很容易操作。现在 Storm 被设计得极为健壮,使用 Storm 的集群会日复一日持续地稳定运行。
(8) *开源
三、Storm 应用现状
3.1 应用方向
目前 Storm 主要应用在以下 3 个方面。
(1) 流处理(Stream Processing)
Storm 最最基本的用例是“流处理”。 Storm 可以用来处理源源不断流进来的消息,处理之后将结果写入到某个存储中去。
(2) 连续计算(Continuous Computation)
Storm 的另一个典型用例是“连续计算”。 Storm 能保证计算可以永远运行,直到用户结束计算进程为止。
(3)分布式RPC(Distributed RPC)
Storm 的第三个典型用例是“分布式RPC”,由于 Storm 的处理组件是分布式的,而且处理延迟极低,所以可以作为通用的分布式 RPC 框架来使用。当然,其实搜索引擎本身也是个分布式 RPC 系统。
3.2 Strom 相关项目
(1) storm-website 项目
storm-website 项目的网址为:https://github.com/nathanmarz/storm-website
这是 https://www.storm-project.net/ 网站的源代码,使用 Jekyll(https://github.com/mojombo/jekyll)编写。
(2) storm-starter 项目
storm-starter 项目的网址为:https://github.com/nathanmarz/storm-starter
storm-starter 项目包含了大量使用 Storm 的例子。
如果读者是第一次接触 Storm,建议首先了解以下 3 个主要的 Storm 的 Topology。
- Exclamation Topology:全由Java编写的基本 Topology
- Wordcount Topology:使用 Python实现Bolt的使用 multilane的基本 Topology
- Reach Topology:在 Storm上面的复杂的DRPC例子
(3) storm-deploy 项目
storm-deploy 项目的网址为:https://github.com/nathanmarz/storm-deploy
如果读者在 AWS 上使用 Storm,那么可以考虑使用 storm-deploy 项目。 storm-deploy 项目使得我们能够非常简单地在 AWS 上部署 Storm 集群。 storm-deploy 在 EC2 上完全自动化地供给、配置和安装 Storm 集群,它还为你设置 Ganglia,你可以使用 Ganglia 监视 CPU、磁盘和网络。
(4) storm-contrib 项目
storm-contrib 项目的网址为:https://github.com/nathanmarz/storm-contrib
storm-contrib 是一个使用 Storm 模块的社区库,其中包含了大量的集成了 Redis、 Kafka、Mongodb等其他系统的 Spout/Bolt,以及 Storm 开发者遇到的常见任务的代码。
一些 storm-contrib 模块是 git 子模块(链接到外部的 github 库)。这允许 storm-contrib 子项日可以被外部维护(所以那些项目可以保持独立的分支和标签),但也包含在 storm-contrib 项目中,以便增加社区可见度
storm-contrib 包括:
- Spouts: Spouts 集成 JMS、 Kafka、 Redis pub/sub等消息队列系统。
- storm-state: storm-state 使得用户在其计算过程中能以一种可靠的方式来很容易地管理大量的内存状态一一通过持久地使用一个分布式文件系统
- 数据库集成:有许多 Bolt 帮助集成各种数据库,如 Mongodb、关系数据库、 Cassandra 等
- 其他繁杂的公用组件。
(5) storm-mesos 项目
storm-mesos 项目在 Mesos 集群资源管理器上运行 Storm。 Storm 与 Mesos 集群资源管理器整合在一起,这个项目已用于 Twitter 产品。
用户可以像将 Topology 提交给正常的 Storm 集群的方式来将 Topology 提交给 Storm/Mesos。
Storm/Mesos 提供了在 Topology 之间进行隔离的技术通过这种技术,用户无须为 Topology 之间可能的干扰而担心。
(6) storm-yarn 项目
sorm-yarm 项目的网址为:https://github.com/yahoo/storm-yarn
storm-yarn 是 Yahoo! 公司的开源项目,使 Storn 集群可以被部署到 Hadoop YARN 管理的主机上,这仍然是进行中的工作
四、其他流式处理框架
4.1 阿里巴巴团队的 JStorm
JStorm(https://github.com/alibaba/jstorm)是阿里巴巴团队基于 Storm 二次开发的, Spout/Bolt 等接口的使用方式和 Storm 保持完全一致,在 Storm 上开发和运行的代码可以行不修改就运行在 JStorm 上。 Storm 的内核是 Clojure 编写, JStorm 完全用 Java 重写。 JStorm 还提供了一些 Storm 没有的特性。
- Nimbus 实现HA :当一台 Nimbus 宕机,自动热切到备份 Nimbus。
- 任务之间影响小 :新上线的任务不会冲击老的任务。采用 CGroups 对资源进行硬隔离,保证程序之间 CPU 不发生抢占。
- 解决 Disruptor 急剧消耗 CPU 问题 :当原生 Disruptor 队列慢时,生产方会不断轮询检食 Disruptor 队列是否有空的 Slot,极大消耗队列。
- 调度更强大,彻底解决了 Storm 任务分配不均衡问题 。从 CPU、内存、磁盘、网络 4 个维度进行任务分配。
- Classloader 隔离 :解决应用的类和 Storm 的类发生冲突的问题。将应用的类放置在自己的类空间中。
- 监控更强大 :Web UI 上展示更多的监控。Task 级别,每一个模块消耗时间和队列长度; Worker 级别,每一个模块消耗时间、队列长度、 CPU/Memory 使用用以及网络时延;还包括用户自定义监控数据。
- JStorm 完全兼容 Storm :JStorm 上的应用能够在一行代码都不需要改动的情况下运行在 Storm 平台上,结合 JStorm 的其他特性,这将给 Storm 带来更广阔的使用选择。
JStorm 的开发和更新速度非常快,用户活跃度也很高。更多详细信息可以参考 Github 的介绍。
4.2 Apache S4
Apache S4(http://incubator.apache.org/s4/)是由 Yahoo 开源的多用途、分布式的、可伸缩的、容错的、可插入式的的实时数据流计算平台。
S4 填补了复杂的专有系统和面向批处理的井源计算平台之间的差距。其目标是开发个高性能计算平台,对应用程序开发者隐藏并行处理系统固有的复杂性。S4 已经在 Yahoo! 系统中大规模使用,目前最新版本是 0.6.0。
S4 相对于 Storm 在可靠性相容错性上差一些,S4 不保证完全不去失数据。在用户活跃度上 S4 也要差一些。
4.3 Spark Streaming
Spark 是 UC Berkeley AMP Lab 开源的类 Hadoop MapReduce 的通用的并行计算框架。 Spark 基于 MapReduce 算法实现的分布式计算拥有 Hadoop MapReduce 所具有的优点,但不同于 MapReduce 的是,作业中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。
Spark Streaming 是建立在 Spark 上的实时计算框架,通过它提供的 API 和基于内存的高速执行引擎,用户可以结合流式、批处理和交互式进行查询和实时计算。 Spark Streaming 的基本的原理是将 Stream 数据分成小的时间片断(几秒钟到几分钟),以类似 batch 批量处理的方式来处理这些小部分数据。 Spark Streaming 构建在 Spark 上,一方面是因为 Spark 的低延迟执行引擎可以用于实时计算,另一方面相比基于 Record 的其他处理框架(如 Storm),弹性分布式数据集(Resilient Distributed Datasets,RDD)更容易实现高效的容错处理。此外,小批量处理的方式使得它可以同时兼容批量和实时数据处理的逻辑和算法,方便了一些需要历史数据和实时数据联合分析的特定应用场合。
Spark Streaming 和 Storm 两个框架都提供了可扩展性和容错性,它们根本的区别在于它们的处理模型。 Storm 处理的是每次传入的一个事件,而 Spark Streaming 是处理某个时间段窗口内的事件流。因此, Storm 处理一个事件可以达到极低的延迟,而 Spark Streaming 的延迟相对较高。
每天用心记录一点点。内容也许不重要,但习惯很重要!
本文来自 《Strom 技术内幕与大数据实践》 一书。