如何使用代码中的新螺栓更新现有的Storm拓扑?

时间:2018-08-16 10:12:16

标签: java spring docker apache-kafka apache-storm

我正在编写一个使用Apache Storm v1.1.2,Kafka v0.11.0.1,Zookeeper 3.4.6,Eureka和Cloud-Config的Docker化Java Spring应用程序,这些应用程序均在Docker-Compose精心安排的Docker容器中。

我通过KafkaSpout接收到的元组有一个“值”字段,它是一个protobuf对象。我使用自定义反序列化器将我的对象移出该对象进行处理。

我有一个基本的应用程序,其中有一个螺栓,该螺栓可打印传入的消息,并根据protobuf对象中字段的值将其路由到其他某些螺栓。我也有LocalCluster,Config和TopologyBuilder充当Spring Bean。

当前,我在PostContruct中设置了所有螺栓,但是我需要能够动态添加螺栓,这些螺栓可以根据protobuf对象的其他字段过滤传入的消息并执行基本的聚合功能(最大值/最小值/窗口平均值)。

我想使用REST控制器执行此操作,但是如何停止和启动拓扑而不丢失数据?我也不想从一开始就通过听Kafka主题来重启拓扑,因为该系统将承受极高的负载。

这篇文章看起来很有希望,但是我绝对希望整个过程自动化,因此我不会进入Zookeeper https://community.hortonworks.com/articles/550/unofficial-storm-and-kafka-best-practices-guide.html

如何在代码中编辑现有拓扑以动态添加新螺栓?

1 个答案:

答案 0 :(得分:1)

不能。提交后,风暴拓扑是静态的。如果您需要根据元组中的字段来改变处理,最好的选择是预先提交所有需要的螺栓。然后,您可以使用一个或多个检查元组并根据元组内容发送到特定流的螺栓,来更改元组通过拓扑的路径。

例如制作一个SplitterBolt

public void execute(Tuple input) {
  if (tuple.getIntegerByField("theDecider") == 1) {
    collector.emit("onlyOnes", tuple.getValues());
  } else {
    collector.emit("others", tuple.getValues());
  }
}

在您的拓扑构建代码中您将拥有类似的东西

builder.setSpout("kafka-spout", ...);
builder.setBolt("splitter", new SplitterBolt()).shuffleGrouping("kafka-spout");
builder.setBolt("countOnes", new CounterBolt()).shuffleGrouping("splitter", "onlyOnes");
builder.setBolt("countOthers", new CounterBolt()).shuffleGrouping("splitter", "others");