我想创建一个服务器套接字,以便在我提前知道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
最终(几分钟后),一旦接收器尝试在正确的主机上启动,它确实会创建套接字,因此上面的代码 工作,但需要大量的“启动时间”,我担心添加更多节点会导致更长时间!
有没有办法在第一次尝试时确保此接收器在正确的主机上启动?
答案 0 :(得分:1)
自定义TCPServerReceiver
实现也应该实现:
def preferredLocation: Option[String]
重写此选项以指定首选位置(主机名)。
在这种情况下,例如:
def preferredLocation = Some(hostname)