笔者用 haproxy 来做 mqtt 负载均衡。在做 5w 连接的压测。发现到 3w 多一点的时候,haproxy 就出现 no free port 问题了。压测客户端就无法连接开始报错了。但等待一段时间后,又可以增加一点连接上去。
通过找资料分析,查看 /proc/sys/net/ipv4/ip_local_port_range 文件,发现端口配置范围是:32768 60999,也就是说只能有 28231 可以使用。另外就是 time_wait 60s(/proc/sys/net/ipv4/tcp_fin_timeout)。这样每秒只能连接 470 个的样子。
那么要达到 5w 个连接,就需要对可使用端口范围进行调整,并缩短 time_wait 时间,在对 time_wait 端口不复用的情况下(复用要客户端服务端同时满足条件,此处不提)。
端口范围调整
sysctl -w net.ipv4.ip_local_port_range='1024 65535'
time_wait调整
sysctl -w net.ipv4.tcp_fin_timeout=15
sysctl -w 是临时配置,如果要持久化就要写入到 /etc/sysctl.conf 文件中,在执行 sysctl -p 生效。
除了上面配置,整个服务器的完整参数配置如下:
/etc/sysctl.conf
# 系统全局允许分配的最大文件句柄数
fs.file-max = 1048576
fs.nr_open = 1048576
# 并发连接 backlog 设置:
net.core.somaxconn=32768
net.ipv4.tcp_max_syn_backlog=16384
net.core.netdev_max_backlog=16384
# 可用知名端口范围
net.ipv4.ip_local_port_range=1024 65535
# TCP Socket 读写 Buffer 设置
net.core.rmem_default=262144
net.core.wmem_default=262144
net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.core.optmem_max=16777216
net.ipv4.tcp_rmem=1024 4096 16777216
net.ipv4.tcp_wmem=1024 4096 16777216
# TCP 连接追踪设置
net.nf_conntrack_max=1000000
net.netfilter.nf_conntrack_max=1000000
net.netfilter.nf_conntrack_tcp_timeout_time_wait=30
# TIME-WAIT Socket 最大数量、回收与重用设置
net.ipv4.tcp_max_tw_buckets=1048576
# FIN-WAIT-2 Socket 超时设置
net.ipv4.tcp_fin_timeout=15
/etc/systemd/system.conf
# 设置服务最大文件句柄数
DefaultLimitNOFILE=1048576
/etc/security/limits.conf
# 持久化设置允许用户 / 进程打开文件句柄数
root soft nofile 1048576
root hard nofile 1048576