Storm中Topology任务调度策略

来源:互联网 发布:别去淘宝搜白夜追凶 编辑:程序博客网 时间:2024/05/11 15:05
Storm中负责Topo分配的工作由nimbus负责,具体代码在nimbus.clj中。

对于一个新Topo的分配来说,主要经历两个阶段:

1. 逻辑分配阶段
这里又会涉及到两个概念executor和task,简单讲对于一个具体的component来说,task就是component在运行时的实例个数,即component使静态的class代码,task是运行时的具体object对象,task的个数即是component在runtime是被实例化的对象个数,
而executor可以理解为线程的概念,一个component对应的executor个数就是component运行时所独占的线程数,举例来讲,某个component的task个数是6,executor个数是2,则运行时component就有6个实例运行在2个线程中,一个线程负责执行3其中3个
task,默认情况下一般会将task个数配置为executor的个数,即每一个线程只负责执行一个component的实例化对象。
具体可以看官方的解释:https://github.com/nathanmarz/storm/wiki/Understanding-the-parallelism-of-a-Storm-topology
逻辑阶段所作的工作就是计算Topology中所有的component的executor个数,task个数,然后将所有的task分配到executor中。

2. 物理分配阶段
executor代表的是线程,具体要落地执行还需要依附于进程,因此物理分配阶段做的工作就是将所有的executor分配到worker slot进程中(一个slot代表一个jvm虚拟机)。
由于在逻辑分配阶段,task就是按照topo进行了排序,即相同component所属的task排列在一起,而在物理分配阶段slot资源也是按照端口进行了排序,即相同端口的slot排在了一起,
而具体分配算法是将排好序的task一次轮序分配到排好序的slot中,因此同一个component所属的不同task会尽可能的分到不同机器的相同端口上的slot中,实现了整个Topo的负载均衡,
这样分配的好处是防止同一个component的所有task都分配到同一台机器上,造成整个集群负载不均。

具体负责Topo分配的函数为
(declare mk-assignments)
具体代码就不展开了,其中核心计算逻辑对应的几个方法调用链为

1. compute-new-topology->executor->node+port

计算topology的每一个component对应的slots资源

2. compute-topology->executors 

计算topology中每一个component分配到的executor

3. compute-executors 

将task分配到executor中

4. storm-task-info 

计算taskId->componentId的对应关系

5. DefaultScheduler.-schedule 

将executor分配到slot中


最后要说明的一点是一个Component对应的Task个数是如何获取的。

在调用mk-assignments之前,还调用了一个叫做normalize-topology的函数,称为topo的规范化。规范化的主要工作就是设置component的Task个数,即component运行时的instance个数。

(defn normalize-topology [storm-conf ^StormTopology topology]  (let [ret (.deepCopy topology)]    (doseq [[_ component] (all-components ret)]      (.set_json_conf        (.get_common component)        (->> {TOPOLOGY-TASKS (component-parallelism storm-conf component)}             (merge (component-conf component))             to-json )))    ret ))
计算component对应task个数,这里起作用的参数有三个
1. TOPOLOGY-MAX-TASK-PARALLELIS
2. TOPOLOGY-TASKS
3. parallelism-hint (该component对应的executor个数)
具体算法为:
1. 如果设置了TOPOLOGY-MAX-TASK-PARALLELISM和TOPOLOGY-TASKS,则获取两者中较小者
2. 如果没有设置TOPOLOGY-TASKS,但是设置了TOPOLOGY-MAX-TASK-PARALLELISM和parallelism-hint,则获取两者中较小者
3. 如果没有设置TOPOLOGY-MAX-TASK-PARALLELISM,则取TOPOLOGY-TASKS,若两者都没有设置,则取parallelism-hint
简单可以总结为:可以为Task单独设值的参数为TOPOLOGY-MAX-TASK-PARALLELIS和TOPOLOGY-TASKS,并且以其中较小者为准,如果这两个参数均没有设置,则将task个数设置为parallelism-hint即该component的运行时并发executor的个数。

(defn- component-parallelism [storm-conf component]  (let [storm-conf (merge storm-conf (component-conf component))        num-tasks (or (storm-conf TOPOLOGY-TASKS) (num-start-executors component))        max-parallelism (storm-conf TOPOLOGY-MAX-TASK-PARALLELISM)        ]    (if max-parallelism      (min max-parallelism num-tasks)      num-tasks)))

0 1
原创粉丝点击