Storm的进程、线程、任务数和线程安全问题研究(一篇明白)
基于Storm
1.0.6
版本
本文查阅了许多资料并反复琢磨,应该能做到一篇明白Storm的worker进程、线程、任务关系
一、概念
-
进程:即worker进程,工作进程,Java进程,或称JVM进程
-
线程:即executor,由进程产生,用于执行任务
-
任务:即task,任务就是被线程执行的东西,数据会流过task,线程作用于task将数据处理,可以理解task就是数据的处理工具,或者是数据的处理逻辑的工具
-
进程数:即worker数
-
线程数:即executor数
-
任务数:即task数
-
component:
spout
和bolt
的统称,后续也会用bolt的prepare/execute方法统称spout的open/nextTuple方法
worker进程可以比喻为工厂
,executor线程可以比喻为工人
,task任务可以比喻为车床
工厂里有很多工人,每个工人操作一到多台车床,车床有原料流过,原料从车床处理完毕流到下一个车床。
进程、线程是比较好理解的,任务(task)就比较难理解,什么是task,task应该是数据的处理逻辑的集合,线程只负责执行,至于怎么执行,是task规定的,而task怎么知道如何处理数据,它应该是委托给Bolt/Spount的,这就是我们书写的Bolt/Spount里头的处理逻辑,而task其实就是包装了bolt/spout实例,线程执行了task的run方法,run方法里转而调用execute/nextTuple方法
三者关系
以下知识点细节都是正确的 (目前的知识认为是对的)
- bolt/spout 实例数一定等于task数
- 每个task都有自己的 bolt 或 spout 的实例,所以 task数等于 bolt/spout 实例数
- 线程数 <= task数,一个线程执行一到多个task
- component 中的成员变量在 prepare/execute(open/nextTuple) 方法中被操作,是线程安全的
- component 中的静态变量在 prepare/execute(open/nextTuple) 方法中被操作,是非线程安全的
- 相同 worker 可能存在类型相同的多个实例 (相同的Class,有多个实例)
- 可能出现一个线程服务于多个task的情况
- 一个executor总会有一个线程来运行executor所有的task,这说明task在executor内部是串行执行的。(An executor always has one thread that it uses for all of its tasks, which means that tasks run serially on an executor.)
- 一个线程服务于多个task,而不是多个线程操作同一个task,因此component的成员变量不存在资源竞争
- 因为component中的静态变量是类共享的,而同一个worker里存在相同类型