Storm内部的消息传递机制
作者:Jack47
转载请保留作者和原文出处
欢迎关注我的微信公众账号程序员杰克,两边的文章会同步,也可以添加我的RSS订阅源。
一个Storm拓扑,就是一个复杂的多阶段的流式计算。Storm中的组件(Component)就是对各个阶段的一个抽象,其中的Spout是生产者的角色,它负责源源不断地从Storm外部接收消息,扔给下游的组件处理,下游组件处理完成后,最终输出到外部的存储系统。
本文主要讲解消息在Storm内部的各个组件(Component)之间如何进行传递,本文适用于JStorm 2.1.0以后的版本。对于JStorm各个版本的改进,见这里。
如果读者对Storm的基本组成部分如Spout,Bolt,Worker进程和Task不了解,可以先看下 Storm介绍(一),Storm介绍(二)和“理解Storm拓扑并发”。
下文中使用的"消息"(Messagesage)和“元组"(Tuple)两个词语其实是同一个意思。
Storm中的每个组件,可以用一个三元组来定义
<inputStreamId, boltImpl, outputStreamInfo>
其中inputStreamId定义了这个组件所消费的流的ID; boltImpl是bolt的具体实现的类;outputStreamInfo代表这个组件的输出流的信息,包含两部分:输出流的ID和路由方式。所以当一个组件发射一个消息后,通过这个流的分组策略(Grouping)就可以立马计算出消费它的taskId。
拿下面中的拓扑为例,从图一看到这个拓扑由三个组件构成:蓝色的Spout,消费方是Green Bolt,Green Bolt的消费方是Yellow Bolt。这个拓扑在集群上的运行时的状态如图二所示:
它由两个Worker进程组成,每个Work里面运行4个Task。仔细的读者已经发现了这里没有Executor,这是JStorm和Storm很大的不同。JStorm认为Executor的存在收益比太低,虽然它支持不停机动态扩大Task的数量,但同时增加了理解成本,增加了应用开发人员编程的复杂度,所以JStorm中去掉了Executor。
->
<-
图一 一个实际拓扑组件的构成
->
<-
图二 集群上运行的一个实际拓扑
在Storm拓扑内部,同一个拓扑的多个Worker之间会发生消息传递,比如上图二中的两个Worker进程,他们之间的通信就是进程间的通信了,发送的消息需要经过序列化和反序列化。Storm中,Worker之间使用Netty进行网络通信。
在Storm拓扑的一个Worker进程内部,多个Task之间也会进行通信。比如上图二中的Task 6和Task 3。Storm中Worker进程内部的消息通信依赖于LMAX Disruptor这个高性能线程间通信的消息通信库。
Storm内部的消息传递
JStorm与Storm在内部消息传递机制上的主要差别:
JStorm中独立出一个线程来专门负责消息的反序列化,这样执行线程单独执行,而不是Storm那样,一个线程负责执行反序列化并执行用户的逻辑。相当于是把流水线拆解的更小了。这样对于反序列化时延跟执行时延在同一个数量级的应用性能提升比较明显。
图三:JStorm内部消息队列的概要图
从图里看到队列都是绿色的,这些队列都是某个Worker内部的队列。为了可读性只保留了一个Worker进程(一个storm节点一般都运行多个Worker),而且在这个Worker进程里只画了一个Task,(再次的,在一个Worker进程里通常有多个Task)
详细解释
每个Worker进程有一个NettyServer,它监听在Worker的TCP端口上(通过 supervisor.slots.ports
来配置),其他需要跟它通信的Worker会作为NettyClient分别建立连接。当NettyServer接收到消息,会根据taskId参数把消息放到对应的反序列化队列(DeserializedQueue)里面。 topology.executor.receive.buffer.size
决定了反序列化队列的大小。TaskReceiver中的反序列化线程专门负责消费反序列化队列中的消息:先将消息反序列化,然后放到执行队列(Execute Queue)中去。
执行队列的消费者是BoltExecutor线程,它负责从队列中取出消息,执行用户的代码逻辑。执行完用户的代码逻辑后,最终通过OutputCollect输出消息,此时消息里已经生成了目标task的taskId。topology.executor.receive.buffer.size
决定了执行队列的大小。可以看到JStorm中执行队列跟反序列化队列的大小是同一个配置项,即它们是一致的。
仔细看了图三的同学会发现执行队列的生产者除了TaskReceiver外,还有一个。这种消息的来源就是Worker内部的其他Task的TaskTransfer。
输出的消息通过TaskTransfer来发送,如果目标Task是Worker内部的Task,就直接扔到目标Task的执行队列中去。如果目标Task是在其他Worker上,那就先放到序列化队列中,然后由单独的一个线程专门负责序列化,然后通过NettyClient发送出去。topology.executor.send.buffer.size
决定了序列化队列的大小。
每个Worker进程有多个NettyClient,他们负责与其他的Worker进行网络通信。
延伸阅读
如何配置Storm的内部消息缓存
上面提到的众多配置项都在conf/defaults.yaml里有定义。可以通过在Storm集群的conf/storm.yaml
里进行配置来全局的覆值。也可以通过Storm的Java API backtype.storm.Config 来对单个的Storm拓扑进行配置。
如何配置Storm的并发###
Storm消息缓存的正确配置不但是和你的拓扑的负载类型紧密关联的,而且和拓扑的并发度有很大关系。后者的详细信息见理解Storm并发一文。
了解Storm拓扑上发生了什么?
Storm UI是一个用于观察你正在运行的拓扑的关键指标的良好开端。例如,它可以给你展示所谓的Spout/Bolt的“容量”。众多的指标可以帮助你决定对本文中提到的众多缓存相关的配置参数的修改,对你的拓扑的运行效率的影响是正向的还是负向的。更多信息见"运行一个多节点Storm集群"一文。
除此之外还可以注册应用程序自己的指标并使用类似Graphite这类工具来跟踪它们。详细信息见“从Storm发送指标到Graphite"和“通过RPM和Supervisord来安装和运行Graphite"。
性能调优方面的建议
可以看Storm主要作者Nathan Marz的演讲:调优和上线Storm拓扑
看看其他没有提到的参数:
topology.spout.max.batch.size
数据容量(data volume),数据速度(velocity),消息的大小,处理一个消息的计算复杂度。所以需要不断调整才能找到最佳的参数,没有银弹。
参考资料:
Understanding storm internal message buffers
如果您看了本篇博客,觉得对您有所收获,请点击右下角的“推荐”,让更多人看到!
Storm内部的消息传递机制的更多相关文章
- Chrome 消息传递机制
Chrome插件开发入门(二)——消息传递机制 Blog | Qiushi Chen 2014-03-31 9538 阅读 Chrome 插件 由于插件的js运行环境有区别,所以消息传递机制是一个重要 ...
- Chrome插件开发入门(二)——消息传递机制
Chrome插件开发入门(二)——消息传递机制 由于插件的js运行环境有区别,所以消息传递机制是一个重要内容.阅读了很多博文,大家已经说得很清楚了,直接转一篇@姬小光 的博文,总结的挺好.后面附一 ...
- iOS开发——OC篇&消息传递机制(KVO/NOtification/Block/代理/Target-Action)
iOS开发中消息传递机制(KVO/NOtification/Block/代理/Target-Action) 今晚看到了一篇好的文章,所以就搬过来了,方便自己以后学习 虽然这一期的主题是关于Fou ...
- Android异步消息传递机制源码分析
1.Android异步消息传递机制有以下两个方式:(异步消息传递来解决线程通信问题) handler 和 AsyncTask 2.handler官方解释的用途: 1).定时任务:通过handler.p ...
- (Android数据传递)Intent消息传递机制 “Intent”“数据传递”
Intent类的继承关系: 需要注意的是,该类实现了Parcelable(用于数据传递)和Cloneable接口. Intent是一种(系统级别的)消息传递机制,可以在应用程序内使用,也可以在应用 ...
- 安卓开发_深入理解Handler消息传递机制
一.概述 因为子线程的run()方法无法修改UI线程(主线程)的UI界面,所以Android引入了Handler消息传递机制,实现在新创建的线程中操作UI界面 二.消息类(Message) 消息类是存 ...
- Apache Storm内部原理分析
转自:http://shiyanjun.cn/archives/1472.html 本文算是个人对Storm应用和学习的一个总结,由于不太懂Clojure语言,所以无法更多地从源码分析,但是参考了官网 ...
- Android 消息传递机制
线程间消息传递机制 1.消息怎么发送的? 我们都知道当调用Handler发送消息的时候,不管是调用 sendMessage,sendEmptyMessage,sendMessageDelayed还是其 ...
- 我理解的Hanlder--android消息传递机制
每一个学习Android的同学都会觉得Handler是一个神奇的东西,我也一样,开始我以为我懂了Handler的机制,后来发现自己是一知半解,昨天想想,我能否自己实现一个Handler,让子线程与Ac ...
随机推荐
- java基础集合经典训练题
第一题:要求产生10个随机的字符串,每一个字符串互相不重复,每一个字符串中组成的字符(a-zA-Z0-9)也不相同,每个字符串长度为10; 分析:*1.看到这个题目,或许你脑海中会想到很多方法,比如判 ...
- DailyTick 开发实录 —— 开始
2009 年我读了李笑来老师的<把时间当朋友>,知识了柳比歇夫的时间记录法.当时激动坏了,马上动手实践起来.一开始的时候,是用一个小本子,走到哪儿都带着.完成一件事,就记录一下花费的时间. ...
- CSS 3学习——animation动画
以下内容根据官方文档翻译以及自己的理解整理. 1. 介绍 本方案介绍动画(animations).通过动画,开发者可以将CSS属性值的变化指定为一个随时间变化的关键帧(keyframes)的集合.在 ...
- JavaScript var关键字、变量的状态、异常处理、命名规范等介绍
本篇主要介绍var关键字.变量的undefined和null状态.异常处理.命名规范. 目录 1. var 关键字:介绍var关键字的使用. 2. 变量的状态:介绍变量的未定义.已定义未赋值.已定义已 ...
- Android -- 真正的 高仿微信 打开网页的进度条效果
(本博客为原创,http://www.cnblogs.com/linguanh/) 目录: 一,为什么说是真正的高仿? 二,为什么要搞缓慢效果? 三,我的实现思路 四,代码,内含注释 五,使用方法与截 ...
- Mac上MySQL忘记root密码且没有权限的处理办法&workbench的一些tips (转)
忘记Root密码肿么办 Mac上安装MySQL就不多说了,去mysql的官网上下载最新的mysql包以及workbench,先安装哪个影响都不大.如果你是第一次安装,在mysql安装完成之后,会弹出来 ...
- css text-fill-color与text-stroke讲解
顾名思义"text-fill-color"就是文字填充颜色而"text-stroke"就是文字描边.还别说,两个属性可以制作出各种炫酷的文字效果,不过IE系列都 ...
- .NET Core 2016 回顾
都在回顾自己的2016,今天我们来看看.NET Core的2016. 每一年的脚步的确是快,转眼间马上就2017.新的一年,带着理想和抱负继续出发. 1 月 ASP.NET 5 改名 ASP.NET ...
- addTwoNumbers
大神的代码好短,自己写的120多行=_= 各种判断 ListNode *f(ListNode *l1, ListNode *l2) { ListNode *p1 = l1; ListNode *p2 ...
- BPM任务管理解决方案分享
一.方案概述任务是企业管理者很多意志的直接体现,对于非常规性事务较多的企业,经常存在各类公司下达的各种任务跟进难.监控难等问题,任务不是完成效果不理解,就是时间超期,甚至很多公司管理层下达的任务都不了 ...