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,業務恢復正常。