JStorm与Storm源码分析(二)--任务分配,assignment
mk-assignments主要功能就是产生Executor与节点+端口的对应关系,将Executor分配到某个节点的某个端口上,以及进行相应的调度处理。代码注释如下:
;;参数nimbus为nimbus-data对象,:scratch-topology-id为需要重新调度的Topology的id
(defnk mk-assignments [nimbus :scratch-topology-id nil]
(let [conf (:conf nimbus);;分别从nimbus-data中获取conf,storm-cluster-state和inimbus对象,并将其保存为临时变量
storm-cluster-state (:storm-cluster-state nimbus)
^INimbus inimbus (:inimbus nimbus)
;;从zk中读取所有活跃的Topologies,获取他们id的集合
topology-ids (.active-storms storm-cluster-state)
;;根据前面得到的Topology-id的集合,对每一个id调用read-topology-details方法
;;从参数nimbus-data中获取topology-details信息,并以<topology-id,topology-details>保存在集合中
topologies (into {} (for [tid topology-ids]
{tid (read-topology-details nimbus tid)}))
;;利用前面得到的<topology-id,topology-details>集合创建Topologies对象
topologies (Topologies. topologies)
;;读取所有已经分配资源的Topology的id的集合。
assigned-topology-ids (.assignments storm-cluster-state nil)
existing-assignments (into {} (for [tid assigned-topology-ids]
;; 对于那些已经分配资源但需要重新调度的Topology(由scratch-topology-id指定),
;; 我们忽略其之前的分配,故之前分配占用的所有slot将被视为空闲slot(空闲资源),可重新被调度使用。
(when (or (nil? scratch-topology-id) (not= tid scratch-topology-id))
{tid (.assignment-info storm-cluster-state tid nil)})))
;; 调用compute-new-topology->executor->node+port方法为所有Topologies计算新的调度,
;; 并返回topology->executor->node+port
topology->executor->node+port (compute-new-topology->executor->node+port
nimbus
existing-assignments
topologies
scratch-topology-id) ;;获取当前系统时间(秒)
now-secs (current-time-secs)
;;调用basic-supervisor-details-map方法获取ZooKeeper中所有的SupervisorInfo信息,
;;然后将其转换为<supervisor-id,SupervisorDetails>集合,具体操作看1
basic-supervisor-details-map (basic-supervisor-details-map storm-cluster-state) ;; 对topology->executor->node+port中各项进行处理,通过添加开始时间等构建最终的作业
;; 返回得到<topology-id Assignment>集合
new-assignments (into {} (for [[topology-id executor->node+port] topology->executor->node+port
;;根据topology-id获取Topology的任务分配情况
:let [existing-assignment (get existing-assignments topology-id)
;;从executor->node+port信息中提取所有的节点信息
all-nodes (->> executor->node+port vals (map first) set)
;;根据all-nodes获取每个节点的主机名信息,并返回一个<node hostname>集合
node->host (->> all-nodes
(mapcat (fn [node]
(if-let [host (.getHostName inimbus basic-supervisor-details-map node)]
[[node host]]
)))
(into {}))
;;将上述获取到的<node, hostname>集合和<node, host>集合,得到所有<node host>关系.
;;如果存在相同的node,则与其对应的主机名将采用<node,hostname>集合中的值
all-node->host (merge (:node->host existing-assignment) node->host)
;;调用changed-executors,通过将executor->node+port信息同existing-assignment中的信息进行比对,
;;计算出所有被重新分配的Executor
reassign-executors (changed-executors (:executor->node+port existing-assignment) executor->node+port)
;;通过将已经存在的assignment中的executor->start-time-secs信息
;;与所有被重新分配的通过将已经存在的assignment中的executor->start-time-secs进行合并,
;;获得最新的所有<executor,start-time-secs>集合
start-times (merge (:executor->start-time-secs existing-assignment)
(into {}
(for [id reassign-executors]
[id now-secs]
)))]]
;;创建Assignment对象,参数分别为该Topology在Nimbus服务器上的root文件夹路径、
;;<node,host>集合、新的executor->node+port映射关系以及新的<executor,start-time-secs>集合
{topology-id (Assignment.
(master-stormdist-root conf topology-id)
(select-keys all-node->host all-nodes)
executor->node+port
start-times)}))] ;; 对于新计算的<topology-id,assignment>集合中的每一项,比较其新的调度与当前运行时的调度之间是否发生了变化
;; 如果没有发生变化,就打印一条记录;否则将该Topology在ZooKeeper中保存的调度结果更新assignment
(doseq [[topology-id assignment] new-assignments
:let [existing-assignment (get existing-assignments topology-id)
topology-details (.getById topologies topology-id)]]
(if (= existing-assignment assignment)
(log-debug "Assignment for " topology-id " hasn't changed")
(do
(log-message "Setting new assignment for topology id " topology-id ": " (pr-str assignment))
(.set-assignment! storm-cluster-state topology-id assignment)
)))
;;对于前面得到的new-assignments中的每一项,首先计算出新增的slot,
;;再将其转换化为worker-slot对象,返回的是<topology-id,worker-slot>集合,
;;最后调用inimbus的assignSlots方法来分配slot
(->> new-assignments
(map (fn [[topology-id assignment]]
(let [existing-assignment (get existing-assignments topology-id)]
[topology-id (map to-worker-slot (newly-added-slots existing-assignment assignment))]
)))
(into {})
(.assignSlots inimbus topologies))
))
在该过程中,如果某个Slot不存在Executor的超时,而Supervisor的ZooKeeper心跳超时时,
认为当前Slot依然有效,可以分配认为.最坏的情况就是这些分配过去的Executor会超时,在下一轮的分配过程中,则不会分配。
mk-assignments的详细过程如下:
1.从ZooKeeper中读取所有活跃的Topologies
2.从ZooKeeper中读取当前的assignments,获取所有已经分配资源的Topology的id的集合。
3.对Topologies进行新assignments
3.1通过调用computer-topology->executors取出所有已经assignment的topology的executors
3.2 update-all-heartbeats,对每一个Topology进行更新心跳
3.3调用compute-topology->alive-executors过滤topology->executors,保留alive的executors
3.4调用compute->supervisor->dead-ports找出dead ports
3.5调用compute-topology->scheduler-assignment转换ZooKeeper中的assignment为SchedulerAssignment
3.6通过调用missing-assignment-topologies找出需要从新assign的Topology
3.7通过调用all-scheduling-slots得到所有Supervisor节点中可用的slot数量
3.8调用read-all-supervisor-details得到所有的Supervisor节点SupervisorDetails
3.9获取backtype.storm.scheduler.Cluster
3.10调用scheduler.schedule分配所有的Topologies
3.11通过调用compute-topology->executor->node_port转换SchedulerAssignment为Assignment,输出ressign日志
4.通过将已经存在的assignment中的executor->start-time-secs信息与所有被重新分配的通过将已经存在的assignment中的executor->start-time-secs进行合并,获得最新的所有<executor,start-time-secs>集合,补充start-times等信息,获得new-assignments。
5.调用set-assignment!将新的assignment结果写入ZooKeeper.
mk-assignments负责对当前集群中所有Topology进行新一轮的任务调度。先检查已运行的Topology所占用的资源,判断它们是否有问题以及重新分配;根据系统当前的可用资源,为新提交的Topology分配任务。mk-assignments会将所有assignment信息更新到ZooKeeper中,Supervisor周期性地检查这些分配信息,并根据这些分配信息做相应的调度处理。
注:学习李明老师Storm源码分析和陈敏敏老师Storm技术内幕与大数据实现的笔记的整理。
欢迎关注下面二维码进行技术交流:

