如何在不重新启动拓扑的情况下动态更新属性文件?

时间:2015-06-22 10:15:02

标签: java properties apache-storm

我需要在apache storm中设计一个拓扑,它可以读取多个属性文件。在我的原始设计中,将在创建拓扑时加载属性,并且每个螺栓将通过使用参数(例如builder.setBolt("Bolt1", new Bolt1(param1, param2, ...), 3)...)获得所需的属性。但是,每次我想更新属性文件时,我都必须重新启动拓扑,此操作将清除内存中的数据。我不想得到这个结果,但是,在每个螺栓中加载属性文件的成本很高,并且它不是一个好的设计。

我有另一个想法。我使用bolt来加载属性文件并将其保存在parameter object中。这个螺栓在喷口之后,它会将parameter object发射到下一个螺栓。在此设计中,parameter object将被发送到需要它的螺栓,并且它可以防止多次访问属性文件。

但是,我不确定它是好的设计还是存在更好的设计。请给我一些建议。非常感谢!

1 个答案:

答案 0 :(得分:0)

一个选项是将配置文件存储在HDFS中,并使用tick tuples定期将其重新加载到您的螺栓内(免责声明:我关于使用tick元组的博客文章)。

例如:

@Override
public void execute(Tuple tuple, BasicOutputCollector collector) {
   try {
      if (isTickTuple(tuple)) {
          // refresh our configs from HDFS
          _fileLoader.load(_configs);
         return;
      }

     // do your bolt stuff 
     // use configs you loaded earlier
     // ...
   } catch (Exception e) {
      LOG.error("Bolt execute error: {}", e);
      collector.reportError(e);
   }
}

我之所以选择HDFS,是因为API很简单,适用于parsing libraries like jackson。例如:

FileSystem fs = FileSystem.get(URI.create(_hdfsUrl), new Configuration());
String path = "hdfs://server/folder/something.json";
Path p = new Path(path);
if (fs.exists(p)) {
   InputStreamReader istream = new InputStreamReader(fs.open(p))
   Map<String, Set<String>> map = new HashMap<String, Set<String>>();
   ObjectMapper mapper = new ObjectMapper();
   map = mapper.readValue(istream, new TypeReference<HashMap<String, HashSet<String>>>() {});
}

响应&#34;加载属性文件在每个螺栓中是昂贵的,这不是一个好的设计&#34; ...我不同意。您的螺栓将在整个群集中分布到许多不同工作者(也称为许多不同的JVM)中的许多不同节点。这意味着您需要在同一个螺栓的多个实例中加载配置。另外,如果你想动态重新加载配置,你将需要在你的螺栓内部的那个机制。

另一种选择是使用Zookeeper,但说实话,API使用起来很痛苦,HDFS也很完美。