Storm的滑动窗口TickTuple通常用来控制bolt定制执行入库操作,使用过程中遇到了TickTuple“意外停止”的情况。
场景描述
Jiaodian任务共计使用12个worker,tick tuple间隔为5分钟。
WebPvLogSpout & WebPvLogBolt的executor数量为12.
WebPvLogSpout消费kafka topic,log_product_ypvlog共计10个partition
6月14号下午启动,次日凌晨1点35分之后,有2个bolt就收不到tick tuple。
生产tickTuple消息的线程【user-timer】由于disruptor的原因,一直处于挂起状态。
"user-timer" daemon prio=10 tid=0x00007f8ea8ac7000 nid=0x353c runnable [0x00007f8e29662000]
java.lang.Thread.State: TIMED_WAITING (parking)【处于挂起状态,一致等待信号激活自己,正常情况应该处于sleeping状态】
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:349)
at com.lmax.disruptor.AbstractMultithreadedClaimStrategy.waitForFreeSlotAt(AbstractMultithreadedClaimStrategy.java:99)
at com.lmax.disruptor.AbstractMultithreadedClaimStrategy.incrementAndGet(AbstractMultithreadedClaimStrategy.java:49)
at com.lmax.disruptor.Sequencer.next(Sequencer.java:127)
at backtype.storm.utils.DisruptorQueue.publishDirect(DisruptorQueue.java:174)
at backtype.storm.utils.DisruptorQueue.publish(DisruptorQueue.java:167)
at backtype.storm.disruptor$publish.invoke(disruptor.clj:66)
at backtype.storm.disruptor$publish.invoke(disruptor.clj:68)
at backtype.storm.daemon.executor$setup_ticks_BANG_$fn__6510.invoke(executor.clj:315)
at backtype.storm.timer$schedule_recurring$this__1807.invoke(timer.clj:99)
at backtype.storm.timer$mk_timer$fn__1790$fn__1791.invoke(timer.clj:50)
at backtype.storm.timer$mk_timer$fn__1790.invoke(timer.clj:42)
at clojure.lang.AFn.run(AFn.java:24)
at java.lang.Thread.run(Thread.java:745)
![](https://i-blog.csdnimg.cn/blog_migrate/6a1568cdf853f0ab313db2d18ca121e9.png)
问题分析
包装后的kafka客户端会让分配不到partition的spout一直阻塞[ArrayBlockingQueue.take()]
user-timer多个小时的jstack信息,都是TIMED_WAITING (parking),其他worker的状态是sleeping。
spout几个小时一直阻塞,由于spout接收队列会被metrics and system stream塞满,一直得不到处理,会导致TickTuple消息无法放入到队列,这就导致了user-timer线程一直挂起,等待被唤醒。
解决方案
将spout的数量设置为kafka topic的partition相等的数量,实际上是不让spout长时间的处于阻塞状态。
官网issues
https://issues.apache.org/jira/browse/STORM-299