我制作了一个简单的日志记录,但似乎忘记了构造函数中提供的名称。此外,似乎构造函数以某种方式被绕过,因为当我向它添加一些日志代码时,它不会记录任何内容。
Apache Storm在某些时候是否对螺栓做了一些奇怪的事情?
public class SimpleLoggingBolt extends BaseBasicBolt {
private static final Logger LOG = LogManager.getRootLogger();
private static String loggingBoltName;
public SimpleLoggingBolt(String name) {
super();
LOG.info("This does not log anything")
loggingBoltName = name;
}
@Override
public void execute(Tuple input, BasicOutputCollector collector) {
LOG.info("Bolt {} received tuple: {}", loggingBoltName, input);
// Loga "Bolt null received tuple..."
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {}
答案 0 :(得分:1)
执行bolt的构造函数的JVM与运行execute
方法的JVM不同。
当您使用storm jar
提交拓扑时,Nimbus会启动一个运行拓扑连接代码的新JVM(使用TopologyBuilder并调用StormSubmitter的部分)。这包括运行bolt的构造函数。我相信这个JVM只是记录到你用来运行storm jar
的终端,这就是你没有看到日志的原因。
提交并验证拓扑后,它会被序列化并通过网络发送给运行主管的主机(您运行的计算机storm supervisor
)。假设主管被分配来运行您的一个螺栓实例。它将启动一个单独的“worker”JVM,它将运行你的bolt(可能还有一些其他组件)。工作者JVM是实际工作发生的地方,也是运行execute
的地方。
所以正在发生的事情是你的静态loggingBoltName
在storm jar
JVM中被初始化,bolt被序列化,当它在worker JVM中被反序列化时,静态字段再次为null,因为静态字段未序列化。
如果要保留字段值,则不应将字段声明为static。如果该字段可以序列化,并且不是static
或transient
,那么一旦在工作程序中反序列化了螺栓,它将保留您在构造函数中设置的值。