mk-assignments主要功能就是产生Executor与节点+端口的对应关系,将Executor分配到某个节点的某个端口上,以及进行相应的调度处理。代码注释如下:

  1. ;;参数nimbusnimbus-data对象,:scratch-topology-id为需要重新调度的Topologyid
  2. (defnk mk-assignments [nimbus :scratch-topology-id nil]
  3. (let [conf (:conf nimbus);;分别从nimbus-data中获取conf,storm-cluster-stateinimbus对象,并将其保存为临时变量
  4. storm-cluster-state (:storm-cluster-state nimbus)
  5. ^INimbus inimbus (:inimbus nimbus)
  6. ;;从zk中读取所有活跃的Topologies,获取他们id的集合
  7. topology-ids (.active-storms storm-cluster-state)
  8. ;;根据前面得到的Topology-id的集合,对每一个id调用read-topology-details方法
  9. ;;从参数nimbus-data中获取topology-details信息,并以<topology-id,topology-details>保存在集合中
  10. topologies (into {} (for [tid topology-ids]
  11. {tid (read-topology-details nimbus tid)}))
  12. ;;利用前面得到的<topology-id,topology-details>集合创建Topologies对象
  13. topologies (Topologies. topologies)
  14. ;;读取所有已经分配资源的Topologyid的集合。
  15. assigned-topology-ids (.assignments storm-cluster-state nil)
  16. existing-assignments (into {} (for [tid assigned-topology-ids]
  17. ;; 对于那些已经分配资源但需要重新调度的Topology(由scratch-topology-id指定),
  18. ;; 我们忽略其之前的分配,故之前分配占用的所有slot将被视为空闲slot(空闲资源),可重新被调度使用。
  19. (when (or (nil? scratch-topology-id) (not= tid scratch-topology-id))
  20. {tid (.assignment-info storm-cluster-state tid nil)})))
  21. ;; 调用compute-new-topology->executor->node+port方法为所有Topologies计算新的调度,
  22. ;; 并返回topology->executor->node+port
  23. topology->executor->node+port (compute-new-topology->executor->node+port
  24. nimbus
  25. existing-assignments
  26. topologies
  27. scratch-topology-id)
  28.  
  29. ;;获取当前系统时间(秒)
  30. now-secs (current-time-secs)
  31. ;;调用basic-supervisor-details-map方法获取ZooKeeper中所有的SupervisorInfo信息,
  32. ;;然后将其转换为<supervisor-id,SupervisorDetails>集合,具体操作看1
  33. basic-supervisor-details-map (basic-supervisor-details-map storm-cluster-state)
  34.  
  35. ;; topology->executor->node+port中各项进行处理,通过添加开始时间等构建最终的作业
  36. ;; 返回得到<topology-id Assignment>集合
  37. new-assignments (into {} (for [[topology-id executor->node+port] topology->executor->node+port
  38. ;;根据topology-id获取Topology的任务分配情况
  39. :let [existing-assignment (get existing-assignments topology-id)
  40. ;;从executor->node+port信息中提取所有的节点信息
  41. all-nodes (->> executor->node+port vals (map first) set)
  42. ;;根据all-nodes获取每个节点的主机名信息,并返回一个<node hostname>集合
  43. node->host (->> all-nodes
  44. (mapcat (fn [node]
  45. (if-let [host (.getHostName inimbus basic-supervisor-details-map node)]
  46. [[node host]]
  47. )))
  48. (into {}))
  49. ;;将上述获取到的<node, hostname>集合和<node, host>集合,得到所有<node host>关系.
  50. ;;如果存在相同的node,则与其对应的主机名将采用<node,hostname>集合中的值
  51. all-node->host (merge (:node->host existing-assignment) node->host)
  52. ;;调用changed-executors,通过将executor->node+port信息同existing-assignment中的信息进行比对,
  53. ;;计算出所有被重新分配的Executor
  54. reassign-executors (changed-executors (:executor->node+port existing-assignment) executor->node+port)
  55. ;;通过将已经存在的assignment中的executor->start-time-secs信息
  56. ;;与所有被重新分配的通过将已经存在的assignment中的executor->start-time-secs进行合并,
  57. ;;获得最新的所有<executor,start-time-secs>集合
  58. start-times (merge (:executor->start-time-secs existing-assignment)
  59. (into {}
  60. (for [id reassign-executors]
  61. [id now-secs]
  62. )))]]
  63. ;;创建Assignment对象,参数分别为该TopologyNimbus服务器上的root文件夹路径、
  64. ;;<node,host>集合、新的executor->node+port映射关系以及新的<executor,start-time-secs>集合
  65. {topology-id (Assignment.
  66. (master-stormdist-root conf topology-id)
  67. (select-keys all-node->host all-nodes)
  68. executor->node+port
  69. start-times)}))]
  70.  
  71. ;; 对于新计算的<topology-id,assignment>集合中的每一项,比较其新的调度与当前运行时的调度之间是否发生了变化
  72. ;; 如果没有发生变化,就打印一条记录;否则将该TopologyZooKeeper中保存的调度结果更新assignment
  73. (doseq [[topology-id assignment] new-assignments
  74. :let [existing-assignment (get existing-assignments topology-id)
  75. topology-details (.getById topologies topology-id)]]
  76. (if (= existing-assignment assignment)
  77. (log-debug "Assignment for " topology-id " hasn't changed")
  78. (do
  79. (log-message "Setting new assignment for topology id " topology-id ": " (pr-str assignment))
  80. (.set-assignment! storm-cluster-state topology-id assignment)
  81. )))
  82. ;;对于前面得到的new-assignments中的每一项,首先计算出新增的slot,
  83. ;;再将其转换化为worker-slot对象,返回的是<topology-id,worker-slot>集合,
  84. ;;最后调用inimbusassignSlots方法来分配slot
  85. (->> new-assignments
  86. (map (fn [[topology-id assignment]]
  87. (let [existing-assignment (get existing-assignments topology-id)]
  88. [topology-id (map to-worker-slot (newly-added-slots existing-assignment assignment))]
  89. )))
  90. (into {})
  91. (.assignSlots inimbus topologies))
  92. ))

