背景:近期在配置mysql集群,集群配置好后,也进行了mysql的调优等方面的工作,但是在并发测试的时候还是会出现too many open files 错误,思考了下,其瓶颈不在于mysql本身,而是其负载的linux服务器,然后网上查了一些前辈们的资料,大概整理了一下linux服务器的配置信息;
句柄的调整 linux的设计中,遵循的是一切皆文件的理念;当打开tcp连接,其实对于服务器来说是打开了多少句柄数,句柄数量的大小决定了linux服务器对外提供的TCP连接的数量;
查看当前服务器设置的句柄的数量
# ulimit -n
1024
查看服务器设置句柄相关的配置信息
# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 30
file size (blocks, -f) unlimited
pending signals (-i) 30605
max locked memory (kbytes, -l) 40000
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 65
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 30605
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
下面大概提供了三种修改Linux系统的最大文件句柄数限制的方法:
1.针对当前session有效,用户退出或者系统重新后恢复默认值
# ulimit -n 65535
2.只对单个用户有效; 修改 profile文件:在 profile文件中添加:ulimit -n 65535
3.永久生效
修改文件:/etc/security/limits.conf
* soft nofile 32768 #限制单个进程最大文件句柄数(到达此限制时系统报警)
* hard nofile 65536 #限制单个进程最大文件句柄数(到达此限制时系统报错)
根据上面的方法设置了句柄的数量,保证了服务器对外提供的TCP连接的数量;
下面进行简单的测试:
获取linux服务器中mysql服务的进程ID
# ps aux| grep mysql
通过上一步获取的进程ID,然后查看mysql服务占用的句柄
# lsof -n | grep 6662 -c
查看当前服务器中所有的进程打开的句柄数的列表
# lsof -n|awk '{print $2}'|sort|uniq -c|sort -nr
比如,结果 111 6662
其中第一列是打开的句柄的数量,第二列是进程ID(PS:打开可能比较慢)
上面的调整结束后只能保证对外提供的tcp连接上限变大,若是存在某个连接一直处于TIME_WAIT或者ESTABLISHED的情况下,那么句柄数则不是唯一的瓶颈了,因为TCP/IP连接断开后,会以TIME_WAIT状态保留一定的时间,然后才会释放端口。当并发请求过多的时候,就会产生大量的 TIME_WAIT状态的连接,无法及时断开的话,会占用大量的端口资源和服务器资源(因为关闭后进程才会退出)。这个时候我们可以考虑优化TCP/IP 的内核参数,来及时将TIME_WAIT状态的端口清理掉。
查看连接数:
# netstat -anp |grep mysql |wc -l 查看mysql占用的连接数
# netstat -anp |grep TIME_WAIT|wc -l 查看连接数等待time_wait状态连接数
# netstat -anp |grep ESTABLISHED |wc -l 查看建立稳定连接数量
# netstat -anp |grep mysql |grep TIME_WAIT|wc -l 查看mysql建立连接的数量
可以发现有大量的time_wait的状态
调整linux服务器内核中time_wait的时间
vim /etc/sysctl.conf
#编辑文件,加入以下内容:
net.ipv4.tcp_syncookies = 1 当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭;
net.ipv4.tcp_fin_timeout = 30 修改系統默认的 TIMEOUT 时间。
#然后执行 /sbin/sysctl -p 让参数生效。
重启机器,然后再次进行压测,监控下对应的数据变化;