Error现象
linux连接socket错误 11: Resource temporarily unavailable
常见于Redis、MySQL、PHP-fpm这些应用连接socket时出现错误。
一般系统处于高负载时会出现Error,导致服务不可用。例如使用Nginx代理时,业务出现502 Bad Gateway,常见如下日志:
... [error] 10615#0: *172810754 connect() to unix:/xxx/www.sock failed (11: Resource temporarily unavailable) while connecting to upstream ...
定位原因
系统net.core.somaxconn值过低导致backlog不够用。
原理
net.core.somaxconn是Linux中的一个内核(kernel)参数,表示socket监听(listen)的backlog上限。学习更多:https://www.cnblogs.com/my-show-time/p/15206020.html
对于一个TCP链接,Server与Client需要通过三次握手来建立网络链接,当三次握手成功之后,我们就可以看到端口状态由LISTEN转为ESTABLISHED,接着这条链路上就可以开始传送数据了
net.core.somaxconn是Linux中的一个内核(kernel)参数,表示socket监听(listen)的backlog上限。
什么是backlog?backlog就是 socket的监听队列,当一个请求(request)尚未被处理或者建立时,它就会进入backlog。
而socket server可以一次性处理backlog中的所有请求,处理后的请求不再位于监听队列中。
当Server处理请求较慢时,导致监听队列被填满后,新来的请求就会被拒绝。
backlog参数主要用于底层方法int listen(int sockfd, int backlog), 在解释backlog参数之前,我们先了解下tcp在内核的请求过程,其实就是tcp的三次握手:
1.client发送SYN到server,将状态修改为SYN_SEND,如果server收到请求,则将状态修改为SYN_RCVD,并把该请求放到syns queue队列中。
2.server回复SYN+ACK给client,如果client收到请求,则将状态修改为ESTABLISHED,并发送ACK给server。
3.server收到ACK,将状态修改为ESTABLISHED,并把该请求从syns queue中放到accept queue。
在linux系统内核中维护了两个队列:syns queue和accept queue
syns queue
用于保存半连接状态的请求,其大小通过/proc/sys/net/ipv4/tcp_max_syn_backlog指定,一般默认值是512,不过这个设置有效的前提是系统的syncookies功能被禁用。互联网常见的TCP SYN FLOOD恶意DOS攻击方式就是建立大量的半连接状态的请求,然后丢弃,导致syns queue不能保存其它正常的请求。accept queue
用于保存全连接状态的请求,其大小通过/proc/sys/net/core/somaxconn指定,在使用listen函数时,内核会根据传入的backlog参数与系统参数somaxconn,取二者的较小值。
如果accpet queue队列满了,server将发送一个ECONNREFUSED错误信息Connection refused到client。
解决方法
Linux系统net.core.somaxconn默认值128,查看方法如下
sysctl net.core.somaxconn
调高该值
立即修改
sysctl -w net.core.somaxconn=65535
配置文件修改
echo "net.core.somaxconn=65536" >> /etc/sysctl.conf sysctl -p
重启相关服务,比如Redis、MySQL、PHP-fpm,业务恢复正常。