spark大批量讀取Hbase時出現java.lang.OutOfMemoryError: unable to create new native thread

zzzzMing發表於2018-10-11

這個問題我去網上搜尋了一下,發現了很多的解決方案都是增加的nproc數量,即使用者最大執行緒數的數量,但我修改了並沒有解決問題,最終是通過修改hadoop叢集的最大執行緒數解決問題的。
並且網路上的回答多數關於增加nproc的答案不完整,我這裡順便記錄一下。

使用者最大執行緒數可以通過linux下的命令

ulimit -a

檢視,螢幕輸出中的max user processes就是使用者最大執行緒數,預設通常為1024.

修改這個引數的地方是在/etc/security/limits.conf以及/etc/security/limits.d/90-nproc.conf(可能這個檔案的名字會不一樣)

/etc/security/limits.conf修改如下

* soft nofile 65536

* hard nofile 65536

xxx soft nproc 65535

xxx hard nproc 65535

其中 xxx表示啟動hbase的使用者,如使用hadoop啟動hbase,則配置如下:

hadoop hard nproc 65535

hadoop soft nproc 65535

這裡說明一下,noproc 是代表最大程式數,nofile 是代表最大檔案開啟數

然後,一般來說,修改ulimit的數值,只需要修改/etc/security/limits.conf即可,但是這個引數需要修改/etc/security/limits.d/90-nproc.conf。
至於為什麼需要修改這裡,可以看看這篇blog

在裡面新增

hadoop hard nproc 65535

hadoop soft nproc 65535

就修改成功啦。

但這個修改並沒有讓我的問題得到解決。我從java.lang.OutOfMemoryError入手,懷疑是否是Hbase或者是DataNode的Jvm程式記憶體不足導致記憶體溢位。於是使用jmap -heap命令分別檢視了各個節點的DataNode,確實發現了有一些DataNode的老年代佔有率過高,於是修改hadoop配置檔案HADOOP_HOME/etc/hadoop/hadoop-env.sh。在最後新增

export HADOOP_DATANODE_OPTS="-Xmx8192m -Xms256m -Dcom.sun.management.jmxremote $HADOOP_DATANODE_OPTS"

這個配置的作用是將DataNode的最大記憶體加到8G,在各個節點修改配置檔案,重啟DataNode。

再次啟動spark讀取hbase,確實有一點點改善,但最終還是會報錯。

這次我再去檢視了hadoop的日誌,發現了不一樣的錯誤,java.io.IOException: Premature EOF from inputStream。

再去網上查,發現其原因是檔案操作超租期,實際上就是data stream操作過程中檔案被刪掉了。通常是因為Mapred多個task操作同一個檔案,一個task完成後刪掉檔案導致。這個錯誤跟dfs.datanode.max.transfer.threads引數到達上限有關。這個是datanode同時處理請求的任務上限,總預設值是 4096,該引數取值範圍[1 to 8192]。

這不正是和unable to create new native thread有關嗎,繼續修改整個叢集,在HADOOP_HOME/etc/hadoop/hdfs-site.xml中增加以下配置

<property> 
<name>dfs.datanode.max.transfer.threads</name> 
<value>8192</value> 
</property>

再次啟動spark任務,操作成功!!




如果覺得對你有幫助,不如花0.5元請作者吃顆糖,讓他甜一下吧~~

spark大批量讀取Hbase時出現java.lang.OutOfMemoryError: unable to create new native thread

相關文章