前言



某天当prometheus添加到大致2500个指标(Targets)时,prometheus开始出现了打开缓慢,无法重新加载配置文件,并且服务偶尔会挂掉的现象.于是进行了对这个问题进行了处理.



报错



查看服务日志和系统日志

systemctl status prometheus
journalctl -u prometheus
tail -f /var/log/messages
msg="Scrape commit failed" err="write to WAL: log samples: create new segment file: open /data/prometheus/wal/00007563: too many open files"

这几个日志都包含Too many open files



原因及处理



上面的报错通常是由于limit设置导致,
系统或某进程 在某个时刻打开了超过系统限制的文件数量以及通讯链接数



<1>查看系统的limit设置

ulimit -n
(open files  系统通常默认为1024)

prometheus 清除數據 prometheus内存占用过大_文件描述符


or

cat /etc/security/limits.conf

*           soft   nofile       102400    ##任何用户可以打开的最大的文件描述符数量,默认1024
*           hard   nofile       102400
*           soft   nproc        102400    #任何用户可以打开的最大进程数
*           hard   nproc        102400


由上可知参数相当大,已经是系统调优过了





<2>查看该进程的文件句柄数

查询prometheus进程pid
ps aux |grep prometheus
cat  /proc/<pid>/limits

Limit                     Soft Limit           Hard Limit           Units     
Max cpu time              unlimited            unlimited            seconds   
Max file size             unlimited            unlimited            bytes     
Max data size             unlimited            unlimited            bytes     
Max stack size            8388608              unlimited            bytes     
Max core file size        0                    unlimited            bytes     
Max resident set          unlimited            unlimited            bytes     
Max processes             256486               256486               processes 
Max open files            1024                 1024                files     
Max locked memory         65536                65536                bytes     
Max address space         unlimited            unlimited            bytes     
Max file locks            unlimited            unlimited            locks     
Max pending signals       256486               256486               signals   
Max msgqueue size         819200               819200               bytes     
Max nice priority         0                    0                    
Max realtime priority     0                    0                    
Max realtime timeout      unlimited            unlimited            us

由上可知,当前进程的最大打开文件数较低,应该调这个就可以了



<3>查看系统中进程打开文件数的排序(或查看该进程的已打开文件数)
(Centos6使用)

lsof -n |awk '{print $2}'|sort|uniq -c |sort -nr|more 

or

lsof -n |awk '{print $2}'|sort|uniq -c |sort -nr|more |grep <pid>


在Centos7及其以上版本,通过lsof统计的文件句柄数比Centos7以下系统高很多倍,
是lsof的版本不同造成的,新版本的lsof 默认打印TID(-K 参数),因此上方的命令建议在Centos6中使用

lsof -p <pid> |wc -l          是统计某个进程打开的文件句柄数
lsof -n|grep <pid> |wc -l     是统计某个进程及其所有线程打开的文件句柄数


<4>统计多少文件被某进程打开
(Centos7使用)

lsof -p <pid> |wc -l
or
ls /proc/<pid>/fdinfo/ | grep '^[0-9]'| wc


<5>调整该服务的limit
由于配置的systemctl的管理方式,修改service文件,并重新加载即可
通常在/etc/systemd/system/ 或 /usr/lib/systemd/system/

cat  /usr/lib/systemd/system/prometheus.service 
[Unit]
Description=Prometheus Node Exporter
After=network.target
 
[Service]
ExecStart=/data/prometheus/prometheus --config.file=/data/prometheus/prometheus.yml --storage.tsdb.path=/data/prometheus --web.read-timeout=5m  --web.max-connections=100 --storage.tsdb.retention=10d --query.max-concurrency=20 --query.timeout=2m --web.enable-lifecycle
User=root
LimitNOFILE=10240

[Install]
WantedBy=multi-user.target



systemctl daemon-reload
systemctl restart prometheus


系统limit调优补充



<1>资源限制配置文件
cat /etc/security/limits.conf

#当前shell该用户能打开的最大文件数
*           soft   nofile       102400
*           hard   nofile       102400
#当前shell该用户所能创建的最大进程数
*           soft   nproc        102400
*           hard   nproc        102400


nofile的值的上限是由/proc/sys/fs/nr_open限制的,默认是1048576
如果你修改limit.conf的nofile,超过这个值就会导致连接ssh失败


---------------------------------------------------------------


<2>当前系统使用的打开文件描述符数
cat /proc/sys/fs/file-nr
3072	                          0	                                          794326
系统已分配使用的打开文件描述符数     第二个数为分配后已释放的(目前已不再使用)      内核可分配最大文件描述符数(file-max)

---------------------------------------------------------------


<3>系统内核最大可分配文件描述符数
cat /proc/sys/fs/file-max
6815744

临时修改方法:
sysctl -w “fs.file-max=6553560”
永久修改file-max的值
vi /etc/sysctl.conf添加
fs.file-max = 6553560

---------------------------------------------------------------

<4>单个进程可分配的最大文件数
cat /proc/sys/fs/nr_open
1048576

临时修改方法:
sysctl -w “fs.nr_open=1048576”
永久修改file-max的值
vi /etc/sysctl.conf添加
fs.nr_open=1048576

---------------------------------------------------------------


<5>总结

file-max的值要大于nr_open,nr_open单进程最大能配置的文件数量不能大于file-max 

所有进程打开的文件描述符数不能超过/proc/sys/fs/file-max

单个进程打开的文件描述符数不能超过user limit中nofile的soft limit

nofile的soft limit不能超过其hard limit

nofile的hard limit不能超过/proc/sys/fs/nr_open