Storm-源码分析- timer (backtype.storm.timer)
mk-timer
timer是基于PriorityQueue实现的(和PriorityBlockingQueue区别, 在于没有阻塞机制, 不是线程安全的), 优先级队列是堆数据结构的典型应用
默认情况下, 按照自然顺序(其实就是默认comparator的定义), 最小的元素排在堆头
当然也可以自己重新实现comparator接口, 比如timer就用reify重新实现了comparator接口
整个过程其实比较简单, 开个timer-thread, 不断check PriorityQueue里面时间最小的timer是否已经可以触发
如果可以, 就poll出来, 调用callback, 并sleep, 都很好理解
唯一需要说的是, 这里使用Semaphore,
信号量和lock相似, 都是用于互斥
不同在于, 信号量模拟资源管理, 所以不同于lock的排他, 信号量可以接收多个aquire(取决于配置)
另外一个比较大的区别, lock是解铃还须系铃人, 谁锁谁解, 而信号量无所谓, 任何线程都可以调用release, 或acquire
这里使用信号量, 是用于在cancel-timer时, 等待timer-thread结束
- (defn cancel-timer [timer]
- (check-active! timer)
- (locking (:lock timer)
- (reset! (:active timer) false)
- (.interrupt (:timer-thread timer)))
- (.acquire (:cancel-notifier timer)))
因为cancel的过程就是将active置false, 然后就是调用acquire等待信号量cancel-notifier被释放
而timer-thread在线程结束前, 会release这个信号量
- (defnk mk-timer [:kill-fn (fn [& _] )]
- (let [queue (PriorityQueue. 10
- (reify Comparator
- (compare [this o1 o2]
- (- (first o1) (first o2))
- )
- (equals [this obj]
- true
- )))
- active (atom true) ;;标志位
- lock (Object.) ;;创建lock对象, 由于PriorityQueue非线程安全, 所以使用locking来保证同时只有一个线程访问queue
- notifier (Semaphore. 0) ;;创建信号量, 初始为0
- timer-thread (Thread.
- (fn []
- (while @active
- (try
- ;;peek读但不从queue中取出, 先读出time看看, 符合条件再取出
- (let [[time-secs _ _ :as elem] (locking lock (.peek queue))]
- (if (and elem (>= (current-time-secs) time-secs))
- ;;无法保证恰好, 只要当前时间>=time-secs, 就可以执行, 可想而知对于afn必须不能耗时, 否则会影响其他timer
- ;; imperative to not run the function inside the timer lock
- ;; otherwise, it's possible to deadlock if function deals with other locks
- ;; (like the submit lock)
- (let [afn (locking lock (second (.poll queue)))] ;;poll从queue中取出
- (afn)) ;;真正执行timer中的callback
- (Time/sleep 1000)
- ))
- (catch Throwable t
- ;; because the interrupted exception can be wrapped in a runtimeexception
- (when-not (exception-cause? InterruptedException t)
- (kill-fn t)
- (reset! active false)
- (throw t))
- )))
- (.release notifier)))]
- (.setDaemon timer-thread true)
- (.setPriority timer-thread Thread/MAX_PRIORITY)
- (.start timer-thread)
- {:timer-thread timer-thread
- :queue queue
- :active active
- :lock lock
- :cancel-notifier notifier}))
schedule
schedule其实就是往PriorityQueue里面插入timer
对于循环schdule, 就是在timer的callback里面, 再次schedule
- (defnk schedule [timer delay-secs afn :check-active true]
- (when check-active (check-active! timer))
- (let [id (uuid)
- ^PriorityQueue queue (:queue timer)]
- (locking (:lock timer)
- (.add queue [(+ (current-time-secs) delay-secs) afn id])
- )))
- (defn schedule-recurring [timer delay-secs recur-secs afn]
- (schedule timer
- delay-secs
- (fn this []
- (afn)
- (schedule timer recur-secs this :check-active false)) ; this avoids a race condition with cancel-timer
- ))
使用例子
Supervisor中的使用例子, 定期的调用hb函数更新supervisor的hb
在mk-timer时, 传入的kill-fn callback, 会在timer-thread发生exception的时候被调用
- :timer (mk-timer :kill-fn (fn [t]
- (log-error t "Error when processing event")
- (halt-process! 20 "Error when processing an event")
- ))
- (schedule-recurring (:timer supervisor)
- 0
- (conf SUPERVISOR-HEARTBEAT-FREQUENCY-SECS)
- heartbeat-fn)
Storm-源码分析- timer (backtype.storm.timer)的更多相关文章
- Storm源码分析--Nimbus-data
nimbus-datastorm-core/backtype/storm/nimbus.clj (defn nimbus-data [conf inimbus] (let [forced-schedu ...
- JStorm与Storm源码分析(一)--nimbus-data
Nimbus里定义了一些共享数据结构,比如nimbus-data. nimbus-data结构里定义了很多公用的数据,请看下面代码: (defn nimbus-data [conf inimbus] ...
- JStorm与Storm源码分析(四)--均衡调度器,EvenScheduler
EvenScheduler同DefaultScheduler一样,同样实现了IScheduler接口, 由下面代码可以看出: (ns backtype.storm.scheduler.EvenSche ...
- JStorm与Storm源码分析(三)--Scheduler,调度器
Scheduler作为Storm的调度器,负责为Topology分配可用资源. Storm提供了IScheduler接口,用户可以通过实现该接口来自定义Scheduler. 其定义如下: public ...
- JStorm与Storm源码分析(二)--任务分配,assignment
mk-assignments主要功能就是产生Executor与节点+端口的对应关系,将Executor分配到某个节点的某个端口上,以及进行相应的调度处理.代码注释如下: ;;参数nimbus为nimb ...
- storm源码分析之任务分配--task assignment
在"storm源码分析之topology提交过程"一文最后,submitTopologyWithOpts函数调用了mk-assignments函数.该函数的主要功能就是进行topo ...
- Nimbus<三>Storm源码分析--Nimbus启动过程
Nimbus server, 首先从启动命令开始, 同样是使用storm命令"storm nimbus”来启动看下源码, 此处和上面client不同, jvmtype="-serv ...
- storm源码分析之topology提交过程
storm集群上运行的是一个个topology,一个topology是spouts和bolts组成的图.当我们开发完topology程序后将其打成jar包,然后在shell中执行storm jar x ...
- JStorm与Storm源码分析(五)--SpoutOutputCollector与代理模式
本文主要是解析SpoutOutputCollector源码,顺便分析该类中所涉及的设计模式–代理模式. 首先介绍一下Spout输出收集器接口–ISpoutOutputCollector,该接口主要声明 ...
- Storm-源码分析- hook (backtype.storm.hooks)
task hook 在某些task事件发生时, 如果用户希望执行一些额外的逻辑, 就需要使用hook 当前定义如下事件, emit, cleanup, spoutAck-- 用户只需要开发实现ITas ...
随机推荐
- SVN 安装后报不是内部或外部命令
SVN安装后报不是内部或外部命令,也不是可运行的程序 解决方法:windows安装svn的时候默认是不安装 svn command line这个东西的,重新打开svn的安装exe,选择modify,将 ...
- jsp学习之scriptlet的使用方法
scriptlet的使用 jsp页面中分三种scriptlet: 第一种:<% %> 可以在里面写java的代码.定义java变量以及书写java语句. 第二种:<%! %> ...
- 一款纯css3实现的超炫3D表单
今天要给大家分享一款纯css3实现的超炫3D表单.该特效页面的加载的时候3d四十五度倾斜,当鼠标经过的时候表单动画回正.效果非常炫,一起看下效果图: 在线预览 源码下载 实现的代码. html代码 ...
- python的卸载方式和运行yum报错:No module named yum
公司测试机环境不知道给我卸了什么包,导致yum运行报错状况: 系统版本:Red Hat Enterprise Linux Server release 6.2 (Santiago) 内核版本:2.6. ...
- DFS应用——遍历有向图+判断有向图是否有圈
[0]README 0.1) 本文总结于 数据结构与算法分析, 源代码均为原创, 旨在 理解 "DFS应用--遍历有向图+判断有向图是否有圈" 的idea 并用源代码加以实现 : ...
- 嵌入式开发之davinci--- 8148/8168/8127 中的图像处理算法优化库vlib
The Texas Instruments VLIB is an optimizedImage/Video Processing Functions Library for C programmers ...
- 采用预取(Prefetch)来加速你的网站(转)
一.DNS预取 如果你像我一样想在网站上有一个Twitter小程序,还有网站分析,再也许一些网页字体,那么你必须要链接到一些其它域名,这意味着你将不得不引发DNS查询.我的建议通常是,不要还没有先适当 ...
- 【BZOJ】1088: [SCOI2005]扫雷Mine(递推)
http://www.lydsy.com/JudgeOnline/problem.php?id=1088 脑残去想递推去了... 对于每一个第二列的格子,考虑多种情况,然后转移.....QAQ 空间可 ...
- hdu 3599(最短路+最大流)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3599 思路:首先spfa求一下最短路,然后对于满足最短路上的边(dist[v]==dist[u]+w) ...
- Amazon(vpc)对等网络
对等连接测试 1.1 东京账户A创建对等连接 注意,双方的vpc网段不能重复,如果重复会造成无法配置路由表 输入双方信息 账户ID和VPC 1.2 东京账户A查看 查看连接信息 显示正在处理接受,需要 ...