在该过程中,如果某个Slot不存在Executor的超时,而Supervisor的ZooKeeper心跳超时时,
认为当前Slot依然有效,可以分配认为.最坏的情况就是这些分配过去的Executor会超时,在下一轮的分配过程中,则不会分配。

  1. mk-assignments的详细过程如下:
  2. 1.ZooKeeper中读取所有活跃的Topologies
  3. 2.ZooKeeper中读取当前的assignments,获取所有已经分配资源的Topologyid的集合。
  4. 3.Topologies进行新assignments
  5. 3.1通过调用computer-topology->executors取出所有已经assignmenttopologyexecutors
  6. 3.2 update-all-heartbeats,对每一个Topology进行更新心跳
  7. 3.3调用compute-topology->alive-executors过滤topology->executors,保留aliveexecutors
  8. 3.4调用compute->supervisor->dead-ports找出dead ports
  9. 3.5调用compute-topology->scheduler-assignment转换ZooKeeper中的assignmentSchedulerAssignment
  10. 3.6通过调用missing-assignment-topologies找出需要从新assignTopology
  11. 3.7通过调用all-scheduling-slots得到所有Supervisor节点中可用的slot数量
  12. 3.8调用read-all-supervisor-details得到所有的Supervisor节点SupervisorDetails
  13. 3.9获取backtype.storm.scheduler.Cluster
  14. 3.10调用scheduler.schedule分配所有的Topologies
  15. 3.11通过调用compute-topology->executor->node_port转换SchedulerAssignmentAssignment,输出ressign日志
  16. 4.通过将已经存在的assignment中的executor->start-time-secs信息与所有被重新分配的通过将已经存在的assignment中的executor->start-time-secs进行合并,获得最新的所有<executor,start-time-secs>集合,补充start-times等信息,获得new-assignments
  17. 5.调用set-assignment!将新的assignment结果写入ZooKeeper.

  

mk-assignments负责对当前集群中所有Topology进行新一轮的任务调度。先检查已运行的Topology所占用的资源,判断它们是否有问题以及重新分配;根据系统当前的可用资源,为新提交的Topology分配任务。mk-assignments会将所有assignment信息更新到ZooKeeper中,Supervisor周期性地检查这些分配信息,并根据这些分配信息做相应的调度处理。

注:学习李明老师Storm源码分析和陈敏敏老师Storm技术内幕与大数据实现的笔记的整理。 
欢迎关注下面二维码进行技术交流:

