Storm调优(optimiaze)

来源:互联网 发布:js时间相减 编辑:程序博客网 时间:2024/06/03 19:30

在充分了解节点计算机硬件资源的情况下进行Storm运行性能的调优。

Storm运行性能调优主要是从以下几个方面:

(1)代码层面,这得看程序编写者的功力了。

(2)并行度层面,分为:

setNumWorkers取值;

kafkaSpout取值(假设是从Kafka中读取数据);

Bolt取值;

shuffleGroupingfieldsGrouping的选择等。


1. setNumWorkders

worker 可以分配到不同的 supervisor 节点上,这是 Storm 实现多节点并行计算的主要配置手段。在一定程度上workers 的数量越多越好,但实际生产硬件资源有限。所以主要考虑集群中各节点的内存情况:默认情况下,一个 worker 分配 768M 的内存,外加 64M 给 logwriter 进程;因此一个 worker 会耗费 832M 内存;假设集群有3个节点,每个节点4G内存,除去 Linux 系统、kafka、zookeeper 等的消耗,保守估计仅有2G内存可用来运行 topology,由此可知,当集群只有一个 topology 在运行的情况下,最多可以配置6个 worker。

此外,还可以调节 worker 的内存空间。这取决于流过 topology 的数据量的大小以及各 bolt 单元的业务代码的执行时间。如果数据量特别大,代码执行时间较长,那么可以考虑增加单个 worker 的工作内存。有一点需要注意的是,一个 worker 下的所有 executor 和 task 都是共享这个 worker 的内存的,也就是假如一个 worker 分配了 768M 内存,3个 executor,6个 task,那么这个 3 executor 和 6 task 其实是共用这 768M 内存的,但是好处是可以充分利用多核 CPU 的运算性能。


2. kafkaSpout

如果 spout 读取的是 kafka 的数据,那么正常情况下,设置为 topic 的分区数量即可。计算 kafkaSpout 的最佳取值,有一个最简单的办法,就是在 Storm UI里面,点开 topology 的首页,在 Spouts (All time) 下,查看以下几个参数的值:

  • Emitted已发射出去的tuple数
  • Transferred已转移到下一个bolt的tuple数
  • Complete latency (ms) 每个tuple在tuple tree中完全处理所花费的平均时间
  • Acked 成功处理的tuple数
  • Failed 处理失败或超时的tuple数

看这几个参数的技巧:

  • 正常情况下Failed值为0,如果不为0,考虑增加该 spout 的并行度。这是最重要的一个判断依据;
  • 正常情况下,EmittedTransferredAcked这三个值应该是相等或大致相等的,如果相差太远,要么该 spout 负载太重,要么下游负载过重,需要调节该 spout 的并行度,或下游 bolt 的并行度;
  • Complete latency (ms)时间,如果很长,十秒以上就已经算很长的了。当然具体时间取决于代码逻辑,bolt 的结构,机器的性能等。

kafka 只能保证同一分区下消息的顺序性,当 spout 配置了多个 executor 的时候,不同分区的消息会均匀的分发到不同的 executor 上消费,那么消息的整体顺序性就难以保证了,除非将 spout 并行度设为 1


3. Bolt

其取值也有一个简单办法,就是在 Storm UI里面,点开 topology 的首页,在 Bolts (All time) 下,查看以下几个参数的值:

3个参数对性能来说参考意义比较明显,包括Execute latency, Process latency, Capacity,

具体的意义如下:

Execute latency:消息的平均处理时间,单位为毫秒。

Process latency:消息从接收到被ack掉所花的时间,单位为毫秒。如果没有启用ACKER机制,那么Process latency的值为0。

Capacity:计算公式为Capacity = Bolt或者Executor调用execute()处理的消息数量×消息平均执行时间/时间区间。如果这个值越接近1,说明Bolt或者Executor基本一直在调用executer(),因此并行度不够,需要扩展这个组件的Executor数量。

  • Capacity(last 10m) 取值越小越好,当接近1的时候,说明负载很严重,需要增加并行度,正常是在 0.0x 到 0.1-0.2 左右
  • Process latency(ms) 单个 tuple 的平均处理时间,越小越好,正常也是 0.0x 级别;如果很大,可以考虑增加并行度,但主要以 Capacity 为准。


一般情况下,按照该 bolt 的代码时间复杂度,设置一个 spout 并行度的 1-3倍即可。


4.优化配置参数

/** tuple发送失败重试策略,一般情况下不需要调整 */spoutConfig.retryInitialDelayMs  = 0;spoutConfig.retryDelayMultiplier = 1.0;spoutConfig.retryDelayMaxMs = 60 * 1000;/** 此参数比较重要,可适当调大一点 *//** 通常情况下 spout 的发射速度会快于下游的 bolt 的消费速度,当下游的 bolt 还有 TOPOLOGY_MAX_SPOUT_PENDING 个 tuple 没有消费完时,spout 会停下来等待,该配置作用于 spout 的每个 task。  */conf.put(Config.TOPOLOGY_MAX_SPOUT_PENDING, 10000)/** 调整分配给每个 worker 的内存,关于内存的调节,上文已有描述 */conf.put(Config.WORKER_HEAP_MEMORY_MB,             768);conf.put(Config.TOPOLOGY_WORKER_MAX_HEAP_SIZE_MB,  768);/** 调整 worker 间通信相关的缓冲参数,以下是一种推荐的配置 */conf.put(Config.TOPOLOGY_RECEIVER_BUFFER_SIZE,             8); // 1.0 以上已移除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 UI 上查看当前集群的 Topology Configuration

worker内存的配置也可以在yaml配置文件中写入。

Storm中真正干活的是各个worker,而worker由supervisor负责启动。在topology启动过程中可以看到如下的启动日志:


这就是启动一个worker进程,也就是一个JVM进程。默认情况下,Storm启动worker进程时,JVM的最大内存是768M。但在使用过程中,由于会在Bolt中加载大量数据,768M内存无法满足需求,会导致内存溢出程序崩溃。可以通过在Strom的配置文件storm.yaml中设置worker的启动参数:


5、rebalance

可以直接采用 rebalance 命令(也可以在 Storm UI上操作)重新配置 topology 的并行度:

storm rebalance TOPOLOGY-NAME -n 5 -e SPOUT/BOLT1-NAME=3 -e SPOUT/BOLT2-NAME=10



GC参数优化:

可以对每个worker的java内存参数进行调整,配置在conf/storm.yaml文件中,

可以通过在Strom的配置文件storm.yaml中设置worker的启动参数:

[plain] view plain copy
  1. worker.childopts: "-Xmx2048m"  
该参数会在启动时传递给JVM,然后就可以在worker中使用2048m内存了。

一个比较简单的启用CMS的GC配置可以为:


也可以在worker.childopts的参数中加入打印GC的日志进行GC性能的优化。

-XX:+PrintGCDetails -Xloggc:d:\gc.log



参考文献:

【1】http://www.jianshu.com/p/f645eb7944b0

【2】https://my.oschina.net/u/2326085/blog/391271

原创粉丝点击