Spark Streaming:在接收器发生故障后如何不重新启动接收器

时间:2016-05-31 21:48:56

标签: apache-spark spark-streaming distributed-computing terminate custom-receiver

我们正在使用自定义的火花接收器,它从提供的http链接中读取流数据。如果提供的http链接不正确,则接收方失败。问题是spark会不断重启接收器,应用程序永远不会终止。问题是如果接收器发生故障,如何告诉Spark终止应用程序。

这是我们自定义接收器的摘录:

 def onStart() {
    // Start the thread that receives data over a connection
    new Thread("Receiver") {
      override def run() { receive() }
    }.start()
  }

  private def receive(): Unit = {
    ....
    val response: CloseableHttpResponse = httpclient.execute(req)
    try {
      val sl = response.getStatusLine()
      if (sl.getStatusCode != 200){
        val errorMsg = "Error: " + sl.getStatusCode 
        val thrw = new RuntimeException(errorMsg)
        stop(errorMsg, thrw)
      } else {
      ...
        store(doc)
      }

我们有一个使用此接收器的火花流应用程序:

val ssc = new StreamingContext(sparkConf, duration)
val changes = ssc.receiverStream(new CustomReceiver(...
...
ssc.start()
ssc.awaitTermination()

如果接收器没有错误,一切都按预期工作。如果接收器发生故障(例如,使用错误的http链接),spark将不断重启它,应用程序将永远不会终止。

16/05/31 17:03:38 ERROR TaskSetManager: Task 0 in stage 0.0 failed 1 times; aborting job
16/05/31 17:03:38 ERROR ReceiverTracker: Receiver has been stopped. Try to restart it.

如果接收器出现故障,我们只想终止整个应用程序。

2 个答案:

答案 0 :(得分:2)

有一种方法可以控制基于Custom接收器的火花流应用程序的生命周期。为您的应用程序定义作业进度监听器,并跟踪发生的情况。

class CustomReceiverListener extends StreamingJobProgressListener {
    private boolean receiverStopped = false;

    public CustomReceiverListener(StreamingContext ssc) { super(ssc);}

    public boolean isReceiverStopped() {
        return receiverStopped;
    }
    @Override
    public void onReceiverStopped(StreamingListenerReceiverStopped receiverStopped) {
        LOG.info("Update the flag field");
        this.receiverStopped = true;
    }
}

在您的驱动程序中,初始化一个线程以监视receiverStopped标志的状态。此线程完成后,驱动程序将停止流应用程序。 (更好的方法是定义驱动程序定义的回调方法,这将停止流应用程序)。

CustomReceiverListener listener = new CustomReceiverListener(ssc);
ssc.addStreamingListener(listener);
ssc.start();
Thread thread = new Thread(() -> {
    while (!listener.isReceiverStopped()) {
        LOG.info("Sleepy head...");
        try {
            Thread.sleep(2 * 1000); /*check after 2 seconds*/
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
});
thread.start();
thread.join();
LOG.info("Listener asked to die! Going to commit suicide :(");
ssc.stop(true, false);

注意:如果您的接收器有多个实例,请更改CustomReceiverListener的实现以确保所有接收器实例都已停止。

答案 1 :(得分:0)

似乎Spark Streaming中的调度工作方式是ReceiverTracker将继续重启失败的接收器,直到ReceiverTracker没有自行停止。

https://github.com/apache/spark/blob/master/streaming/src/main/scala/org/apache/spark/streaming/scheduler/ReceiverTracker.scala#L618

要停止ReceiverTracker,我们需要停止整个应用程序。因此,似乎没有办法从接收器本身控制这个过程。