Spout实现mk-threads接口用于创建与Executor对应的消息循环主函数。

defmulti mk-threads executor-selector

Mk-threads函数的主消息循环通过async-loop方法实现,若传入的函数为工厂方法,则在第一次调用该方法时进行初始化,并返回用于消息循环的函数。

Spout输入处理函数

spout的输入处理函数采用非阻塞的方式从接收队列中获取消息:

(disruptor/consume-batch receive-queue event-handler)

处理函数原型:

tuple-action-fn (fn [task-id ^TupleImpl tuple])

函数说明:

  1. 确定消息来源(根据流ID判定),若消息来自SYSTEM_TICK_STREAM_ID,则调用pending对象的rotate方法,该方法导致发送消息超时.在进行消息跟踪过程中,Spout会用pending对象来保存所有发送出去的消息,用SYSTEM_TICK消息作为清理缓存消息的信号.
  2. 若消息来自METRICS_TICK_STREAM_ID,则调用metrics-tick方法来整理目前统计信息并将其发送到信息统计Bolt节点上去.
  3. 其它消息来源只能为Ack/Fail的流,获取消息的ID,将该ID对应的数据从pending数组中清除出去,并返回该ID对应的数据,返回数据格式:
    [stored-task-id,spout-id,tuple-finished-info,start-time-ms]
    Stored-task-id为发送消息的TaskID,spout-id为发送消息是附带的MessageId,tuple-finished-info含有发送消息的StreamId及消息内容,start-time-ms则在消息被执行统计采样时,存储当前的时间.否则为空。
  4. 若消息来自ACKER-ACK-STREAM-ID,则调用ack-spout-msg回调方法处理消息(ack-spout-msg函数主要调用用户的Spout对象的Ack回调方法  .ack spout msg-id),若消息来自ACKER-FAIL-STREAM-ID,则调用fail-spout-msg方法处理(fail-spout-msg函数主要调用Spout对象的Fail回调方法 .fail spout msg-id)

Spout消息发送函数

Spout使用send-spout-msg函数来发送消息。

函数原型:

send-spout-msg (fn [out-stream-id values message-id out-task-id])

参数说明:

Out-stream-id为消息的StreamId,values为消息内容,message-id为消息的MessageId,表示是否对消息进行跟踪,out-task-id则是消息的接收端TaskId,用于向直接流发送消息.

方法说明:

  1. 调用task-fn函数获得消息的目标TaskId,task-fn为Task的主要函数,它根据消息的StreamId和消息内容来确定哪些Task将接收该流的消息,以及以何种方式来接收该流的消息。对于直接分组方式,其作用主要是检查目标out-task-id是否以直接分组的方式来接收消息.
  2. task-fn函数内部通过调用,从outbound-components函数返回的从组件到某一个流的分组函数,获得的目标Task集合.
  3. 调用transfer-fn函数发送消息,该函数由mk-executor-transfer-fn函数创建,并会将消息发送至Executor发发送队列中.

mk-executor-transfer-fn函数原型:

(defn mk-executor-transfer-fn [bath-transfer->worker])

函数说明:

  1. bath-transfer->worker对于于Executor的输出Disruptor Queue.
  2. 该函数有三种重载,主要区别在于是否对发送的消息进行缓存.
  3. 当Disruptor Queue接收端未启动或空间不足时,用overflow-buffer临时存放将要发送的信息。
  4. 在进行消息发送时若overflow-buffer非空,则标明该异常已经发生过,Disruptor Queue中空间不足,此时消息会被直接放入overflow-buffer以提高效率.
  5. 在 Spout消息循环中,会优先发送overflow-buffer中的数据.

Spout对象的初始化

调用Executor中各Spout对象的open操作,且open方法只会调用一次.

初始化过程说明:

  1. 等待对应的Topology处于活跃状态.
  2. 对Executor中的每个Spout进行如下操作,获得tasks-fn函数和send-spout-msg函数,send-soput-msg函数会利用tasks-fn函数选择目标TaskId,每个Spout都定义了send-spout-msg方法,它是Task级别非Executor共享.
  3. 调用Spout对象的open回调方法,同时实例化SpoutOutputCollector,它主要用于调用send-spout-msg来发送消息.
  4. 调用consumer-started!函数打开接收队列。由于在open函数被调用之前,接收队列尚未打开,故最好不要在Spout的open函数中发送消息.

Spout消息循环

Async-loop:该函数使用一个线程来循环调用传入的函数afn,同时要求被调用的afn在执行结束后返回一个时间间隔,并将其作为与下次调用之间需要等待的事件间隔.

过程说明:

  1. 以非阻塞的方式对接收队列中的消息进行处理。
  2. 优先发送overflow-buffer中的数据。
  3. 若overflow-buffer为空,并且pending存储的数据少于max-spout-pending,或者未设置max-spout-pending,Topology处于活动状态,则Spout可以发送消息,若Topology处于非活动状态则休眠100毫秒。
  4. 依次调用spout的nextTuple回调方法来发送消息,nextTuple会利用传入的SpoutOutputCollector的emit或emitDirect方法来发送消息,并最终调用send-spout-msg函数将消息发送到Executor的消息队列中,send-spout-msg会更新emitted-count.
  5. 若emitted-count与上次发送消息的curr-count相同,则表明nextTuple函数没有发送出去消息,此时调用spout-wait-strategy的emptyEmit方法来进行处理,默认休眠1毫秒(TOPOLOGY_SLEEP_SPOUT_WAIT_STRATEGY_TIME_MS配置项决定休眠时间).

