簡體   English   中英

將Spark Streaming輸出寫入套接字

[英]Writing Spark Streaming Output to a Socket

我有一個DStream“Crowd”,我想把“Crowd”中的每個元素寫入套接字。 當我嘗試從該套接字讀取時,它不會打印任何東西。 我正在使用以下代碼行:

val server = new ServerSocket(4000,200);
val conn = server.accept()
val out = new PrintStream(conn.getOutputStream());
crowd.foreachRDD(rdd => {rdd.foreach(record=>{out.println(record)})})

但是如果使用(這不是我想要的):

crowd.foreachRDD(rdd => out.println(rdd)) 

它確實向套接字寫了一些內容。

我懷疑使用rdd.foreach()時出現問題。 雖然它應該工作。 我不確定我錯過了什么。

DStream閉包之外的代碼在驅動程序中執行,而rdd.foreach(...)將在RDD的每個分布式分區上執行。 因此,在驅動程序的機器上創建了一個套接字,並且該作業嘗試在另一台機器上寫入 - 這顯然不會起作用。

DStream.foreachRDD在驅動程序上執行,因此在該實例中,套接字和計算在同一主機中執行。 因此它有效。

由於RDD計算的分布式特性,這種服務器套接字方法很難實現,因為動態服務發現成為一個挑戰,即“我的服務器套接字在哪里打開?”。 查看一些允許您集中訪問分布式數據的系統。 Kafka是這種流媒體流程的一個很好的選擇。

crowd.foreachRDD(rdd => {rdd.collect.foreach(record=>{out.println(record)})})

您在評論中建議的代碼將正常工作,但在這種情況下,您必須收集驅動程序中RDD的所有記錄。 如果記錄數量很小就可以,但是如果記錄數量大於驅動程序的內存,那將成為瓶頸。 您的第一次嘗試應始終在客戶端處理數據。 記住RDD是在工作機器上分發的,這意味着首先需要將RDD中的所有記錄都帶到驅動程序中,從而增加通信,這在分布式計算中是一種殺戮。 如上所述,只有當RDD中的記錄有限時,您的代碼才會正常。

我正在研究類似的問題,我一直在搜索如何池連接並將它們序列化到客戶機。 如果某個機構對此有任何答案,那就太棒了。

在官方文檔中,您有答案!

您必須在foreachRDD函數內部創建連接,如果您想以最佳方式進行連接,則需要創建連接的“池”,然后在foreachPartition函數中引入所需的連接,並調用foreach函數通過該連接發送元素。 這是以最佳方式執行此操作的示例代碼:

dstream.foreachRDD { rdd =>
  rdd.foreachPartition { partitionOfRecords =>
    // ConnectionPool is a static, lazily initialized pool of connections
    val connection = ConnectionPool.getConnection()
    partitionOfRecords.foreach(record => connection.send(record))
    ConnectionPool.returnConnection(connection)  // return to the pool for future reuse
  }
}

在任何情況下,請檢查其他注釋,因為它們提供了有關問題上下文的良好知識。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM