我们在单个拓扑内的任务并行性方面存在问题。我们无法获得良好,流畅的处理速度。
我们正在使用Kafka和Storm构建具有不同拓扑的系统,在该系统中,数据是根据使用Kafka主题连接的一系列拓扑进行处理的。
我们正在使用Kafka 1.0.0和Storm 1.2.1
消息量很小,每天大约2000条消息,但是每个任务可能要花费一些时间。特别是一种拓扑可能需要花费可变的时间来处理每个任务,通常在1到20分钟之间。如果按顺序处理,则吞吐量不足以处理所有传入消息。所有拓扑和Kafka系统都安装在一台计算机上(16个内核,16 GB RAM)。
由于消息是独立的并且可以并行处理,因此我们尝试使用Storm并发功能来提高吞吐量。
为此,拓扑已配置如下:
使用此配置,我们在此拓扑中观察到以下行为。
我们有两个主要问题。首先,即使有4个工作程序和10个并行提示,也仅启动4-5个任务。其次,即使只有一项任务,在有待处理的工作时也不会启动任何批处理。
没有足够的工作要做的问题,因为我们一开始尝试插入2000个任务,所以有很多工作要做。
我们试图增加参数“ maxSpoutsPending”,希望拓扑将读取更多批并将它们同时排队,但是似乎它们是在内部进行流水线处理,而不是同时进行处理。
使用以下代码创建拓扑:
private static StormTopology buildTopologyOD() {
//This is the marker interface BrokerHosts.
BrokerHosts hosts = new ZkHosts(configuration.getProperty(ZKHOSTS));
TridentKafkaConfig tridentConfigCorrelation = new TridentKafkaConfig(hosts, configuration.getProperty(TOPIC_FROM_CORRELATOR_NAME));
tridentConfigCorrelation.scheme = new RawMultiScheme();
tridentConfigCorrelation.fetchSizeBytes = Integer.parseInt(configuration.getProperty(MAX_SIZE_BYTES_CORRELATED_STREAM));
OpaqueTridentKafkaSpout spoutCorrelator = new OpaqueTridentKafkaSpout(tridentConfigCorrelation);
TridentTopology topology = new TridentTopology();
Stream existingObject = topology.newStream("kafka_spout_od1", spoutCorrelator)
.shuffle()
.each(new Fields("bytes"), new ProcessTask(), new Fields(RESULT_FIELD, OBJECT_FIELD))
.parallelismHint(Integer.parseInt(configuration.getProperty(PARALLELISM_HINT)));
//Create a state Factory to produce outputs to kafka topics.
TridentKafkaStateFactory stateFactory = new TridentKafkaStateFactory()
.withProducerProperties(kafkaProperties)
.withKafkaTopicSelector(new ODTopicSelector())
.withTridentTupleToKafkaMapper(new ODTupleToKafkaMapper());
existingObject.partitionPersist(stateFactory, new Fields(RESULT_FIELD, OBJECT_FIELD), new TridentKafkaUpdater(), new Fields(OBJECT_FIELD));
return topology.build();
}
和配置创建为:
private static Config createConfig(boolean local) {
Config conf = new Config();
conf.setMaxSpoutPending(1); // Also tried 2..6
conf.setNumWorkers(4);
return conf;
}
我们是否可以通过增加并行任务的数量或/和在完成批处理时避免饥饿来提高性能?
答案 0 :(得分:0)
我发现内森·马兹(Nathan Marz)在风暴用户中发现了old post,有关为Trident设置并行性:
我建议使用“名称”功能来命名流的各个部分 以便用户界面可以显示与各个部分对应的螺栓。
Trident将操作打包到尽可能少的螺栓中。此外, 除非您完成操作,否则它绝不会重新划分流 明确涉及重新分区(例如shuffle,groupBy, partitionBy,全局聚合等)。三叉戟的财产 确保您可以控制事物的排序/半排序 被处理。因此,在这种情况下,groupBy之前的所有内容都必须 具有相同的并行度,否则三叉戟将不得不重新分区 流。而且由于您没有说过要流 重新分区,它无法做到这一点。您可以获得不同的并行度 通过引入重新分区来针对喷口 操作,就像这样:
stream.parallelismHint(1).shuffle()。each(...)。each(...)。parallelismHint(3).groupBy(...);
我认为您可能想为自己的喷口以及.each
设置parallelismHint。
关于同时处理多个批处理,您很正确,这就是maxSpoutPending
在Trident中的用途。尝试在Storm UI中检查您的最大出水口未决值是否实际被提取了。另外,请尝试为MasterBatchCoordinator启用调试日志记录。通过该日志记录,您应该能够知道是否同时有多个批次在飞行。
当您说不是同时处理多个批次时,您的意思是ProcessTask吗?请记住,Trident的属性之一是根据批次对状态更新进行排序。如果您有maxSpoutPending = 3并且批次1、2和3在飞行中,在写入批次1之前,Trident不会发射更多的批次进行处理,此时它将再发射一个。因此,即使完成了2和3的处理,速度较慢的批处理也会阻止更多的发光,它们必须等待1完成并被写入。
如果您不需要Trident的批处理和订购行为,则可以尝试使用常规Storm。
更多附带说明,但您可能需要考虑从storm-kafka
迁移到storm-kafka-client
。这个问题并不重要,但是如果不这样做,您将无法升级到Kafka 2.x,并且在迁移一堆状态之前会更加容易。