JStorm与Storm源码分析(二)--任务分配,assignment的更多相关文章

  1. JStorm与Storm源码分析(四)--均衡调度器,EvenScheduler

    EvenScheduler同DefaultScheduler一样,同样实现了IScheduler接口, 由下面代码可以看出: (ns backtype.storm.scheduler.EvenSche ...

  2. JStorm与Storm源码分析(一)--nimbus-data

    Nimbus里定义了一些共享数据结构,比如nimbus-data. nimbus-data结构里定义了很多公用的数据,请看下面代码: (defn nimbus-data [conf inimbus] ...

  3. JStorm与Storm源码分析(三)--Scheduler,调度器

    Scheduler作为Storm的调度器,负责为Topology分配可用资源. Storm提供了IScheduler接口,用户可以通过实现该接口来自定义Scheduler. 其定义如下: public ...

  4. storm源码分析之任务分配--task assignment

    在"storm源码分析之topology提交过程"一文最后,submitTopologyWithOpts函数调用了mk-assignments函数.该函数的主要功能就是进行topo ...

  5. JStorm与Storm源码分析(五)--SpoutOutputCollector与代理模式

    本文主要是解析SpoutOutputCollector源码,顺便分析该类中所涉及的设计模式–代理模式. 首先介绍一下Spout输出收集器接口–ISpoutOutputCollector,该接口主要声明 ...

  6. Storm源码分析--Nimbus-data

    nimbus-datastorm-core/backtype/storm/nimbus.clj (defn nimbus-data [conf inimbus] (let [forced-schedu ...

  7. Fresco 源码分析(二) Fresco客户端与服务端交互(1) 解决遗留的Q1问题

    4.2 Fresco客户端与服务端的交互(一) 解决Q1问题 从这篇博客开始,我们开始讨论客户端与服务端是如何交互的,这个交互的入口,我们从Q1问题入手(博客按照这样的问题入手,是因为当时我也是从这里 ...

  8. 框架-springmvc源码分析(二)

    框架-springmvc源码分析(二) 参考: http://www.cnblogs.com/leftthen/p/5207787.html http://www.cnblogs.com/leftth ...

  9. Tomcat源码分析二:先看看Tomcat的整体架构

    Tomcat源码分析二:先看看Tomcat的整体架构 Tomcat架构图 我们先来看一张比较经典的Tomcat架构图: 从这张图中,我们可以看出Tomcat中含有Server.Service.Conn ...

随机推荐

  1. Linux常见命令(二)

    随着Linux应用的扩展许多同学开始接触Linux,根据学习Windwos的经验往往有一些茫然的感觉:不知从何处开始学起.虽然Linux桌面应用发展很快,但是命令在Linux中依然有很强的生命力.Li ...

  2. sed的用法

    1.什么是sed sed命令是一个流线式.非交互式编辑器,可以实现在vi等编辑器中一样的编辑效果.   2.sed的工作原理 模式空间(pattern space) sed一次处理一行文本(或输入), ...

  3. 安装旧版的docker-engine-1.12.6

    执行kubeadm init --api-advertise-addresses=172.16.160.211命令的时候,提示docker版本太新了 想要安装旧版docker,可以使用以下方法: yu ...

  4. 关于MATLAB处理大数据坐标文件2017530

    今天使用了所有特征并且用SVM测试数据 理由:SVM可以使用特征将测试集划分区域,比较单调.死板 结果:成绩很不理想,无疑又一次说明随机森林更适合大数据处理 第二次提交数据 用MATLAB运行11次运 ...

  5. sql求和isnull注意事项

    如果不用isnull函数判断则计算出来如果有一列是null 则相加就是null,如 两列:1 null 1+null = nullselect sum(ISNULL(jinE,0)+ISNULL(qi ...

  6. 【Android Developers Training】 97. 序言:访问通讯录数据

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  7. 如何在新浪sae服务器上面连接redis

    1.创建php空应用 2.选择

  8. 跨进程通信之Messenger

    1.简介 Messenger,顾名思义即为信使,通过它可以在不同进程中传递Message对象,通过在Message中放入我们需要的入局,就可以轻松实现数据的跨进程传递了.Messenger是一种轻量级 ...

  9. Swift开发常用知识点

    #pragma mark - as/类型转换as? / as! 需要根据前面的返回值决定 有?证明可选,可能为空:需要弱解包 没有?证明一定有值:大胆解包 as? 前面的结果是可选的 if let / ...

  10. 使用Gulp实现前端构建自动化

    使用Gulp实现前端构建自动化 安装 一.安装NodeJs Gulp的安装依赖于NodeJs的npm安装管理器 安装包下载地址 关于npm命令: 1. npm install <name> ...