Storm-源码分析- Component ,Executor ,Task之间关系
Component包含Executor(threads)的个数
在StormBase中的num-executors, 这对应于你写topology代码时, 为每个component指定的并发数(通过setBolt和setSpout)
Component和Task的对应关系, (storm-task-info)
默认你可以不指定task数, 那么task和executor为1:1关系
当然也可以通过ComponentConfigurationDeclarer#setNumTasks()去设置TOPOLOGY_TASKS
这个函数, 首先读出所有components
对每个component, 读出ComponentComm中的json_conf, 然后从里面读出上面设置的TOPOLOGY_TASKS
最后用递增序列产生taskid, 并最终生成component和task的对应关系
如果不设置, task数等于executor数, 后面分配就很容易, 否则就涉及task分配问题
(defn storm-task-info
"Returns map from task -> component id"
[^StormTopology user-topology storm-conf]
(->> (system-topology! storm-conf user-topology)
all-components
(map-val (comp #(get % TOPOLOGY-TASKS) component-conf))
(sort-by first)
(mapcat (fn [[c num-tasks]] (repeat num-tasks c)))
(map (fn [id comp] [id comp]) (iterate (comp int inc) (int 1)))
(into {})
))
首先产生system-topology!, 因为system-topology!会增加系统components, acker, systemBolt, metricsBlot, 这些也都是topology中不可缺少的部分, 所以单纯使用用户定义的topology是不够的
然后取出topology里面所有component
(defn all-components [^StormTopology topology]
(apply merge {}
(for [f thrift/STORM-TOPOLOGY-FIELDS]
(.getFieldValue topology f)
)))
使用thrift/STORM-TOPOLOGY-FIELDS从StormTopology的metadata里面读出每个fieldid, 并取出value进行merge
所以结果就是下面3个map, merge在一起的集合
struct StormTopology {
//ids must be unique across maps
// #workers to use is in conf
1: required map<string, SpoutSpec> spouts;
2: required map<string, Bolt> bolts;
3: required map<string, StateSpoutSpec> state_spouts;
}
使用map-value对map中的component进行如下操作
取出component里面的ComponentComm对象(.getcommon), 并读出json_conf, 最终读出conf中TOPOLOGY-TASKS
(defn component-conf [component]
(->> component
.get_common
.get_json_conf
from-json))
struct ComponentCommon {
1: required map<GlobalStreamId, Grouping> inputs;
2: required map<string, StreamInfo> streams; //key is stream id
3: optional i32 parallelism_hint; //how many threads across the cluster should be dedicated to this component
// component specific configuration
4: optional string json_conf;
}
输出{component-string:tasknum}, 按component-string排序, 再进行mapcat
{c1 3, c2 2, c3 1} –> (c1,c1,c1,c2,c2,c3)
再加上递增编号, into到map, {1 c1, 2 c1, 3 c1, 4 c2, 5 c2, 6 c3}
Topology中, Task和Executor的分配关系, (compute-executors)
上面已经产生, component->executors 和 component->task, 现在根据component对应的task和executor个数进行task分配(到executor)
默认是1:1分配, 但如果设置了task数,
比如对于c1, 2个executor, 3个tasks [1 2 3], 分配结果就是['(1 2) ‘(3)]
最终to-executor-id, 列出每个executor中task id的范围([(first task-ids) (last task-ids)])
(defn- compute-executors [nimbus storm-id]
(let [conf (:conf nimbus)
storm-base (.storm-base (:storm-cluster-state nimbus) storm-id nil)
component->executors (:component->executors storm-base) ;从storm-base中获取每个component配置的(executor)线程数
storm-conf (read-storm-conf conf storm-id)
topology (read-storm-topology conf storm-id)
task->component (storm-task-info topology storm-conf)]
(->> (storm-task-info topology storm-conf)
reverse-map ;{“c1” [1,2,3], “c2” [4,5], “c3” 6}
(map-val sort)
(join-maps component->executors) ; {"c1" ‘(2 [1 2 3]), "c2" ‘(2 [4 5]), "c3" ‘(1 6)}
(map-val (partial apply partition-fixed)) ; {"c1" ['(1 2) '(3)], "c2" ['(4) '(5)], "c3" ['(6)]}
(mapcat second) ;((1 2) (3) (4) (5) (6))
(map to-executor-id) ;([1 2] [3 3] [4 4] [5 5] [6 6])
)))
partition-fixed, 将aseq分成max-num-chunks份
思路,
7整除3, 2余1所以, 分成3份, 每份2个, 还余一个
把这个放到第一份里面,
所以, 有1份的2+1个, 有(3-1)份的2个
这里使用integer-divided(7 3), ([3 1] [2 2]) , 刚开始比较难理解, 其实函数名起的不好, 这里不光除, 已经做了划分
返回的结果的意思是, 1份3个, 2份2个接着就是使用split-at, loop划分
(defn partition-fixed
“(partition-fixed 3 '( 1 2 3 4 5 6 7)) [(1 2 3) (4 5) (6 7)]”
[max-num-chunks aseq]
(if (zero? max-num-chunks)
[]
(let [chunks (->> (integer-divided (count aseq) max-num-chunks)
(#(dissoc % 0))
(sort-by (comp - first))
(mapcat (fn [[size amt]] (repeat amt size)))
)]
(loop [result []
[chunk & rest-chunks] chunks
data aseq]
(if (nil? chunk)
result
(let [[c rest-data] (split-at chunk data)]
(recur (conj result c)
rest-chunks
rest-data)))))))
Topology中, Executor和component的关系, (compute-executor->component ), 根据(executor:task)关系和(task:component)关系join
(defn- compute-executor->component [nimbus storm-id]
(let [conf (:conf nimbus)
executors (compute-executors nimbus storm-id)
topology (read-storm-topology conf storm-id)
storm-conf (read-storm-conf conf storm-id)
task->component (storm-task-info topology storm-conf)
executor->component (into {} (for [executor executors
:let [start-task (first executor)
component (task->component start-task)]]
{executor component}))]
executor->component)) ;{[1 2] “c1”, [3 3] “c1”, [4 4] “c2”, [5 5] “c2”, [6 6] “c3”}
最终目的就是获得executor->component关系, 用于后面的assignment, 其中每个executor包含task范围[starttask, endtask]
Storm-源码分析- Component ,Executor ,Task之间关系的更多相关文章
- storm源码分析之任务分配--task assignment
在"storm源码分析之topology提交过程"一文最后,submitTopologyWithOpts函数调用了mk-assignments函数.该函数的主要功能就是进行topo ...
- Storm源码分析--Nimbus-data
nimbus-datastorm-core/backtype/storm/nimbus.clj (defn nimbus-data [conf inimbus] (let [forced-schedu ...
- JStorm与Storm源码分析(二)--任务分配,assignment
mk-assignments主要功能就是产生Executor与节点+端口的对应关系,将Executor分配到某个节点的某个端口上,以及进行相应的调度处理.代码注释如下: ;;参数nimbus为nimb ...
- JStorm与Storm源码分析(四)--均衡调度器,EvenScheduler
EvenScheduler同DefaultScheduler一样,同样实现了IScheduler接口, 由下面代码可以看出: (ns backtype.storm.scheduler.EvenSche ...
- JStorm与Storm源码分析(三)--Scheduler,调度器
Scheduler作为Storm的调度器,负责为Topology分配可用资源. Storm提供了IScheduler接口,用户可以通过实现该接口来自定义Scheduler. 其定义如下: public ...
- Spark源码分析之八:Task运行(二)
在<Spark源码分析之七:Task运行(一)>一文中,我们详细叙述了Task运行的整体流程,最终Task被传输到Executor上,启动一个对应的TaskRunner线程,并且在线程池中 ...
- Spark源码分析之七:Task运行(一)
在Task调度相关的两篇文章<Spark源码分析之五:Task调度(一)>与<Spark源码分析之六:Task调度(二)>中,我们大致了解了Task调度相关的主要逻辑,并且在T ...
- Spark源码分析之六:Task调度(二)
话说在<Spark源码分析之五:Task调度(一)>一文中,我们对Task调度分析到了DriverEndpoint的makeOffers()方法.这个方法针对接收到的ReviveOffer ...
- JStorm与Storm源码分析(一)--nimbus-data
Nimbus里定义了一些共享数据结构,比如nimbus-data. nimbus-data结构里定义了很多公用的数据,请看下面代码: (defn nimbus-data [conf inimbus] ...
随机推荐
- cocos2d-x的win32编译环境
1> 检查或配置VS 1.1>头文件 [c/c++]->附加包含目录 1.2>依赖库 [链接器]->[输入]->[附加依赖项] 2> 可能出现 ...
- NGINX + LUA实现复杂的控制
安装lua_nginx_module 模块 lua_nginx_module 可以一步步的安装,也可以直接用淘宝的OpenResty Centos和debian的安装就简单了.. 这里说下freebs ...
- ngBind {{}} ngBindTemplate
1.首先我们最常使用的一个绑定表达式的指令是ngBind,比如在一个div标签中我们可以这样使用: <div ng-bind="vm.info"></div> ...
- 中兴ZXV10 B860AV1.1 全TTL操作完美破解
本文转自:http://www.znds.com/tv-496624-1-1.html 1)前期准备工作 1.1 拆开盒子,TTL接线,这个论坛里有好多其它帖子,就不再详细描述. 1.2 复制需要安装 ...
- weblogic管理服务器密码相关
安全控制weblogic,我们可以为weblogic Administrator服务器设置密码 1.administrator服务器或受管服务器启动时,需要认证,方法有三种: (1)command启动 ...
- hdu1142(dj+记忆化搜索)
题意:给你n各点,m行关于这些点的联通关系,以及距离,求从1这个点到2这个点之间,下一个点到2这个点比当前点到2这个点的距离要小的路径的条数...... 思路:dj+记忆化搜索....... #inc ...
- 在echarts中自定义提示框内容
1.期望效果 以柱状图为例,在鼠标滑过每个数据标签时,为了更友好地显示数据内容,需要对显示的数据内容作格式化处理,添加自定义内容. 如下图,鼠标滑过每个数据项时, 第1张是默认提示框: 第2张是处理成 ...
- exchange邮箱系统增加验证码机制
首先背景是exchange的邮箱系统没有后台源代码.因为这个原因,生成验证码的机制放在aspx的runat="sever"后台代码里面. 首先需要找到iis中logon.aspx文 ...
- springboot日志管理+集成log4j
sprongboot使用的默认日志框架是Logback. 可以在application.properties配置简单日志属性,也可以单独配置logback.xml格式,还可以使用log4j来管理. 下 ...
- 将php和mysql命令加入到环境变量中
方法一:直接运行命令export PATH=$PATH:/usr/local/webserver/php/bin 和 export PATH=$PATH:/usr/local/webserver/my ...