HaProxy学习 ---300K的TCP Socket并发连接实现(翻译)
- [1 原文链接](#1 原文链接)
- [2 原文翻译](#2 原文翻译)
-
- [2.1 调整Linux系统参数](#2.1 调整Linux系统参数)
- [2.2 调整HAProxy](#2.2 调整HAProxy)
1 原文链接
2 原文翻译
标题 :用HAProxy的负载均衡实现300K的TCP Socket并发连接:端口耗尽、保持连接等。
发表时间: 2015年8月19日
最近我尝试建立一个推送系统。为了增加系统的可扩展性,最佳实践是使每个连接尽可能无状态。因此当瓶颈出现时,可以通过添加更多的机器来轻松扩展整个系统的容量。说到负载平衡和反向代理,Nginx可能是最著名和公认的一个。然而,TCP代理是一个相当新的事情。Nginx从v1.9引入了TCP负载平衡和反向代理,该版本于今年5月下旬发布,有很多缺失的功能。另一方面,HAProxy作为TCP加载平衡的先驱,已经相当成熟和稳定。我选择使用HAProxy来构建系统,最终我达到了300K的TCP Socket并发连接。如果不是我相当过时的客户端PC,我可以实现更高的数量。
2.1 调整Linux系统参数
300K的TCP Socket并发连接对于高性能服务器PC来说也不是一件容易的事情。首先,我们需要调整Linux内核配置,以充分利用我们的服务器。
- 文件描述符
从Linux系统角度来看,Sockets等同于文件,因此默认的文件描述符限制对于我们的300k目标来说相当小。修改系统全局允许分配的最大文件句柄数:
bash
sysctl -w fs.file-max=10000000
sysctl -w fs.nr_open=10000000
这些行将文件描述符总数增加到100万。接着修改 /etc/security/limits.conf
,添加持久化设置允许用户 / 进程打开文件句柄数:
bash
* soft nofile 10000000
* hard nofile 10000000
root soft nofile 10000000
root hard nofile 10000000
非root用户,前两行应该可以完成工作。但是,如果是以root用户身份运行HAProxy,则需要明确声明root用户。
- TCP Socket 读写 Buffer 设置
保持如此大量的连接会消耗大量内存。为了减少内存使用,修改/etc/sysctl.conf
添加以下行。
bash
net.ipv4.tcp_mem = 786432 1697152 1945728
net.ipv4.tcp_rmem = 4096 4096 16777216
net.ipv4.tcp_wmem = 4096 4096 16777216
2.2 调整HAProxy
完成内核Linux调优后,我们需要调整HAProxy以更好地满足我们的需求。
- 增加最大连接数
在HAProxy中,全局和具体后端都有一个"最大连接上限"。为了增加上限,我们需要在全局范围下添加一行配置。
bash
maxconn 2000000
然后将相同的行添加到后端范围内,示例:
bash
backend pushserver
mode tcp
balance roundrobin
maxconn 2000000
- 调整timeout
调整连接超时时间,默认情况下,这些参数都的以毫秒为单位。
bash
timeout connect 5000
timeout client 50000
timeout server 50000
-
配置源IP来解决端口耗尽问题(调整可用知名端口范围)
当同时有30k连接时,会遇到"端口耗尽"的问题,它是由每个反向代理的连接都会占用一个本地IP的可用端口造成的,可用于传出连接的默认IP范围在30k~60k左右,换句话说,我们只有一个IP的30k端口可用,显然不够,可以通过修改/etc/sysctl.conf
增加下面这一行来增加这个范围。bashsysctl -w net.ipv4.ip_local_port_range='1024 65535'
这不能解决根本问题,当达到60k上限时,我们仍然会用完端口。
这个端口耗尽问题的最终解决方案是增加可用IP的数量。首先,我们将一个新的IP绑定到一个新的虚拟网络接口。
bash
ifconfig eth0:1 192.168.8.1
这个命令绑定一个Intranet地址到一个硬件接口为eth0的虚拟网络接口eth0:1上。该命令可以执行几次,来添加任意数量的虚拟网络接口。只需记住IP应该在真实应用服务器的同一个子网络中。换句话说,你不能用任何类型的NAT服务在HAProxy和应用服务器之间建立连接。因为它不起作用。
接下来,配置HAProxy来使用这些新的IP。有一个源命令可以在后端范围内使用,也可以作为服务器命令的参数。在我们的实验中,后端范围似乎不起作用,所以我们选择了参数一。这是具体配置。
bash
backend mqtt
mode tcp
balance roundrobin
maxconn 2000000
server app1 127.0.0.1:1883 source 192.168.8.1
server app2 127.0.0.1:1883 source 192.168.8.2
server app3 127.0.0.1:1883 source 192.168.8.3
server app4 127.0.0.1:1884 source 192.168.8.4
server app5 127.0.0.1:1884 source 192.168.8.5
server app6 127.0.0.1:1884 source 192.168.8.6
这里有一个技巧,需要在多个条目中声明它们,并给它们不同的应用程序名称。如果你为所有四个条目设置相同的应用程序名称,HAProxy将无法工作。如果你可以查看HAProxy状态报告的输出,你会发现即使这些条目具有相同的后端地址,HAProxy仍然将它们视为不同的应用程序。
这就是配置!现在你的HAProxy应该能够处理超过300k并发TCP连接,就像我的一样。