我为什么不在Spout.nextTuple()

时间:2015-09-13 08:47:55

标签: apache-storm

我看到很多代码片段在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()内应该不循环。问题是为什么?

1 个答案:

答案 0 :(得分:5)

执行Spout时,它在单个线程中运行。这个线程“永远”循环,并有多个职责:

  1. 致电Spout.nextTuple()
  2. 检索“acks”并处理它们
  3. 检索“失败”并处理它们
  4. 超时元组
  5. 为了实现这一点,必须在nextTuple()中保持“永久”(即循环或阻止),但在向系统发出元组后返回(或者如果没有元组可以返回则返回)被发射,但不阻止)。否则,Spout无法正常工作。 Storm会在一个循环中调用nextTuple()。因此,在处理了ack / fail消息等之后,对nextTuple()的下一次调用很快就会发生。

    因此,在nextTuple()的单个调用中发出多个元组也被认为是不好的做法。只要代码保留在nextTuple()中,spout线程就不能(例如)对传入的ack作出反应。这可能会导致不必要的超时,因为无法及时处理。

    最佳做法是为每次调用nextTuple()发出一个元组。如果没有可用的元组发出,你应该返回(不发出)而不要等到元组可用。