理解Storm内部的消息缓冲区

From:http://www.michael-noll.com/blog/2013/06/21/understanding-storm-internal-message-buffers/
当对Storm topology进行性能优化时,理解如何配置和应用Storm内部的消息队列会很有帮助,在这篇文章中我将会解释和展示Storm 0.8/0.9实现worker间通信时worker及内部的thread executor时如何工作的。
storm work进程间Message
术语:我将会使用message/tuple,它们代表相同的意思。
当我说internal messaging时是指storm worker进程内部通信,也即发生在同一台storm machine/node内的通信。这种类型的通信依赖于基于LMAX Disruptor的几种Message Q, LMAX是一种高性能的线程间消息通信库。注意这种worker内的线程间通信不同于inter-worker通信,inter-work通信往往发生在基于网络的机器之间。Storm默认使用ZeroMQ进行inter-work通信,在storm 0.9中实验性的基于Netty进行inter-work通信,这样,ZeroMQ/Netty主要是用于work内的task想要发送数据给集群内另一台机器上work内的task。
参考如下:
Intra-worker通信/同一node上inter-thread: LMAX Disruptor
Inter-worker通信(网络内node间通信) : ZeroMQ or Netty
Inter-topology通信:Storm没提供相应机制,你必须自己寻找解决方案,比如Kafka/RabbitMQ消息系统、DataBase等。
如果你还不清楚Storm里worker进程,thread executor, task间区别,请参考Understanding the Parallelism of a Storm Topology.

图解
我们以一副图开始细节真相的详解

上图是Storm worker的internal message queue概况,work进程相关的Q用红色标注,worker内executor thread相关Q用绿色标记,尽管一个node上有多个worker进程,为了可读性这里只展示一个worker,同样一个worker内有多个thread,这里只展示了一个executor thead.

详细描述
现在你已经初略了解了intra-worker内消息结构,现在我们来详细解释。
Worker进程:
为了管理进入/进出消息,每个worker都有一个单独的receive thread监听在一个TCP端口号上,这个端口号通过supervisor.slots.ports 配置,topology.receiver.buffer.size决定了存放发送给executor thread 消息队列的缓冲大小,同样,每个worker有个send thread负责从worker的transfer queue中读取消息并通过网络发送给下游的consumer, transfer queue的大小由topology.transfer.buffer.size配置。
topology.receiver.buffer.size是receive thread一次能够发送给executor incomming queue的最大消息量,这些消息是通过网络读取的。这个参数设置过大可能会引起很多问题,比如heartbeat thread饥饿,throughput骤降,默认值为8个元素,并且必须是2的幂,这个要求是LMAX Disruptor间接决定的。
// Example: configuring via Java API
Config conf = new Config();
conf.put(Config.TOPOLOGY_RECEIVER_BUFFER_SIZE, 16); // default is 8
topology.receiver.buffer.size用来对比这篇文章中其他相关buffer size的大小,并不会用来配置LMAX Disruptor Queue大小, 它仅仅用来设置buffer incomming message ArrayList的大小,在这种特殊的情况下ArrayList并不会被其他thread共享,它是receive thread的局部变量。但是它的内容会用来填充基于Disruptor Q的executor incoming Q,这个Disruptor Q的大小必须是power of 2,更详细的内容可参考backtype.storm.messaging.loader中launch-receive-thread的飞
topology.transfer.buffer.size配置的transfer queue中每个元素是一个tuple list,多个Executor Send Thread将会从executor outgoing Q中取出并一批batch outgoing tuples,此参数默认值是1024个elements.
// Example: configuring via Java API
conf.put(Config.TOPOLOGY_TRANSFER_BUFFER_SIZE, 32); // default is 1024

Executor:
每个worker内控制着一个或多个executor thread. 每个executor thread 都有他自己的incoming Q和outgoing Q,就像上面描述的,每个worker都有一个专用的receive thread负责从worker incomming Q移动消息到executor thread incomming Q, 类似的,每个executor都有一个专用的send thread负责从executor outgoing Q移动消息至所在worker的transfer Q,executor incomming/outgoing Q大小通过topology.executor.receive.buffer.size/topology.executor.send.buffer.size配置。
每个executor thread都有一个单独的线程处理用户的逻辑spout/bolt, 并且还有一个send thread从executor outgoing Q中move消息到worker thransfer Q.
topology.executor.receive.buffer.size配置了executor incomming Q的大小,Q里每个元素是一个tuple list. tuple以batch为单位追加到Q中,此参数默认为1024个elements,此参数值必须为2的幂,这个要求来自LMAX Disruptor。
// Example: configuring via Java API
conf.put(Config.TOPOLOGY_EXECUTOR_RECEIVE_BUFFER_SIZE, 16384); // batched; default is 1024
topology.executor.send.buffer.size配置了executor outgoing Q大小,Q里每个元素是一个tuple,此参数默认是1024 elements,参数值必须是2的幂,此要求来自LMAX Disruptor。
// Example: configuring via Java API
conf.put(Config.TOPOLOGY_EXECUTOR_SEND_BUFFER_SIZE, 16384); // individual tuples; default is 1024

其他可参考信息:
如何配置storm’s internal message buffers
以上提到参数默认值定义在conf/defaults.yaml.你可以在storm集群的全局配置conf/storm.yarn中覆盖默认值,当然你也可以通过Storm Java API backtype.storm.Config 配置某个topology。
如何配置storm’s parallelism
storm的message buffer的正确配置与topology的工作负荷紧密联系,topo parallelism的配置同样如此,参考Understanding the Parallelism of a Storm Topology 配置prallelism.
理解storm topology的状态
Storm UI是监控topo指标的好入口,比如它展示了spout/bolt的capacity,这些不同的metrics将会帮助你决定调整这篇文章中涉及的buffer配置参数对topo的performance具有积极还是负面的作用,参考Running a Multi-Node Storm Cluster 获取更多详细信息。
此外你还可以产生你自己的应用metric,并通过工具比如Graphite追踪。参考 Sending Metrics From Storm to Graphite 和 Installing and Running Graphite via RPM and Supervisord 获取详细信息。也许从github check out ooyala’s metrics_storm 是值得的,但是目前我还没有这样做。

性能调优建议
观看Nathan Marz’s vedio Tuning and Productionization of Storm
试着从以下配置开始并观察它是否提升了你的topology performance conf.put(Config.TOPOLOGY_RECEIVER_BUFFER_SIZE, 8);
conf.put(Config.TOPOLOGY_TRANSFER_BUFFER_SIZE, 32);
conf.put(Config.TOPOLOGY_EXECUTOR_RECEIVE_BUFFER_SIZE, 16384);
conf.put(Config.TOPOLOGY_EXECUTOR_SEND_BUFFER_SIZE, 16384);

你可能感兴趣的:(Storm)