2015-12-23 100 views
3

我正在使用Java中的newAPIHadoopRDD來讀取MongoDB集合。 首先,我創建使用下面的類JavaSparkContext對象:如何在使用Java中的newAPIHadoopRDD讀取MongoDB集合之後停止線程?

public class SparkLauncher { 
    public JavaSparkContext javaSparkContext ; 

    public SparkLauncher() 
    { 
     javaSparkContext = null; 
    } 

    public JavaSparkContext getSparkContext() { 
     if (javaSparkContext == null) { 
      System.out.println("SPARK INIT..."); 
      try { 
       System.setProperty("spark.executor.memory", "2g"); 
       Runtime runtime = Runtime.getRuntime(); 
       runtime.gc(); 
       int numOfCores = runtime.availableProcessors();     
       numOfCores=3;    
       SparkConf conf = new SparkConf(); 
       conf.setMaster("local[" + numOfCores + "]"); 
       conf.setAppName("WL");     
       conf.set("spark.serializer", 
         "org.apache.spark.serializer.KryoSerializer"); 
        javaSparkContext = new JavaSparkContext(conf);     
      } catch (Exception ex) { 
       ex.printStackTrace(); 
      } 
     } 
     return javaSparkContext; 
    } 

    public void closeSparkContext(){ 
     javaSparkContext.stop(); 
     javaSparkContext.close(); 
     javaSparkContext= null;  
    } 
} 

然後,在其他類我讀了MongoDB的集合:

SparkLauncher sc = new SparkLauncher(); 
JavaSparkContext javaSparkContext = sc.getSparkContext(); 

try { 
     interactions = javaSparkContext.newAPIHadoopRDD(mongodbConfig, 
     MongoInputFormat.class, Object.class, BSONObject.class); 
    } 
catch (Exception e) { 
     System.out.print(e.getMessage()); 
    } 

此代碼創建了很多線程讀取集合的分裂的。關閉JavaSparkContext對象後:

javaSparkContext.close(); 
sc.closeSparkContext(); 
System.gc(); 

所有線程仍處於活動狀態且內存未釋放。它會導致內存泄漏和線程泄漏。這是因爲newAPIHadoopRDD方法嗎?有沒有辦法擺脫這些線程?

這裏是線程的一部分快照仍然活着: enter image description here

下面是使用jconsole程序的內存使用情況: enter image description here

最後在Eclipse內存分析器泄漏嫌疑人: enter image description here

+0

你怎麼知道*「的所有線程都還活着,內存不會被釋放。」 *?你如何測量/追蹤它?幾個截圖可以幫助你看到你看到和參考。 –

回答

1

有似乎是一個connection leakage problem與蒙戈 - Hadoop的。在運行一個從mongodb流式傳輸數據的示例代碼之後,我可能會遇到同樣的問題。

它似乎與最新版本1.4.2修復,它在我的示例代碼中工作正常。 改變你的Maven依賴關係:

<dependency> 
    <groupId>org.mongodb.mongo-hadoop</groupId> 
    <artifactId>mongo-hadoop-core</artifactId> 
    <version>1.4.2</version> 
</dependency> 
+0

這是我的問題的解決方案。謝謝卓然。 –

+0

因此,處理這些奇怪問題的最佳方法是檢查POM文件中的軟件包版本,並始終嘗試使用它們的最新版本。 –

0

我不使用MongoDB和Spark,很可能不能完全回答你的問題,但我沒有幾個可能導致解決方案的意見。

  • System.setProperty("spark.executor.memory", "2g")不影響你的星火環境,因爲你使用local模式,內存爲一個且只有一個執行量的內存分配給應用程序在啓動時的量(和不能改變)。

您最好不要移除該行或切換到其他Spark部署環境,例如,獨立,YARN或Mesos。

  • 的註釋同樣適用於conf.set("spark.executor.instances", "10"),因爲只能有最多runtime.availableProcessors()numOfCores線程啓動任務。畢竟,在只有一個JVM的情況下,您最好使用local模式,並且任務執行的線程數最多爲Runtime.getRuntime().availableProcessors()

Spark所使用的線程最終會被釋放。他們所屬的線程池已被關閉,作爲SparkContext.stop的一部分(在您的示例中沒有看到它被調用,但由於我使用Scala API,因此可能存在差異)。

+0

感謝您的回覆。 –

+0

我添加了一些顯示場景的圖像(第一個和第二個圖像在運行停止命令後與之相關)。關於你的帖子中提到的其他設置你是對的,但他們不是問題的原因。 –

0

我做了另一個實驗。這一次,我只寫了一個簡單的代碼,使用相同的方法在15次迭代循環中讀取Mongo集合。在循環結束時,我還打電話給System.gc()以防萬一。

下面是此代碼的jconsole輸出,它顯示了運行期間積累的線程。 enter image description here

我還實施使用MongoDB的API和無newAPIHadoopRDD上另一個集合的代碼(見下表): enter image description here 過了一會的存儲器使用量變得固定。 但看到內存使用情況和線程,當我用newAPIHadoopRDD讀同一個集合: enter image description here