我看到很多代码片段在Spout.nextTuple()
中使用了一个循环(例如,读取整个文件并为每一行发出一个元组):
public void nextTuple() {
// do other stuff here
// reader might be BufferedReader that is initialized in open()
String str;
while((str = reader.readLine()) != null) {
_collector.emit(new Values(str));
}
// do some more stuff here
}
这段代码似乎是直截了当的,然而,我被告知在nextTuple()
内应该不循环。问题是为什么?
答案 0 :(得分:5)
执行Spout时,它在单个线程中运行。这个线程“永远”循环,并有多个职责:
Spout.nextTuple()
为了实现这一点,必须在nextTuple()
中保持“永久”(即循环或阻止),但在向系统发出元组后返回(或者如果没有元组可以返回则返回)被发射,但不阻止)。否则,Spout无法正常工作。 Storm会在一个循环中调用nextTuple()
。因此,在处理了ack / fail消息等之后,对nextTuple()
的下一次调用很快就会发生。
因此,在nextTuple()
的单个调用中发出多个元组也被认为是不好的做法。只要代码保留在nextTuple()
中,spout线程就不能(例如)对传入的ack作出反应。这可能会导致不必要的超时,因为无法及时处理。
最佳做法是为每次调用nextTuple()
发出一个元组。如果没有可用的元组发出,你应该返回(不发出)而不要等到元组可用。