作者:hncscwc http://my.oschina.net/hncscwc/blog/199152

1. maxconn设置

大家都知道haproxy启动时可以通过命令行参数-n, -N设置连接数,在配置文件也可以在global段,default段,listen段中分别对maxconn进行设置,然而这些设置都启什么作用,优先级又是怎样的?

01haproxy -f haproxy.cfg -n 60000 -N 50000 
02
03haproxy.cfg 
04
05global 
06maxconn 40000 
07
08default 
09maxconn 30000 
10
11listen test1 
12bind 0.0.0.0:50000 
13maxconn 20000 
14server srv-test1... maxconn 10000 check 
15
16listen test2 
17bind 0.0.0.0:6000 
18server srv-test2 ... maxconn 10000 check


以上图为例: 

global段中的maxconn:  设置进程的最大连接数,等同于命令行参数 -n

default段中的maxconn:  设置默认代理段的最大连接数, 等同于命令行参数 -N

listen段中的maxconn:  设置该代理的最大连接数,等同于命令行参数-N

server中的maxconn:  设置该后台服务的最大连接数

其优先级为: 

(1) 命令行参数-n指定的连接数 > global中通过maxconn设置的连接数 

(2) listen段中的maxconn > default段中的maxconn > 命令行参数-N指定的连接数 

根据上面的总结,如果按照前面的命令行参数和配置文件运行haproxy,那么 

haproxy的最大连接数为60000 

侦听端口为50000的代理段,最大连接数为20000 

侦听端口未60000的代理段,最大连接数为30000(使用了default中maxconn的值) 

其后端真正的服务最大连接数为10000 

实际运行结果为: 

对haproxy配置学习过程中几个点进行总结_listen

2. ulimit 

聊到最大连接数,那么必然会涉及到ulimit的设置,是否还需要对haproxy进行ulimit -n的设置?不进行设置的话那真正的限制数是多少?上图中 maxsock=120015又是怎么来的? 

对haproxy配置学习过程中几个点进行总结_优先级_02

官网的文档中看到可以通过ulimit-n进行设置,然而并不推荐手动进行设置,因为haproxy自身会进行调整。 

具体计算方式为: 

maxsock = 10(默认值) + global.maxconn * 2 + global.maxpipes * 2 + bind数量 + check数量 

其中maxconn对应global中maxconn或者命令行参数-n设置的值 

maxpipes对应global中maxpipes的值 

bind对应为bind的个数 

check对应于对后台真正服务进行健康检测的个数 

还是以前面的例子说明: 

maxconn的值为60000;maxpipes没有进行设置,其值为0;在50000,60000进行bind(实际还在1080端口进行了bind,以供管理员通过web查看haproxy的相关信息,上面的配置文件中并没有列出来),那么bind的值等于3;对后台服务srv-test1,srv-test2均进行了check,因此check的值为2 

maxsock = 10 + 60000*2 + 0 + 3 + 2 = 120015 

这个maxsock也就是最终的限制数,通过查看/proc/PID/limits可以验证 

对haproxy配置学习过程中几个点进行总结_haproxy_03

如果在配置文件中配置了 ulimin-n,其值应该大于通过计算后得出的maxsock的值。 

设置ulimit-n 130000的运行情况为 

对haproxy配置学习过程中几个点进行总结_优先级_04

3. bind interface 

通常,作为后台服务的代理,haproxy会配置多网段的地址,比如在不同的网卡上分别绑定移动,联通,电信,内网等地址。那么如果业务需要区分来自不同网段的客户端时,可以考虑在bind中增加interface配置项来解决。例如: 

01listen 电信 
02bind 0.0.0.0:60000 interface eth0 
03server  ... 
04
05listen 联通 
06bind 0.0.0.0:60000 interface eth1 
07server  ... 
08
09listen 内网 
10bind 0.0.0.0:60000 interface eth2 
11server  ...

简单翻了下代码,发现haproxy对此的大概实现为:在解析配置文件的bind时,记录interface指定的网卡名,然后通过 

setsockopt(fd,SOL_SOCKET,SO_BINDTODEVICE,listener->interface,strlen(listener->interface)+1)来实现。 

注意: 这种方式仅在linux下有效,且需要root权限。