提交火花流式接收器时,如何在没有“失败”的情况下指定主机?

时间:2015-05-11 18:23:08

标签: scala apache-spark yarn spark-streaming

我想创建一个服务器套接字,以便在我提前知道ip和主机名的主机上进行监听(并在纱线节点列表中显示该主机名)。但我似乎无法让它在那个主机上听,而不会让它在事先失败任意次数。

有一个Flume receiver具有我正在寻找的主机特定功能。

FlumeUtils.createStream(streamingContext, [chosen machine's hostname], [chosen port])

我的收件人代码:

class TCPServerReceiver(hostname: String, port: Int)
  extends Receiver[String](StorageLevel.MEMORY_AND_DISK_2) with Logging {

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

  def onStop() {
  }

    private def receive() {
        /*  This is where the job fails until it happens to start on the correct host */
        val server = new ServerSocket(port, 50, InetAddress.getByName(hostname))

        var userInput: String = null
        while (true) {
            try {
                val s = server.accept()
                val in = new BufferedReader(new InputStreamReader(s.getInputStream()))

                userInput  = in.readLine()
                while (!isStopped && userInput != null) {
                    store(userInput)
                    userInput = in.readLine()
                }
            } catch {
                case e: java.net.ConnectException =>
                    restart("Error connecting to " + port, e)
                case t: Throwable =>
                    restart("Error receiving data", t)
            }
        }
    }
}

然后在它运行时进行测试:

echo 'this is a test' | nc <hostname> <port>

当我作为本地客户端运行时,这一切都有效,但是当它被提交到一个纱线集群时,日志显示它试图在不同主机上的其他容器中运行,并且所有这些都失败,因为主机名与容器:

java.net.BindException: Cannot assign requested address

最终(几分钟后),一旦接收器尝试在正确的主机上启动,它确实会创建套接字,因此上面的代码 工作,但需要大量的“启动时间”,我担心添加更多节点会导致更长时间!

有没有办法在第一次尝试时确保此接收器在正确的主机上启动?

1 个答案:

答案 0 :(得分:1)

自定义TCPServerReceiver实现也应该实现:

def preferredLocation: Option[String]
  

重写此选项以指定首选位置(主机名)。

在这种情况下,例如:

def preferredLocation = Some(hostname)