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

Java 如何在不重新启动拓扑的情况下动态更新属性文件?,java,properties,apache-storm,Java,Properties,Apache Storm,我需要在ApacheStorm中设计一个能够读取多个属性文件的拓扑。在我的原始设计中,创建拓扑时将加载属性,每个螺栓将通过使用参数获得所需的属性,例如builder.setBolt(“Bolt1”,新的Bolt1(param1,param2,…),3).。但是,每次更新属性文件时,我都必须重新启动拓扑,此操作将清除内存中的数据。我不想得到这个结果,但是,在每个螺栓中加载属性文件是昂贵的,这不是一个好的设计 我有另一个想法。我使用螺栓加载属性文件并将它们保存在参数对象中。此螺栓位于喷口之后,它将向

我需要在ApacheStorm中设计一个能够读取多个属性文件的拓扑。在我的原始设计中,创建拓扑时将加载属性,每个螺栓将通过使用参数获得所需的属性,例如
builder.setBolt(“Bolt1”,新的Bolt1(param1,param2,…),3).
。但是,每次更新属性文件时,我都必须重新启动拓扑,此操作将清除内存中的数据。我不想得到这个结果,但是,在每个螺栓中加载属性文件是昂贵的,这不是一个好的设计

我有另一个想法。我使用螺栓加载属性文件并将它们保存在
参数对象中。此螺栓位于喷口之后,它将向下一个螺栓发射
参数对象。在这个设计中,
参数对象
将被发送到需要它的螺栓上,它可以防止访问属性文件的次数过多


然而,我不确定这是一个好的设计,还是有更好的设计。请给我一些建议。非常感谢

一个选项是将配置文件存储在HDFS中,并使用(免责声明:我的博客文章关于使用tick tuples)定期在bolt中重新加载它们

例如:

@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);
   }
}
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>>>() {});
}
我之所以选择HDFS,是因为API很简单,可以很好地使用。例如:

@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);
   }
}
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>>>() {});
}
FileSystem fs=FileSystem.get(URI.create(_hdfsUrl),new Configuration());
字符串路径=”hdfs://server/folder/something.json";
路径p=新路径(路径);
如果(财政司司长存在(p)){
InputStreamReader istream=新的InputStreamReader(fs.open(p))
Map Map=newhashmap();
ObjectMapper mapper=新的ObjectMapper();
map=mapper.readValue(istream,newTypeReference(){});
}
回应“在每个螺栓中加载属性文件的成本很高,这不是一个好的设计”。。。我不同意。您的螺栓将在集群中分布到许多不同工作区(也称为许多不同JVM)中的许多不同节点。这意味着您需要在同一螺栓的多个实例中加载配置。另外,如果你想动态地重新加载配置,你需要在你的螺栓中的某个地方使用这种机制


另一种选择是使用Zookeeper,但老实说,API使用起来很麻烦,HDFS工作得很好。

您可以有一个额外的喷口,它将轮询存储在某处的属性文件中的更改,并在检测到任何更改时将该文件作为元组发送到所有螺栓。从喷口接收元组时,所有螺栓都可以更新其属性。