是否可以在实际群集环境中使用Storm Bolts / Spout中的全局静态变量

时间:2016-11-29 08:45:40

标签: java apache-storm

我有一个Storm项目,Topology Class有提交拓扑的主要方法,Spout1 - > Bolt1,Spout2 - > Bolt2。我有另一个最终的util类,它有一个静态变量 - >字符串列表。现在Bolt1使用这个静态列表并打印出内容,其中Bolt2在列表中添加了String。 Spout1和Spout2都分别以1000ms和500ms的间隔向相应的螺栓发送消息。

我已将工作人员数量设置为4,即Config.setNumWorkers(4)。

平行主义提示:Spout1 - 1,Bolt1 - 100,Spout2 - 1,Bolt2 - 100.

此代码设置在我的Window机器中的LocalCluster模式下工作。

但我不确定这是否适用于Linux中的实际集群环境,多个服务器可以满足Supervisor deamon的要求。在实际的集群环境中,我认为worker将在具有不同JVM进程的不同机器上运行。 那么螺栓是否可以访问全局静态变量,即字符串列表,因为它们可以在本地集群中进行?

下面是一些代码供参考:

public static void main(String[] args) {

    System.out.println("Starting Topology....");
    TopologyBuilder builder = new TopologyBuilder();

    builder.setSpout("spout12", new TestSpout2(), 1);
    builder.setBolt("bolt12", new TestBolt2(), 100).shuffleGrouping("spout12", "spout12Stream");
    builder.setSpout("spout11", new TestSpout1(), 1);
    builder.setBolt("bolt11", new TestBolt1(), 100).shuffleGrouping("spout11", "spout11Stream");

    Config conf = new Config();
    conf.setDebug(false);
    conf.setNumWorkers(4);
    LocalCluster cluster = new LocalCluster();

    cluster.submitTopology("TestTopology3", conf, builder.createTopology());

}


Spout1 :
public void nextTuple() {
    int a = (int) (((Math.random() * 10)+1)*((Math.random() * 10)+1));
    String str = String.valueOf(a);
    Utils.sleep(1000);
    collector.emit("spout11Stream", new Values(str), str);
}


Bolt1 : 
public void execute(Tuple tuple) {
    System.out.println("########## In execute of TestBolt11....\t Value 0 : " + tuple.getString(0) + "\t\t List : "
            + CommonUtils.list);
    _collector.ack(tuple);
}


Spout2 : 
public void nextTuple() {
    int a = (int) (((Math.random() * 10)+1)*((Math.random() * 10)+1));
    String str = String.valueOf(a);
    Utils.sleep(500);
    collector.emit("spout12Stream", new Values(str), str);
}


Bolt2 : 
public void execute(Tuple tuple) {
    System.out.println("!!!!!!!!!!!!! In execute of TestBolt12....\t Value 0 : " + tuple.getString(0));
    CommonUtils.list.add(tuple.getString(0)+"gb");
    _collector.ack(tuple);
}


CommonUtilis class : 
public final class CommonUtils {
public static List<String> list = new ArrayList<String>();
}

成功运行时的Sysout:

 !!!!!!!!!!!!! In execute of TestBolt12....  Value 0 : 31
 !!!!!!!!!!!!! In execute of TestBolt12....  Value 0 : 9
 !!!!!!!!!!!!! In execute of TestBolt12....  Value 0 : 68
 !!!!!!!!!!!!! In execute of TestBolt12....  Value 0 : 24
 ########## In execute of TestBolt11....     Value 0 : 39        List : [31gb, 9gb, 68gb, 24gb]
 !!!!!!!!!!!!! In execute of TestBolt12....  Value 0 : 60
 !!!!!!!!!!!!! In execute of TestBolt12....  Value 0 : 30
 ########## In execute of TestBolt11....     Value 0 : 26        List : [31gb, 9gb, 68gb, 24gb, 60gb, 30gb]
 !!!!!!!!!!!!! In execute of TestBolt12....  Value 0 : 9
 !!!!!!!!!!!!! In execute of TestBolt12....  Value 0 : 15
 ########## In execute of TestBolt11....     Value 0 : 11        List : [31gb, 9gb, 68gb, 24gb, 60gb, 30gb, 9gb, 15gb]

1 个答案:

答案 0 :(得分:0)

简短的回答是否定的,静态变量访问的范围是JVM,你可以指出几个JVM。

有一些解决方法,那些:

  1. 您可以使用并行度提示为1的螺栓来访问静态变量。由于只有一个螺栓,只能在一个JVM中进行访问,但是再次,您可能只需在该螺栓上使用一个实例变量。
  2. (1)的变体是在storm中使用调度程序实现来拥有你的bolt的多个实例,但是所有实例都分配给同一个worker。这种做法不是我尝试过的,但我还以为我会把它扔出去。
  3. 您可以使用数据库,关系数据库或NoSQL作为分布在群集中的数据的读/写存储
  4. 您可以将列表存储在zookeeper中。我将在单例类中包装zookeeper访问,以便使您的bolt实现更简单。