進程數限制導致的線上問題

先來了解下Linux系統的最大線程數限制的參數有哪些:

  • /proc/sys/kernel/threads-max:內核所能使用的線程的最大數目,由物理內存決定,32G內存的默認值爲255928。
  • /proc/sys/vm/max_map_count:限制一個進程可以擁有的VMA(虛擬內存區域)的數量,默認值爲65530。
  • ulimit -u:單個用戶允許的最大進程或線程上限,默認root用戶不限制,其他用戶爲4096。
  • /proc/sys/kernel/pid_max:操作系統線程數限制。爲了兼容舊版(舊版本32位操作系統的最大值爲32768),默認爲32768。PS:其實64位操作系統最多可以設置爲2^22,400多萬。

問題出現前這些參數的實際值

在問題出現之前,ulimit -u的已經調整到了404800,其他的都爲默認值。

問題描述

xshell連接服務器時報錯:fork:cannot allocate memory

解決過程

其實這個報錯直接就可以定位到是pid_max的問題。

查詢當前整個系統已用的線程或進程數:

$ pstree -p | wc -l
32602

###這是問題解決之後查的,問題產生時的值應該比32768略小些。

問題已經很明確了,就是pid_max的值不夠大造成的。

知道了問題,那就好辦了,直接修改/proc/sys/kernel/pid_max的值:

#臨時生效
$ echo 1000000 > /proc/sys/kernel/pid_max

#永久生效
$ echo "kernel.pid_max=1000000 " >> /etc/sysctl.conf
$ sysctl -p

修改之後,xshll可以登錄了。

其實這中間還是蠻曲折的:在執行命令的時候,一直報fork:cannot allocate memory,沒辦法,只能一直試,後來總算能勉強執行命令了。但是當時是用非root用戶登錄的,命令需要用root用戶執行,在su - root時,也是一直報這個錯。然後嘗試了阿里雲UI中的vnc遠程登錄也是如此。沒辦法,只能將一個相對不那麼重要的服務先kill掉,然後再切到root用戶執行上面的命令。

思考

雖然這臺主機中跑了比較多(二十幾個)的java模塊,但是3萬多的線程數,平均一個模塊要產生1000+的線程?我的預感是這其中應該有某個(些)模塊產生了異常多的線程。

寫個腳本驗證下:

#!/bin/bash
for pid in `jps | awk '{print $1}'`
do 
  num=`pstree -p $pid | wc -l`
  echo $pid
  echo $num
  echo " "
done

執行結果:

$ ./check_thread.sh 
21056
105
 
15170
162
 
20355
70
 
20422
65
 
9611
144
 
31180
203
 
6029
64
 
22606
183
 
21011
260
 
14932
148
 
21464
175
 
14491
87
 
22747
64
 
1819
99
 
10971
155
 
46556
119
 
9886
47
 
7007
146
 
20707
166
 
21285
81
 
6572
150
 
22318
75
 
9970
59
 
10099
36
 
51827
0
 
9973
54
 
6646
73
 
5047
29228
 
20026
181
 
33087
63

可以看到pid爲5047的進程產生了29228個線程,然後根據pid就可以直接找到這個模塊了。

解決

第二天上班之後,跟負責這個模塊的開發人員反映了這個問題。在一番仔細的查看代碼之後,終於是找到了問題的根本所在—連接solr的http連接一直沒有關閉導致的。

知道問題所在之後,解決起來就很快了。

至此,一個線上的線程數暴增的問題順利得到了解決。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章