Performance 调整Apache Storm序列化程序以提高性能

Performance 调整Apache Storm序列化程序以提高性能,performance,serialization,apache-storm,kryo,Performance,Serialization,Apache Storm,Kryo,我对Java和ApacheStorm还不熟悉,我想知道如何让事情进展得更快! 我设置了一个Storm群集,其中有两台物理机器,每台机器有8个内核。集群工作得非常好。为了测量性能,我设置了以下测试拓扑: builder.setSpout("spout", new RandomNumberSpoutSingle(sizeOfArray), 10); builder.setBolt("null", new NullBolt(), 4).allGrouping(&

我对Java和ApacheStorm还不熟悉,我想知道如何让事情进展得更快! 我设置了一个Storm群集,其中有两台物理机器,每台机器有8个内核。集群工作得非常好。为了测量性能,我设置了以下测试拓扑:

builder.setSpout("spout", new RandomNumberSpoutSingle(sizeOfArray), 10);
builder.setBolt("null", new NullBolt(), 4).allGrouping("spout");
RandomNumbersPoutingle创建如下数组:

  ArrayList<Integer> array = new ArrayList<Integer>();
ArrayList数组=新的ArrayList();
我用sizeOfArray整数填充它。这个数组与一个ID相结合,构建了我的元组。 现在,我使用allGrouping测量每秒到达bolt的元组数(我查看Storm GUI的“Transfer”值)

如果我把sizeOfArray=1024,大约173000个元组/秒被推送。由于1个元组应该是大约4*1024字节,所以移动大约675MB/秒

到目前为止我说的对吗? 现在我的问题是:Storm/Kryo是否能够移动更多?我怎样才能调整这个?是否有我忽略的设置? 我想每秒序列化更多元组!如果我使用本地洗牌,值会急剧上升,因为不需要序列化任何内容,但我需要所有worker上的元组。
CPU、内存和网络都没有被完全占用。

我认为您的计算是正确的,但我不确定在序列化过程中是否考虑了非原始整数类型的Java开销,这会给等式增加更多字节。然而,我也不确定这是否是分析storm性能的最佳方法,因为这更多地是用每秒的元组数来衡量的,而不是用带宽来衡量的

Storm为基本类型、字符串、字节数组、ArrayList、HashMap和HashSet()内置了序列化。当我编程Java以获得最高性能时,我会尽可能地坚持使用基本类型。使用
int[]
而不是
ArrayList
是否可行?如果在您的设置中可能的话,我希望从中获得一些性能

考虑到storm能够即时序列化的上述类型,我很可能不会尝试改进序列化性能。我认为kryo是非常优化的,在这里很难实现更快的目标。我也不确定序列化是否是这里的真正瓶颈,或者说是拓扑设置中的某个瓶颈(见下文)

我将研究与工作人员内部和工作人员之间通信相关的其他可调参数。可以找到一个很好的概述。在一个性能至关重要的拓扑中,我使用以下设置代码来调整此类参数。需要通过测试找出在您的情况下最有效的方法

int topology_executor_receive_buffer_size = 32768; // intra-worker messaging, default: 32768
int topology_transfer_buffer_size = 2048; // inter-worker messaging, default: 1000
int topology_producer_batch_size = 10; // intra-worker batch, default: 1
int topology_transfer_batch_size = 20; // inter-worker batch, default: 1
int topology_batch_flush_interval_millis = 10; // flush tuple creation ms, default: 1
double topology_stats_sample_rate = 0.001; // calculate metrics every 1000 messages, default: 0.05
conf.put("topology.executor.receive.buffer.size", topology_executor_receive_buffer_size);
conf.put("topology.transfer.buffer.size", topology_transfer_buffer_size);
conf.put("topology.producer.batch.size", topology_producer_batch_size);
conf.put("topology.transfer.batch.size", topology_transfer_batch_size);
conf.put("topology.batch.flush.interval.millis", topology_batch_flush_interval_millis);
conf.put("topology.stats.sample.rate", topology_stats_sample_rate);
正如您所注意到的,当storm能够使用工作进程内处理时,性能会大大提高,所以如果可能的话,我总是建议使用它。您确定需要所有分组吗?如果不是,我建议使用shuffleGrouping,如果storm认为合适,它实际上将使用本地通信,除非
topology.disable.loadaware.messaging
设置为false。我不确定allGrouping是否会对同一个worker上的组件使用本地通信

我想知道的另一件事是拓扑结构的配置:有10个喷嘴和4个耗电螺栓。除非螺栓使用传入元组的速度比创建元组的速度快得多,否则建议对这两个组件使用相同数量的元组。从您描述流程的方式来看,您似乎使用了确认和失败,因为您已经编写了一个为元组分配ID的代码。在保证处理单个元组不是绝对要求的情况下,可以通过切换到未编排的元组来获得性能。确认和失败确实会产生一些开销,所以如果关闭它,我会假设元组吞吐量会更高

最后,您还可以尝试最大挂起元组数的值(通过方法setMaxSpoutPending of theSpouts配置)。不确定storm默认使用的是什么,但是根据我的经验,设置一个比螺栓可以吸收的下游稍高的数字可以提供更高的吞吐量。查看storm UI中传输的元组的容量和数量