Storm的并发
1个worker进程执行的是1个topology的子集(注:不会出现1个worker为多个topology服务)。1个worker进程会启动1个或多个executor线程来执行1个topology的(spout或bolt)。因此,1个运行中的topology就是由集群中多台(可能是一台)物理机上的一个或者多个worker进程组成的。
executor是worker进程启动的一个单独线程。每个executor只会运行1个topology的1个或者多个(spout或bolt)task(注:task可以是1个或多个,Storm默认是1个(spout或bolt)只生成1个task,executor线程会在每次循环里顺序调用所有task实例)。
task是最终运行spout或bolt中代码的执行单元(注:1个task即为spout或bolt的1个实例,executor线程在执行期间会调用该task的nextTuple或execute方法)。topology启动后,1个(spout或bolt)的task数目是固定不变的,但该(spout或bolt)使用的executor线程数可以动态调整(例如:1个executor线程可以执行该(spout或bolt)的1个或多个task实例)。这意味着,对于1个(spout或bolt)存在这样的条件:#threads<=#tasks(即:线程数小于等于task数目)。默认情况下task的数目等于executor线程数目,即1个executor线程只运行1个task。
默认情况下,一个supervisor节点最多可以启动4个worker进程,每一个topology默认占用一个worker进程,每个spout或者bolt会占用1个executor,每个executor启动1个task。
worker(slot)
默认一个从节点上面可以启动4个worker进程,参数是supervisor.slots.ports。在Storm配置文件中已经配置过了,默认是在strom-core.jar包中的defaults.yaml中配置的有。
默认一个topology只使用一个worker进程,可以通过代码来设置使用多个worker进程。
通过config.setNumWorkers(workers)设置。
通过conf.setNumAckers(0);可以取消acker任务(点击topology页面最下面的show system stats,可以显示系统级别的bolt,可以验证acker线程的存在)。
最好一台机器上的一个topology只使用一个worker,主要原因是减少了worker之间的数据传输。
如果worker使用完的话再提交topology就不会执行,会处于等待状态。
注意:worker之间通信是通过Netty 进行通信的。
executor
默认情况下一个executor运行一个task,可以通过在代码中设置。
builder.setSpout(id, spout,parallelism_hint);
builder.setBolt(id, bolt, parallelism_hint);
task
通过boltDeclarer.setNumTasks(num);来设置实例的个数。
executor的数量会小于等于task的数量(为了rebalance)。
在Storm 0.8.2中引入了隔离调度器,让多个拓扑很容易且安全地共享一个集群,例如,它解决了多租户的问题--避免多个拓扑之间的资源竞争--通过提供拓扑间的完全隔离
当使用隔离调度器的时候Nathan[Storm作者]建议你把worker数量设置成机器数量的倍数。把executor数量设置成worker数量的倍数。如果你会调用setNumTasks()(多数人不会),应该设置成executor数量的倍数。这样做了之后,你的拓扑的负载就会均匀分布。每台机器和每个Java虚拟机进程会有相同数量的线程和大致等量的负载。
Storm一个灵巧的功能是可以增减worker进程或者executor的数量而不需要重启集群或者拓扑。这种做法叫做rebalancing。
有两种方法可以用来做拓扑的rebalance:
①使用Storm web UI来做
②使用命令行工具Storm rebalance