1.Storm源码下载及目录熟悉
- 1.1在Storm官方网站上寻找源码地址
- http://storm.apache.org/downloads.html
- 1.2 点击文字标签进入github
点击Apache/storm文字标签,进入github
https://github.com/apache/storm - 1.3 拷贝storm源码地址
在网页右侧,拷贝storm源码地址
- 1.4 使用Subversion客户端下载
https://github.com/apache/storm/tags/v0.9.5
1.5 Storm源码目录分析
扩展包中的三个项目,使storm能与hbase、hdfs、kafka交互
- Idea导入pom工程
- 导入Jstorm源码在之前Storm直接导入代码,切换一下导包就可以直接用了。
- 1.6 Storm源码编译
2.1 Storm 任务提交的过程
- 将数据序列化原理
storm的任务提交和执行
- 一个完整的assignment对象
- storm数据分组策略
3.1 Worker进程间通信
- 对于worker进程来说,为了管理流入和传出的消息,每个worker进程有一个独立的接收线程 (对配置的TCP端口supervisor.slots.ports进行监听);
对应Worker接收线程,每个worker存在一个独立的发送线程 ,它负责从worker的transfer-queue 中读取消息,并通过网络发送给其他worker - 每个executor有自己的incoming-queue 和outgoing-queue 。
Worker接收线程将收到的消息通过task编号传递给对应的executor(一个或多个)的incoming-queues;
每个executor有单独的线程分别来处理spout/bolt的业务逻辑,业务逻辑输出的中间数据会存放在outgoing-queue中,当executor的outgoing-queue中的tuple达到一定的阀值,executor的发送线程将批量获取outgoing-queue中的tuple,并发送到transfer-queue中。 - 每个worker进程控制一个或多个executor线程,用户可在代码中进行配置。其实就是我们在代码中设置的并发度个数。
总结
6.4、Worker 内部通信技术(Disruptor) (了解即可)
Disruptor的来历
- 一个公司的业务与技术的关系,一般可以分为三个阶段。第一个阶段就是跟着业务跑。第二个阶段是经历了几年的时间,才达到的驱动业务阶段。第三个阶段,技术引领业务的发展乃至企业的发展。所以我们在学习Disruptor这个技术时,不得不提LMAX这个机构,因为Disruptor这门技术就是由LMAX公司开发并开源的。
- LMAX是在英国注册并受到FSA监管(监管号码为509778)的外汇黄金交易所。LMAX也是欧洲第一家也是唯一一家采用多边交易设施Multilateral Trading Facility(MTF)拥有交易所牌照和经纪商牌照的欧洲顶级金融公司
- LAMX拥有最迅捷的交易平台,顶级技术支持。LMAX交易所使用“(MTF)分裂器Disruptor”技术,可以在极短时间内(一般在3百万秒之一内)处理订单,在一个线程里每秒处理6百万订单。所有订单均为撮合成交形式,无一例外。多边交易设施(MTF)曾经用来设计伦敦证券交易 所(london Stock Exchange)、德国证券及衍生工具交易所(Deutsche Borse)和欧洲证券交易所(Euronext)。
- 2011年LMAX凭借该技术获得了金融行业技术评选大赛的最佳交易系统奖和甲骨文“公爵杯”创新编程框架奖。
Disruptor是什么
1、 简单理解:Disruptor是一个Queue。Disruptor是实现了“队列”的功能,而且是一个有界队列。而队列的应用场景自然就是“生产者-消费者”模型。
2、 在JDK中Queue有很多实现类,包括不限于ArrayBlockingQueue、LinkBlockingQueue,这两个底层的数据结构分别是数组和链表。数组查询快,链表增删快,能够适应大多数应用场景。
3、 但是ArrayBlockingQueue、LinkBlockingQueue都是线程安全的。涉及到线程安全,就会有synchronized、lock等关键字,这就意味着CPU会打架。
4、 Disruptor一种线程之间信息无锁的交换方式(使用CAS(Compare And Swap/Set)操作)。
Disruptor主要特点
1、 没有竞争=没有锁=非常快。
2、 所有访问者都记录自己的序号的实现方式,允许多个生产者与多个消费者共享相同的数据结构。
3、 在每个对象中都能跟踪序列号(ring buffer,claim Strategy,生产者和消费者),加上神奇的cache line padding,就意味着没有为伪共享和非预期的竞争。
Disruptor 核心技术点
Disruptor可以看成一个事件监听或消息机制,在队列中一边生产者放入消息,另外一边消费者并行取出处理.
底层是单个数据结构:一个ring buffer。
每个生产者和消费者都有一个次序计算器,以显示当前缓冲工作方式。
每个生产者消费者能够操作自己的次序计数器的能够读取对方的计数器,生产者能够读取消费者的计算器确保其在没有锁的情况下是可写的。
核心组件
- Ring Buffer 环形的缓冲区,负责对通过 Disruptor 进行交换的数据(事件)进行存储和更新。
- Sequence 通过顺序递增的序号来编号管理通过其进行交换的数据(事件),对数据(事件)的处理过程总是沿着序号逐个递增处理。
- RingBuffer底层是个数组,次序计算器是一个64bit long 整数型,平滑增长。
1、 接受数据并写入到脚标31的位置,之后会沿着序号一直写入,但是不会绕过消费者所在的脚标。
2、 Joumaler和replicator同时读到24的位置,他们可以批量读取数据到30
3、消费逻辑线程读到了14的位置,但是没法继续读下去,因为他的sequence暂停在15的位置上,需要等到他的sequence给他序号。如果sequence能正常工作,就能读取到30的数据。
5 消息不丢失机制
- 5.1、 ack是什么
- ack 机制是storm整个技术体系中非常闪亮的一个创新点。
通过Ack机制,spout发送出去的每一条消息,都可以确定是被成功处理或失败处理, 从而可以让开发者采取动作。比如在Meta中,成功被处理,即可更新偏移量,当失败时,重复发送数据。
因此,通过Ack机制,很容易做到保证所有数据均被处理,一条都不漏。
另外需要注意的,当spout触发fail动作时,不会自动重发失败的tuple,需要spout自己重新获取数据,手动重新再发送一次
ack机制即, spout发送的每一条消息,
- 在规定的时间内,spout收到Acker的ack响应,即认为该tuple 被后续bolt成功处理
- 在规定的时间内,没有收到Acker的ack响应tuple,就触发fail动作,即认为该tuple处理失败,
- 或者收到Acker发送的fail响应tuple,也认为失败,触发fail动作
另外Ack机制还常用于限流作用: 为了避免spout发送数据太快,而bolt处理太慢,常常设置pending数,当spout有等于或超过pending数的tuple没有收到ack或fail响应时,跳过执行nextTuple, 从而限制spout发送数据。
通过conf.put(Config.TOPOLOGY_MAX_SPOUT_PENDING, pending);设置spout pend数。
这个timeout时间可以通过Config.TOPOLOGY_MESSAGE_TIMEOUT_SECS来设定。Timeout的默认时长为30秒
- 异或运算
ack机制当中运用了异或运算,当其中值为0 则成功。
- 5.2、 如何使用Ack机制
spout 在发送数据的时候带上msgid
设置acker数至少大于0;Config.setNumAckers(conf, ackerParal);
在bolt中完成处理tuple时,执行OutputCollector.ack(tuple), 当失败处理时,执行OutputCollector.fail(tuple);
推荐使用IBasicBolt, 因为IBasicBolt 自动封装了OutputCollector.ack(tuple), 处理失败时,请抛出FailedException,则自动执行OutputCollector.fail(tuple)
- 开启ack机制
- 5.3、 如何关闭Ack机制
有2种途径
spout发送数据是不带上msgid
设置acker数等于0
- kafka+storm组合会不会丢失数据?(容易出面试题)
- kafka通过副本机制保障数据不丢失,strom通过ack机制保障。