Storm系列(十五)架构分析之Executor-Spout的更多相关文章

  1. Storm系列(十六)架构分析之Executor-Bolt

    准备消息循环的数据 函数原型: 1  let[executor-sampler (mk-stats-sampler (:storm-conf executor-data))] 主要功能: 定义tupl ...

  2. Storm系列(十四)架构分析之Executor-输入和输出处理

    Executor的数据 mk-executor-data函数用于定义Executor中含有的数据. Executor的输入处理 根据executor-id从Worker的:executor-recei ...

  3. Storm系列(十二)架构分析之Worker-心跳信息处理

    Worker通过worker-data方法定义了一个包含很多共享数据的映射集合,Worker中很多方法都依赖它 mk-worker 功能: 创建对应的计时器.Executor.接收线程接收消息   方 ...

  4. 聊聊MySQL的加锁规则《死磕MySQL系列 十五》

    大家好,我是咔咔 不期速成,日拱一卒 本期来聊聊MySQL的加锁规则,知道这些规则后可以判断SQL语句的加锁范围,同时也可以写出更好的SQL语句,防止幻读问题的产生,在能力范围内最大程度的提升MySQ ...

  5. 学习ASP.NET Core Razor 编程系列十五——文件上传功能(三)

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  6. Storm系列(五)架构分析之Nimbus启动过程

    启动流程图   mk-assignments 功能:对当前集群中所有Topology进行新一轮的任务调度. 实现源码路径: \apache-storm-0.9.4\storm-core\src\clj ...

  7. Nimbus<一>Storm系列(五)架构分析之Nimbus启动过程

    启动流程图 mk-assignments 功能:对当前集群中所有Topology进行新一轮的任务调度. 实现源码路径: \apache-storm-0.9.4\storm-core\src\clj\b ...

  8. MP实战系列(十五)之执行分析插件

    SQL 执行分析拦截器[ 目前只支持 MYSQL-5.6.3 以上版本 ],作用是分析 处理 DELETE UPDATE 语句, 防止小白或者恶意 delete update 全表操作! 这里我引用M ...

  9. Storm 系列(五)—— Storm 编程模型详解

    一.简介 下图为 Strom 的运行流程图,在开发 Storm 流处理程序时,我们需要采用内置或自定义实现 spout(数据源) 和 bolt(处理单元),并通过 TopologyBuilder 将它 ...

随机推荐

  1. 网络请求 post 的接受请求头的代理方法

    接收响应头 content-Length content-Type - (void)connection:(NSURLConnection *)connection didReceiveRespons ...

  2. WIN32api总结

    1.鼠标操作: win32api.SetCursorPos((101,156)) win32api.mouse_event(win32con.MOUSEEVENT_LEFTDOWN,0,0,0,0) ...

  3. shell 练习

    shell 练习 iii= ] do iii=$[$iii+] echo -n "$iii " done iii= ] do iii=$[$iii+] echo -n " ...

  4. jquery 简单弹出层(转)

    预定义html代码:没有 所有代码通过js生成和移除. 预定义css /* 基本弹出层样式 */ .my-popup-overlay { width:100%; height:auto; /* wid ...

  5. BZOJ 3983 Takeover Wars 解题报告

    我猜了一个结论,能合并就合并,到了必须要敌对交易的时候才进行敌对交易. 然后合并的话,肯定是拿最大的两个去合并. 至于敌对交易,肯定是干掉对方最大的公司才是有意义的. 于是各种分类讨论...看代码好了 ...

  6. HDU4530+模拟

    /* */ #include<stdio.h> #include<string.h> #include<stdlib.h> #include<algorith ...

  7. nginx -t "nginx: [warn] only the last index in "index" directive should be absolute in 6 "的问题解决

    修改完nginx的配置文件之后,执行nginx -t命令提示"nginx: [warn] only the last index in "index" directive ...

  8. Codeforces Round #215 (Div. 1)

    A Sereja and Algorithm 题意:给定有x,y,z组成的字符串,每次询问某一段s[l, r]能否变成变成zyxzyx的循环体. 分析: 分析每一段x,y,z数目是否满足构成循环体,当 ...

  9. *[codility]StoneWall

    https://codility.com/demo/take-sample-test/stone_wall 拼石块.用最少的方块.一开始想了想用贪心,是可行的,就是尽量每次把当前的高度往右延伸到最多, ...

  10. Android Button悬浮在SurfaceView上

    实现Button悬浮于与SurfaceView之上实现 注意:你实现的SurfaceView和android中的Button,EditView是同级的,不能把一个包含在另一个里面 1.创建自己的Sur ...