foreachRDD常見問題

問題代碼如下;
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是在需要的時候創建,一段時間不使用後超時。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章