dstream.foreachRDD { rdd =>
val connection = createNewConnection() // executed at the driver
rdd.foreach { record =>
connection.send(record) // executed at the worker
}
}
connection連接對象會被序列化,並會從driver端發送到worker端。
可能會出現兩種錯誤:
1、序列化錯誤:conncetion對象不是序列化的對象,會出現序列化的錯誤。
2、初始化錯誤:connection對象在worker端會被初始化。
解決辦法:在worker端,創建connection對象。
第一種方案(嚴重不好):
dstream.foreachRDD { rdd =>
rdd.foreach { record =>
val connection = createNewConnection()
connection.send(record)
connection.close()
}
}
問題:會在每條record中,創建一個新的connection對象。
第二種方案(較好):
dstream.foreachRDD { rdd =>
rdd.foreachPartition { partitionOfRecords =>
val connection = createNewConnection()
partitionOfRecords.foreach(record => connection.send(record))
connection.close()
}
}
在rdd中的每個partition中創建一個connection對象,並在當前partition中的所有記錄中使用當前的connection對象。
第三種方案(相當好):
dstream.foreachRDD { rdd =>
rdd.foreachPartition { partitionOfRecords =>
val connection = ConnectionPool.getConnection() // ConnectionPool is a static, lazily initialized pool of connections
partitionOfRecords.foreach(record => connection.send(record))
ConnectionPool.returnConnection(connection) // return to the pool for future reuse
}
}
在多個批次的rdd中重用connection對象。創建一個connection的連接池
注意:連接池中的connection是在需要的時候創建,一段時間不使用後超時。