1. 程式人生 > >mongo連接數滿問題處理

mongo連接數滿問題處理

登錄 lsof ase 文件中 線程 sof rep 資源 本地

記一次mongo服務端無法建立更多連接造成的客戶端無法訪問mongo集群的故障分析及解決

一. 問題:

程序無法連接mongo集群

現象:

2017-09-05T01:29:08.765+0000 I NETWORK  [thread2] connection refused because too many open connections: 819

二. 排查及解決

1. 本地測試訪問mongo主機及端口

telnet 192.168.1.100 20000

正常訪問,端口存在

2. 登陸mongo主機查看進程和端口是否存在。

查看進程

ps -ef | grep mongo

查看端口

netstat -ntlp

確認進程和端口都正常運行

3. 查看日誌

tail -f /data/mongodb/log/mongos.log

技術分享

從log文件中可以看出connection refused because too many open connections: 819,不能建立更多的連接造成,mongo服務端主動拒絕,造成客戶端無法訪問。於是想到系統允許進程打開的的最大文件具柄數的限制。

三. 分析解決

1. 查看系統默認的最大文件句柄數,系統默認是1024

# ulimit -n
1024
參數:
命令參數
-a 顯示所有限制
-c core文件大小的上限
-d 進程數據段大小的上限
-f shell所能創建的文件大小的上限
-m 駐留內存大小的上限
-s 堆棧大小的上限
-t 每秒可占用的CPU時間上限
-p 管道大小
-n 打開文件數的上限
-u 進程數的上限
-v 虛擬內存的上限

2. 查看當前進程打開了多少句柄數

# lsof -n|awk ‘{print $2}‘|sort|uniq -c|sort -nr|more
14505 2684
13937 2781
12992 2492
11616 2361
10486 2583
#其中第一列是打開的句柄數,第二列是進程ID。
根據進程PID查看進程名
# ps -ef | grep 2684
mongodb   2684     1  0 04:19 ?        00:00:38 mongod -f /data/mongodb/config/shard2.conf

3. 什麽是ulimit -n

網上很多人說,ulimit -n限制用戶單個進程的問價打開最大數量。嚴格來說,這個說法其實是錯誤的。看看ulimit官方描述:
Provides control over the resources available to the shell and to processes started by  it,  on  systems that allow such control. The -H and -S options specify that the hard or soft limit is set for the given resource. A hard limit cannot be increased once it is set; 
a soft limit may be increased up to the value of the hard limit. If neither -H nor -S is specified, both the soft and hard limits are set. The value of limit can be a number in the unit specified for the resource or one of the special values hard, soft, or unlimited,
which stand for the current hard limit, the current soft limit, and no limit, respectively.If limit is omitted, the current value of the soft limit of the resource is printed, unless the -H option is given. When more than one resource is specified, the limit name and unit are printed before the value.
人家從來就沒說過是限制用戶的單個進程的最大文件打開數量,看看紅色部分,是限制當前shell以及該shell啟動的進程打開的文件數量。為什麽會給人限制單個線程的最大文件數量的錯覺,因為很多情況下,在一個shell環境裏,雖然可能會有多個進程,但是非常耗費文件句柄的進程不會很多,只是其中某個進程非常耗費文件句柄,比如服務器上運行著一個tomcat,那麽就是java進程要占用大多數文件句柄。此時ulimit設置的最大文件數和java進程耗費的最大文件數基本是對應的,所以會給人這樣的一個錯覺。
還有,很多文章稱ulimit -n 只允許設置得越來越小,比如先執行了ulimit -n 1000,在執行ulimit -n 1001,就會報"cannot modify limit: Operation not permitted"錯誤。這個其實也是不準確的說法。首先要搞清楚,任何用戶都可以執行ulimit,但root用戶和非root用戶是非常不一樣的。
註: 非root用戶只能越設置越小,不能越設置越大,root用戶不受限制

4. 到底最大文件數被什麽限制了?too many open files錯誤到底可以通過什麽參數控制?

shell級限制
通過ulimit -n修改,如執行命令ulimit -n 1000, 當前session會話生效,則表示將當前shell的當前用戶所有進程能打開的最大文件數量設置為1000.

用戶級限制
ulimit -n是設置當前shell的當前用戶所有進程能打開的最大文件數量,但是一個用戶可能會同時通過多個shell連接到系統,所以還有一個針對用戶的限制,通過修改 /etc/security/limits.conf實現,例如,往limits.conf輸入以下內容:
root soft nofile 1000
root hard nofile 1200
soft nofile表示軟限制,hard nofile表示硬限制,軟限制要小於等於硬限制。上面兩行語句表示,root用戶的軟限制為1000,硬限制為1200,即表示root用戶能打開的最大文件數量為1000,不管它開啟多少個shell。

系統級限制

# cat /proc/sys/fs/file-max
1637385
ulimit修改後生效周期 修改後立即生效,重新登錄進來後失效,因為被重置為limits.conf裏的設定值。 修改了limits.conf需要重啟系統? 重新登錄進來就生效了。

5. 文件/proc/sys/fs/file-max

網上說,ulimit -n 和limits.conf裏最大文件數設定不能超過/proc/sys/fs/file-max的值,這也是搞笑了,/proc/sys/fs/file-max是系統給出的建議值,系統會計算資源給出一個和合理值,一般跟內存有關系,內存越大,改值越大,但是僅僅是一個建議值,limits.conf的設定完全可以超過/proc/sys/fs/file-max。

6. 修改limit限制

#  在文件末尾添加,永久生效
# vim /etc/security/limits.conf
mongodb                soft    nofile  100000
mongodb                hard    nofile  100000

# 切換到mongodb用戶下查看
# ulimit -n 
100000

重啟mongo後,故障恢復!

四. 總結

  • /proc/sys/fs/file-max限制不了/etc/security/limits.conf
  • 只有root用戶才有權限修改/etc/security/limits.conf
  • 對於非root用戶, /etc/security/limits.conf會限制ulimit -n,但是限制不了root用戶
  • 對於非root用戶,ulimit -n只能越設置越小,root用戶則無限制
  • 任何用戶對ulimit -n的修改只在當前環境有效,退出後失效,重新登錄新來後,ulimit -n由limits.conf決定
  • 如果limits.conf沒有做設定,則默認值是1024
  • 當前環境的用戶所有進程能打開的最大文件數量由ulimit -n決定

mongo連接數滿問題處理