HAProxy
最常见的负载均衡软件有:lvs、nginx、haproxy,而这三种中数lvs性能最好,能够负载的能力也最强,但提供的功能相对较少,且需结合keepalived来进行监控状态检查,在高并发的流量负载的生产环境下,lvs是不二的选择,而相对的nginx和haproxy,整体性能上都差不多,但haproxy提供的功能比nginx多的多,也更容易让我们管理集群和监控集群。
HAProxy提供了两种调度模式,tcp和http,相对的这也就是它可以完成四层调度和七层调度,整个haproxy的工作模型都是基于用户空间的socket进行完成的,所以haproxy受到了socket数的制约,它的并发量也就收到了限制,四层传输层调度也是通过socket模拟完成。
安装
官方网站: http://www.haproxy.org
haproxy已经被收入了base源,所以我们可以可以通过yum直接安装,haproxy版本较多,我这里安装的是1.5:
1 | ~]# yum install -y haproxy |
配置文件
haproxy的配置参数有很多,可以提供丰富的定制代理,所以相对的配置文件也是可以千变万化,但整体构造如下:
global
proxies:
- defaults
- listen
- frontend
- backend
global
log:定义全局的syslog服务器,最多可以定义2个
chroot:安全设置
pidfile
maxconn 设定haproxy单个进程最大可以接受的并发数
user
group
daemon: 守护进程
stats: haproxy提供的socket文件来输出stats统计页
nbproc {number}:指明要启动的haproxy进程的数量
ulimit-n {number}: 每个haproxy进程所能够打开的最大文件数,haproxy会自动计算此数据
性能调整:
maxconn
maxpipes: haproxy使用pipe机制实现内核tcp报文重组,每进程所能使用的最大pipe数量,默认为maxconn/4
noepoll/nokqueue/nopoll/nosepoll:禁用事件机制
nosplice:禁用内核级tcp报文重组功能
spread-checks {0..50} 百分比,调动健康状态检测时间
debug配置参数:
debug
quiet
proxies
- defaults: 为listen/frontend/backend提供默认值
- frontend {name}: 定义监听的套接字,用于接受客户端请求并与之建立连接
- backend {name}: 定义后端服务器组,用于处理frontend转发来的用户请求
- listen {name}: 通过关联“前端”和“后端”定义一个完整proxy server
bind
bind [address]:port_range [, …] [param]bind
bind /path [, …] [param]
1 | listen http_proxy |
2 | bind :80,:443 |
3 | bind 10.0.0.1:10080,10.0.0.1:10443 |
4 | bind /var/run/ssl-frontend.sock user root mode 600 accept-proxy |
balance
balance {algorithm} [ arguments ]
balance url_param param [check_post]
algorithm:
- roundrobin: 动态算法,支持权重的运行时调整及慢查询机制,最大支持4095个后端主机
- static-rr: 静态算法,不支持权重的运行时调整及慢查询机制,后端主机无上限
- leastconn: 最少连接,推荐使用在较长时间会话的场景中;例如ldap,mysql等协议
- first: 根据服务器中的位置,自上而下进行调度,前面的主机服务器达到上限,新请求将调度至下一个服务器
- source: 源地址hash:
取模法:将源地址hash计算后除以服务器总权重,服务器变动会影响全局调度效果,静态调度
一致性hash:服务器变动仅影响局部调动,动态调度
hash_type:指明hash计算方法,map-based:取模,consistent:一致性hash - uri:对uri的左半部分活着整个uri做hash计算,并由服务器的总权重相除后派发至挑选出后端主机,作用在于能够将对同一个uri请求始终法网发往同一个backend server,适合做缓存服务器的场景
- url_param: 对用户请求的url中params中参数的值做hash计算,并由服务器的总权重相除后派发至某挑选出的后端主机,此算法常用于追踪标识,以确保来自同一用户的请求始终发往同一个backend server
- hdr(name)对于每个http请求,通过name指定的http首部会被取出;此首部如果没有有效值,则轮询调度,否则,对其值进行hash计算,并由服务器的总权重相除后派发至某一挑选出的后端主机
- rdp-cookie
- rdp-cookie(name)
1 | balance roundrobin |
2 | balance url_param userid |
3 | balance url_param session_id check_post 64 |
4 | balance hdr(User-Agent) |
5 | balance hdr(host) |
log
log global
log address [len (length)] facility [level[minlevel]]
no log
为每个实例启用事件和流量日志,可用于所以区段;每个实例最多指定两个log目标
compression
compression algo algoriyhm …
compression type mime type …
compression offload
支持的algo:
- identity:通常仅debug时使用
- gzip:
- deflate:
- type:压缩的mime类型,通常仅压缩文本类型的资源
1 | compression algo gzip |
2 | compression type text/html text/plain |
server
server name address[:[port]] [param*]
定义后端主机的服务器及其参数:
- name:服务器的内部名称;如果设定了http-send-server-name,它还将被添加至发往此服务器的请求首部当中
- address:服务器的地址,支持使用主机名
- port:端口映射
- params:参数
- backup:设定备用服务器
- check:对后端服务器做健康状态检查,无check时表示后端主机始终可用,同时可以使用很多辅助参数
- – addr:通过此地址进行健康状态检查
- – port:通过此端口进行健康状态检查
- – inter (delay): 连续两次检测之间的时间间隔,默认2000ms
- – fall (count): 连续多少次检测失败标记为失败
- – rise (count): 连续多少次检测成功标记为成功
- cookie (value): 当当前server指定cookie值,用于实现基于cookie的会话黏性
- maxconn (maxconn): 当前服务器支持的最大并发连接数,超出此值将会被放入队列中
- maxqueue (maxqueue): 当前服务器的队列上限
- redir: 发往此服务器的所以get和head请求全部重定向至指定的地址
- weight: 权重
1 | server first 10.1.1.1:1080 cookie first check inter 1000 maxconn 2000 maxqueue 200 weight 2 |
2 | server second 10.1.1.2:1080 cookie second check inter 1000 fall 2 rise 1 |
option httpchk
option httpchk [method]
option httpchk [method] [uri]
定义基于7层健康状态检测
1 | backend https_relay |
2 | mode tcp |
3 | option httpchk |
4 | server apache1 192.168.1.1:443 check port 80 |
maxconn
定义实例的最大并发连接数
mode
mode {tcp|http|health}
定义实例的工作模式:
- tcp:当代理的为ssl,ssh,mysql等非http协议的使用;默认即为tcp
- http:仅当代理的为http协议时使用
- health:工作健康状态检查响应模式,当仅收到请求仅回应‘ok’即断开连接
cookie
cookie [name [ rewrite | insert | prefix ] [ indirect ] [ nocache ] [ postonly ] [ preserve ] [ httponly ] [ secure ] [ domain domain ]
name: cookie的那段被监控修改或插入
rewrite:重写
insert:插入
prefix:加入前缀
基于cookie的黏性
1 | cookie WEBSRV insert indirect nocache |
2 | server srv1 10.211.55.38 check cookie websrv1 |
3 | server srv2 10.211.55.39 check cookie websrv2 |
stats
- stats enable
启用统计页:基于默认参数启用统计页
stats url:/haproxy?stats
stats realm: “HAProxy Statistics”
stats scope: no restriction - stats uri 【prefix】
统计页的访问uri - stats realm 【realm】
设定认证时使用的realm - stats auth 【user】:【passwd】
认证的账号和密码,可以使用多个 - stats refresh 【delay】
统计页的自动刷新事件间隔 - stats show-desc 【str】
- stats hide-version
- stats admin {if | unless} 【cond】
在指点的条件下启用admin功能
option forwardfor
把发往backend server的请求报文中添加X-Forwarded-For
option forwardfor [ except {network} ] [ header
except network:来自于此网络的请求不添加
header name: 不使用默认的X-Forward-For,而使用此处定义的首部名称
reqadd reqdel rspadd rspdel rspidel
reqadd string [{if | unless} cond]
在请求报文尾部添加自定义的header
reqdel [search] [{if|unless} [cond]
reqdel [search] [{if|unless} (ignore case)]
基于模式删除匹配到的header即其值
rspadd rspdel rspidel
响应报文
errorfile
- errorfile
error code file - errorloc
- errorloc302
error code file
acl
acl [aclname] [criterion] [flags] [operator] [value] …
ceriterion:
1 | dest ip |
2 | dest_port port |
3 | src ip |
4 | src_port port |
5 | |
6 | path: string |
7 | path : exact string match |
8 | path_beg : prefix match |
9 | path_dir : subdir match |
10 | path_dom : domain match |
11 | path_end : suffix match |
12 | path_len : length match |
13 | path_reg : regex match |
14 | path_sub : substring match |
15 | |
16 | url: string |
17 | url : exact string match |
18 | url_beg : prefix match |
19 | url_dir : subdir match |
20 | url_dom : domain match |
21 | url_end : suffix match |
22 | url_len : length match |
23 | url_reg : regex match |
24 | url_sub : substring match |
25 | |
26 | urlp(<name>[,<delim>]) : string |
27 | url_param(<name>[,<delim>]) : string |
28 | 检查请求url中指定param的值 |
29 | urlp(<name>[,<delim>]) : exact string match |
30 | urlp_beg(<name>[,<delim>]) : prefix match |
31 | urlp_dir(<name>[,<delim>]) : subdir match |
32 | urlp_dom(<name>[,<delim>]) : domain match |
33 | urlp_end(<name>[,<delim>]) : suffix match |
34 | urlp_len(<name>[,<delim>]) : length match |
35 | urlp_reg(<name>[,<delim>]) : regex match |
36 | urlp_sub(<name>[,<delim>]) : substring match |
37 | |
38 | req.hdr ([<name>[,<occ>]]) : string |
39 | 检查请求报文指定的首部的值 |
40 | hdr([<name>[,<occ>]]) : exact string match |
41 | hdr_beg([<name>[,<occ>]]) : prefix match |
42 | hdr_dir([<name>[,<occ>]]) : subdir match |
43 | hdr_dom([<name>[,<occ>]]) : domain match |
44 | hdr_end([<name>[,<occ>]]) : suffix match |
45 | hdr_len([<name>[,<occ>]]) : length match |
46 | hdr_reg([<name>[,<occ>]]) : regex match |
47 | hdr_sub([<name>[,<occ>]]) : substring match |
48 | method |
49 | status |
use_backend
use_backend [backend] [{if | unless} [condition]]
default_backend
default_backend backend
1 | backend phpserv |
2 | balance roundrobin |
3 | cookie PHP insert indirect nocache |
4 | server phpsrv1 10.211.55.38 check weight 1 cookie phpsrv1 maxconn 300 |
5 | server phpsrv2 10.211.55.39 check weight 2 cookie phpsrv2 maxconn 600 |
6 | |
7 | backend websrv |
8 | balance roundrobin |
9 | server websrv1 10.211.55.40 check maxconn 10000 |
10 | server websrv2 10.211.55.41 check maxconn 10000 |
11 | |
12 | frontend mysrv |
13 | bind *:80 |
14 | acl php path_end -i .php |
15 | use_backend phpserv if php |
16 | default_backend websrv |
block
block {if | unless}
http-request http-response
http-request {deny|allow|auth} {if | unless} condition
http-response {deny|allow|auth} {if | unless} condition
tcp-request
tcp-request content [action] [{if | unless} condition]
1 | acl is_host_com hdr(Host) -i example.com |
2 | tcp-request content accept if is_host_name |
3 | tcp-request content reject |
实例
实例1
统计页
1 | ~]# cat /etc/haproxy/haproxy.cfg |
2 | glocal |
3 | log 127.0.0.1 local2 |
4 | chroot /var/lib/haproxy |
5 | pidfile /var/run/haproxy.pid |
6 | maxconn 4000 |
7 | user haproxy |
8 | group haproxy |
9 | daemon |
10 | stats socket /var/lib/haproxy/stats |
11 | |
12 | default |
13 | mode http |
14 | log global |
15 | option httplog |
16 | option dontlognull |
17 | option http-server-close |
18 | option forwardfor except 127.0.0.0/0 |
19 | retries 3 |
20 | timeout http-request 10s |
21 | timeout queue 1m |
22 | timeout connect 10s |
23 | timeout client 1m |
24 | timeout server 1m |
25 | timeout http-keep-alive 10s |
26 | timeout check 10s |
27 | maxconn 3000 |
28 | |
29 | listen stats |
30 | bind :9001 |
31 | stats uri /haproxyadmin?stats |
32 | stats realm Haproxy\ Stats |
33 | stats auth admin:admin |
34 | stats show-desc test |
35 | stats admin if TRUE |
36 | stats hide-version |
37 | stats refresh 5s |
实例2
listen反向代理,基于七层健康状态检测
1 | listen web *:80 |
2 | balance roundrobin |
3 | option httpchk GET / |
4 | maxconn 5000 |
5 | server srv1 10.211.55.43 check inter 1000 fall 2 rise 1 maxconn 2000 maxqueue 200 |
6 | server srv2 10.211.55.48 check inter 1000 fall 2 rise 1 maxconn 2000 maxqueue 200 |
1 | ~]# curl 10.211.55.39 |
2 | nginx1 |
3 | ~]# curl 10.211.55.39 |
4 | nginx2 |
实例3
基于cookie的会话黏性
1 | listen web *:80 |
2 | balance roundrobin |
3 | option httpchk GET / |
4 | maxconn 5000 |
5 | cookie WEBSRV insert indirect nocache |
6 | server srv1 10.211.55.43 check inter 1000 fall 2 rise 1 maxconn 2000 maxqueue 200 cookie websrv1 |
7 | server srv2 10.211.55.48 check inter 1000 fall 2 rise 1 maxconn 2000 maxqueue 200 cookie websrv2 |
实例4
基于fortend和backend的动静分离
1 | backend phpserver |
2 | balance roundrobin |
3 | cookie PHP insert indirect nocache |
4 | server php1 10.211.55.48 check cookie php1 maxconn 300 |
5 | server php2 10.211.55.49 check cookie php2 maxconn 300 |
6 | |
7 | backend webserver |
8 | balance roundrobin |
9 | option httpchk GET / |
10 | server web1 10.211.55.50 check maxconn 10000 |
11 | server web2 10.211.55.51 check maxconn 10000 |
12 | |
13 | backend jsserver |
14 | balance roundrobin |
15 | option httpchk GET / |
16 | server js1 10.211.55.52 check maxconn 5000 |
17 | server js2 10.211.55.53 check maxconn 5000 |
18 | |
19 | frontend myweb |
20 | bind *:80 |
21 | acl php path_end -i .php |
22 | acl js path_reg -i \.js|\.css|\.jpeg|\.png|\.swf |
23 | use_backend phpserver if php |
24 | use_backend jsserver if js |
25 | default_backend webserver |
实例5
删除响应报头的信息泄漏
1 | listen web *:80 |
2 | balance roundrobin |
3 | option httpchk GET / |
4 | maxconn 5000 |
5 | rspidel X-Powered-BY:.*|Server:.* |
6 | cookie WEBSRV insert indirect nocache |
7 | server srv1 10.211.55.43 check inter 1000 fall 2 rise 1 maxconn 2000 maxqueue 200 cookie websrv1 |
8 | server srv2 10.211.55.48 check inter 1000 fall 2 rise 1 maxconn 2000 maxqueue 200 cookie websrv2 |
实例6
阻断请求,并重定向错误页
1 | listen web *:80 |
2 | balance roundrobin |
3 | option httpchk GET / |
4 | maxconn 5000 |
5 | rspidel X-Powered-BY:.*|Server:.* |
6 | acl bad_ip src 192.168.31.0/24 10.211.55.0/24 |
7 | block if bad_ip |
8 | errorfile 403 /tmp/sorry.html |
9 | cookie WEBSRV insert indirect nocache |
10 | server srv1 10.211.55.43 check inter 1000 fall 2 rise 1 maxconn 2000 maxqueue 200 cookie websrv1 |
11 | server srv2 10.211.55.48 check inter 1000 fall 2 rise 1 maxconn 2000 maxqueue 200 cookie websrv2 |