JStorm与Storm源码分析(二)--任务分配,assignment的更多相关文章
- JStorm与Storm源码分析(四)--均衡调度器,EvenScheduler
EvenScheduler同DefaultScheduler一样,同样实现了IScheduler接口, 由下面代码可以看出: (ns backtype.storm.scheduler.EvenSche ...
- JStorm与Storm源码分析(一)--nimbus-data
Nimbus里定义了一些共享数据结构,比如nimbus-data. nimbus-data结构里定义了很多公用的数据,请看下面代码: (defn nimbus-data [conf inimbus] ...
- JStorm与Storm源码分析(三)--Scheduler,调度器
Scheduler作为Storm的调度器,负责为Topology分配可用资源. Storm提供了IScheduler接口,用户可以通过实现该接口来自定义Scheduler. 其定义如下: public ...
- storm源码分析之任务分配--task assignment
在"storm源码分析之topology提交过程"一文最后,submitTopologyWithOpts函数调用了mk-assignments函数.该函数的主要功能就是进行topo ...
- JStorm与Storm源码分析(五)--SpoutOutputCollector与代理模式
本文主要是解析SpoutOutputCollector源码,顺便分析该类中所涉及的设计模式–代理模式. 首先介绍一下Spout输出收集器接口–ISpoutOutputCollector,该接口主要声明 ...
- Storm源码分析--Nimbus-data
nimbus-datastorm-core/backtype/storm/nimbus.clj (defn nimbus-data [conf inimbus] (let [forced-schedu ...
- Fresco 源码分析(二) Fresco客户端与服务端交互(1) 解决遗留的Q1问题
4.2 Fresco客户端与服务端的交互(一) 解决Q1问题 从这篇博客开始,我们开始讨论客户端与服务端是如何交互的,这个交互的入口,我们从Q1问题入手(博客按照这样的问题入手,是因为当时我也是从这里 ...
- 框架-springmvc源码分析(二)
框架-springmvc源码分析(二) 参考: http://www.cnblogs.com/leftthen/p/5207787.html http://www.cnblogs.com/leftth ...
- Tomcat源码分析二:先看看Tomcat的整体架构
Tomcat源码分析二:先看看Tomcat的整体架构 Tomcat架构图 我们先来看一张比较经典的Tomcat架构图: 从这张图中,我们可以看出Tomcat中含有Server.Service.Conn ...
随机推荐
- [BZOJ4008]亚瑟王
Description 小 K 不慎被 LL 邪教洗脑了,洗脑程度深到他甚至想要从亚瑟王邪教中脱坑. 他决定,在脱坑之前,最后再来打一盘亚瑟王.既然是最后一战,就一定要打得漂 亮.众所周知,亚瑟王是一 ...
- Ceph Object Gateway Admin api 获取用户列表问题
按照官方文档使用Admin Ops API 获取用户列表 GET /admin/user时 返回{code: 403, message: Forbidden}这里有两个问题:首先用户列表的请求为 如下 ...
- 开始学习机器学习,从Ng的视频开始
时隔开5个月,忙完了考研和毕设后终于有时间搞自己想搞得,研究生导师方向是图像处理与机器学习结合,重新开工 何为机器学习? 对于机器学习(Machine Learning)的定义大体上有两种,第一种是美 ...
- v9 调用模型中新增的字段
在模型中新增字段的时候,可以选择“是否为主表”. 若选是,则前台调用可直接通过字段名调用. 若选否,在前台调用是应在{pc:content}中添加 moreinfo="1",表示允 ...
- java当中成员变量和局部变量的区别
1:成员变量定义在类中,整个类中都可以访问.2:局部变量定义在函数,语句,局部代码块中,只在所属的区域有效.3:成员变量存在于堆内存的对象中.4:局部变量存在于栈内存的方法中.5:成员变量随着对象的创 ...
- 不支持placeholder浏览器下对placeholder进行处理
if(document.createElement('input').placeholder !== '') { $('[placeholder]').focus(function() { var i ...
- 执行3小时超长SQL的分析优化过程:从索引遇见IS NULL,到最佳实践
月底高峰期,对一个典型项目抽查分析时,发现了一个超级慢.全表扫描的SQL,语句很简单,AWR中赫然在列,在我统计的截止时间内还没有结束... 使用v$active_session_history进一步 ...
- jq-animate
jq-animate: <!doctype html> <html> <head> <meta charset="utf-8"> & ...
- 在MacOS中,Unity使用VSCode开发,4.7版本无法正常使用C#
我在MacOS中安装了两个版本的Unity,一个是4.7版本,一个是5.6版本,在5.6版本中使用VSCode打开项目时,可以正常代码提示和查看,但是打开4.7版本的项目时,无法正常提示和查看. 经过 ...
- Linux离线安装Ruby详解
很多时候我们会发现,真实的生成环境很多都没有外网,只有内网环境,这个时候我们又需要安装Ruby,则不能提供yum命令进行在线安装了,这个时候我们就需要下载安装包进行离线安装.本文主要简单介绍如果离线安 ...