2021SC@SDUSC
storm代码阅读(十)
2021SC@SDUSC
Task部分阅读(五)
mk-tasks-fn函数
mk-tasks-fn函数将返回一个函数tasks-fn,tasks-fn函数可根据要发送的消息获取消息的接收端TaskId集合。
mk-tasks-fn函数代码如下:
1 (defn mk-tasks-fn [task-data]
2 (let [task-id (:task-id task-data)
3 executor-data (:executor-data task-data)
4 component-id (:component-id executor-data)
5 ^WorkerTopologyContext worker-context (:worker-context executor-data)
6 storm-conf (:storm-conf executor-data)
7 emit-sampler (mk-stats-sampler storm-conf)
8 stream->component->grouper (:stream->component->grouper executor-data)
9 user-context (:user-context task-data)
10 executor-stats (:stats executor-data)
11 debug? (= true (storm-conf TOPOLOGY-DEBUG))]
12
13 (fn ([^Integer out-task-id ^String stream ^List values]
14 (when debug?
15 (log-message "Emitting direct: " out-task-id "; " component-id " " stream " " values))
16 (let [target-component (.getComponentId worker-context out-task-id)
17 component->grouping (get stream->component->grouper stream)
18 grouping (get component->grouping target-component)
19 out-task-id (if grouping out-task-id)]
20 (when (and (not-nil? grouping) (not= :direct grouping))
21 (throw (IllegalArgumentException. "Cannot emitDirect to a task expecting a regular grouping")))
22 (if out-task-id [out-task-id])
23 ))
24 ([^String stream ^List values]
25 (when debug?
26 (log-message "Emitting: " component-id " " stream " " values))
27 (let [out-tasks (ArrayList.)]
28 (fast-map-iter [[out-component grouper] (get stream->component->grouper stream)]
29 (when (= :direct grouper)
30 ;; TODO: this is wrong, need to check how the stream was declared
31 (throw (IllegalArgumentException. "Cannot do regular emit to direct stream")))
32 (let [comp-tasks (grouper task-id values)]
33 (if (or (sequential? comp-tasks) (instance? Collection comp-tasks))
34 (.addAll out-tasks comp-tasks)
35 (.add out-tasks comp-tasks)
36 )))
37 out-tasks)))
38 ))
下面对这个函数进行解读:
line8:该行定义的stream->component->grouper变量非常重要,它指定了系统中的组件将以分组函数定义的方式去收听流。
line13~23:定义了函数的第一个重载。该重载函数用于应对向直接流发送消息的情况,传入的参数中out-task-id为接收端的TaskId,stream为消息发送流,values为要发送的消息。当用户将TOPOLOGY_DEBUG设置为true时,debug?方法也将返回true,此时系统将对输入的消息进行记录。
line16~19:通过out-task-id获得其所在的组件以及该组件对该直接流的收听方式。直接流只能采取直接分组的方式进行收听,第20 ~23行对此进行检测。要注意的是,若out-task-id为空,则表示该流没有组件收听,这在Storm中是允许的,该消息将被丢弃掉。由于发送到直接流的消息的目标Task已经确定,因此这部分重载的最主要功能其实是完成异常检测。
line24~38:这部分定义了函数的另一个重载,其输入函数仅包括消息所在的流以及消息本身。第28行根据流找到所有收听该流的组件及收听方式。类似的,对于非直接流,不能使用直接分组的方式进行收听。
line32:该行调用grouper函数来获得目标节点的TaskId,输入为发送消息的Task对应的TaskId以及消息本身。例如,随机分组的分组函数会根据消息的哈希值来选择目标TaskId。
line33~36:该部分会根据分组函数返回的是集合还是单个元素而调用不同的函数,将结果添加到ret中。
line37:该行返回目标TaskId的集合,消息将被发送到这些Task。