Skip to content
This repository has been archived by the owner on Jun 16, 2023. It is now read-only.

JStorm basics in 5 min

Cody edited this page Mar 7, 2016 · 1 revision

本文主要讲一下JStorm的基本概念,让你在5分钟内对JStorm有一个大体的了解。

基本概念

首先,JStorm有点类似于Hadoop的MR(Map-Reduce),但是区别在于,hadoop的MR,提交到hadoop的MR job,执行完就结束了,进程就退出了,而一个JStorm任务(JStorm中称为topology),是7*24小时永远在运行的,除非用户主动kill。

JStorm组件

接下来是一张比较经典的Storm的大致的结构图(跟JStorm一样):

twitter_storm_topology

图中的水龙头(好吧,有点俗)就被称作spout,闪电被称作bolt。

在JStorm的topology中,有两种组件:spoutbolt

spout

spout代表输入的数据源,这个数据源可以是任意的,比如说kafaka,DB,HBase,甚至是HDFS等,JStorm从这个数据源中不断地读取数据,然后发送到下游的bolt中进行处理。

bolt

bolt代表处理逻辑,bolt收到消息之后,对消息做处理(即执行用户的业务逻辑),处理完以后,既可以将处理后的消息继续发送到下游的bolt,这样会形成一个处理流水线(pipeline,不过更精确的应该是个有向图);也可以直接结束。

通常一个流水线的最后一个bolt,会做一些数据的存储工作,比如将实时计算出来的数据写入DB、HBase等,以供前台业务进行查询和展现。

组件的接口

JStorm框架对spout组件定义了一个接口:nextTuple,顾名思义,就是获取下一条消息。执行时,可以理解成JStorm框架会不停地调这个接口,以从数据源拉取数据并往bolt发送数据。

同时,bolt组件定义了一个接口:execute,这个接口就是用户用来处理业务逻辑的地方。

每一个topology,既可以有多个spout,代表同时从多个数据源接收消息,也可以多个bolt,来执行不同的业务逻辑。

调度和执行

接下来就是topology的调度和执行原理,对一个topology,JStorm最终会调度成一个或多个worker,每个worker即为一个真正的操作系统执行进程,分布到一个集群的一台或者多台机器上并行执行。

而每个worker中,又可以有多个task,分别代表一个执行线程。每个task就是上面提到的组件(component)的实现,要么是spout要么是bolt。

用户在提交一个topology的时候,会指定以下的一些执行参数:

总worker数

即总的进程数。举例来说,我提交一个topology,指定worker数为3,那么最后可能会有3个进程在执行。之所以是可能,是因为根据配置,JStorm有可能会添加内部的组件,如__acker或者__topology_master(这两个组件都是特殊的bolt),这样会导致最终执行的进程数大于用户指定的进程数。我们默认是如果用户设置的worker数小于10个,那么__topology_master 只是作为一个task存在,不独占worker;如果用户设置的worker数量大于等于10个,那么__topology_master作为一个task将独占一个worker

每个component的并行度

上面提到每个topology都可以包含多个spout和bolt,而每个spout和bolt都可以单独指定一个并行度(parallelism),代表同时有多少个线程(task)来执行这个spout或bolt。

JStorm中,每一个执行线程都有一个task id,它从1开始递增,每一个component中的task id是连续的。

还是上面这个topology,它包含一个spout和一个bolt,spout的并行度为5,bolt并行度为10。那么我们最终会有15个线程来执行:5个spout执行线程,10个bolt执行线程。

这时spout的task id可能是1~5,bolt的task id可能是6~15,之所以是可能,是因为JStorm在调度的时候,并不保证task id一定是从spout开始,然后到bolt的。但是同一个component中的task id一定是连续的。

每个component之间的关系

即用户需要去指定一个特定的spout发出的数据应该由哪些bolt来处理,或者说一个中间的bolt,它发出的数据应该被下游哪些bolt处理。

还是以上面的topology为例,它们会分布在3个进程中。JStorm使用了一种均匀的调度算法,因此在执行的时候,你会看到,每个进程分别都各有5个线程在执行。当然,由于spout是5个线程,不能均匀地分配到3个进程中,会出现一个进程只有1个spout线程的情况;同样地,也会出现一个进程中有4个bolt线程的情况。

在一个topology的运行过程中,如果一个进程(worker)挂掉了,JStorm检测到之后,会不断尝试重启这个进程,这就是7*24小时不间断执行的概念。

消息的通信

上面提到,spout的消息会发送给特定的bolt,bolt也可以发送给其他的bolt,那这之间是如何通信的呢?

首先,从spout发送消息的时候,JStorm会计算出消息要发送的目标task id列表,然后看目标task id是在本进程中,还是其他进程中,如果是本进程中,那么就可以直接走进程内部通信(如直接将这个消息放入本进程中目标task的执行队列中);如果是跨进程,那么JStorm会使用netty来将消息发送到目标task中。

实时计算结果输出

JStorm是7*24小时运行的,外部系统如果需要查询某个特定时间点的处理结果,并不会直接请求JStorm(当然,DRPC可以支持这种需求,但是性能并不是太好)。一般来说,在JStorm的spout或bolt中,都会有一个定时往外部存储写计算结果的逻辑,这样数据可以按照业务需求被实时或者近实时地存储起来,然后直接查询外部存储中的计算结果即可。

Clone this wiki locally