Haproxy基础知识 -运维小结

 

开源软件负载均衡器

现在常用的三大开源软件负载均衡器分别是Nginx、LVS、Haproxy。 在之前的文章中已经对比了这三个负载均衡软件, 下面根据自己的理解和使用经验, 再简单说下这三个负载均衡软件各自特点:
LVS负载均衡的特点
1) 抗负载能力强。抗负载能力强、性能高,能达到F5硬件的60%;对内存和cpu资源消耗比较低
2) 工作在网络4层,通过vrrp协议转发(仅作分发之用),具体的流量由linux内核处理,因此没有流量的产生。
3) 稳定性、可靠性好,自身有完美的热备方案;(如:LVS+Keepalived)
4) 应用范围比较广,可以对所有应用做负载均衡;
5) 不支持正则处理,不能做动静分离。
6) 支持负载均衡算法:rr(轮循)、wrr(带权轮循)、lc(最小连接)、wlc(权重最小连接)
7) 配置 复杂,对网络依赖比较大,稳定性很高。

Ngnix负载均衡的特点 
1) 工作在网络的7层之上,可以针对http应用做一些分流的策略,比如针对域名、目录结构;
2) Nginx对网络的依赖比较小,理论上能ping通就就能进行负载功能;
3) Nginx安装和配置比较简单,测试起来比较方便;
4) 也可以承担高的负载压力且稳定,一般能支撑超过1万次的并发;
5) 对后端服务器的健康检查,只支持通过端口来检测,不支持通过url来检测。
6) Nginx对请求的异步处理可以帮助节点服务器减轻负载;
7) Nginx仅能支持http、https和Email协议,这样就在适用范围较小。
8) 不支持Session的直接保持,但能通过ip_hash来解决。、对Big request header的支持不是很好,
9) 支持负载均衡算法:Round-robin(轮循)、Weight-round-robin(带权轮循)、Ip-hash(Ip哈希)
10) Nginx还能做Web服务器即Cache功能。

HAProxy负载均衡的特点
1) 支持两种代理模式:TCP(四层)和HTTP(七层),支持虚拟主机;
2) 能够补充Nginx的一些缺点比如Session的保持,Cookie的引导等工作
3) 支持url检测后端的服务器出问题的检测会有很好的帮助。
4) 更多负载均衡策略比如:动态加权轮循(Dynamic Round Robin),加权源地址哈希(Weighted Source Hash),加权URL哈希和加权参数哈希(Weighted Parameter Hash)已经实现
5) 单纯从效率上来讲HAProxy更会比Nginx有更出色的负载均衡速度。
6) HAProxy可以对Mysql进行负载均衡,对后端的DB节点进行检测和负载均衡。
9) 支持负载均衡算法:Round-robin(轮循)、Weight-round-robin(带权轮循)、source(原地址保持)、RI(请求URL)、rdp-cookie(根据cookie)
10) 不能做Web服务器即Cache。

这三大主流软件负载均衡器适用业务场景
1) 网站建设初期,可以选用Nigix/HAproxy作为反向代理负载均衡(或者流量不大都可以不选用负载均衡),因为其配置简单,性能也能满足一般的业务场景。如果考虑到负载均衡器是有单点问题,可以采用Nginx+Keepalived/HAproxy+Keepalived避免负载均衡器自身的单点问题。
2) 网站并发达到一定程度之后,为了提高稳定性和转发效率,可以使用LVS、毕竟LVS比Nginx/HAproxy要更稳定,转发效率也更高。不过维护LVS对维护人员的要求也会更高,投入成本也更大。

需要注意的是
Niginx与Haproxy比较: Niginx支持七层、用户量最大,稳定性比较可靠。Haproxy支持四层和七层,支持更多的负载均衡算法,支持session保存等。具体选型看使用场景,目前来说Haproxy由于弥补了一些Niginx的缺点致使其用户量也不断在提升

衡量负载均衡器好坏的几个重要因素
1) 会话率 :单位时间内的处理的请求数
2) 会话并发能力:并发处理能力
3) 数据率:处理数据能力
经过官方测试统计,haproxy 单位时间处理的最大请求数为20000个,可以同时维护40000-50000个并发连接,最大数据处理能力为10Gbps。综合上述,haproxy是性能优越的负载均衡、反向代理服务器。

Haproxy简介

HAProxy是法国人Willy Tarreau开发的一款可应对客户端10000以上的同时连接的高性能的TCP和HTTP负载均衡器。由于其丰富强大的功能在国内备受推崇,是目前主流的负载均衡器。Haproxy是一个开源的高性能的反向代理或者说是负载均衡服务软件之一,它支持双机热备、虚拟主机、基于TCP和HTTP应用代理等功能。其配置简单,而且拥有很好的对服务器节点的健康检查功能(相当于keepalived健康检查),当其代理的后端服务器出现故障时,Haproxy会自动的将该故障服务器摘除,当服务器的故障恢复后haproxy还会自动重新添加回服务器主机。

Haproxy实现了一种事件驱动、单一进程模型,此模型支持非常大的并发连接数。多进程或多线程模型受内存限制、系统调度器限制以及无处不在的锁限制,很少能处理数千并发连接。事件驱动模型因为在有更好的资源和时间管理的用户空间(User-Space)实现所有这些任务,所以没有这些问题。此模型的弊端是,在多核系统上,这些程序通常扩展性较差。这就是为什么必须对其进行优化以使每个CPU时间片(Cycle)做更多的工作。

Haproxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保持或七层处理。haproxy运行在当前的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单安全的整合进当前架构中,同时可以保护web服务器不被暴露到网络上。

Haproxy软件引入了frontend,backend的功能,frontend(acl规则匹配)可以根据任意HTTP请求头做规则匹配,然后把请求定向到相关的backend(server pools等待前端把请求转过来的服务器组)。通过frontend和backend,可以很容易的实现Haproxy的7层负载均衡代理功能

Haproxy是一种高效、可靠、免费的高可用及负载均衡解决方案,非常适合于高负载站点的七层数据请求。客户端通过Haproxy代理服务器获得站点页面,而代理服务器收到客户请求后根据负载均衡的规则将请求数据转发给后端真实服务器。
同一客户端访问服务器,Haproxy保持回话的三种方案
1) Haproxy将客户端ip进行Hash计算并保存,由此确保相同IP访问时被转发到同一真实服务器上。
2) Haproxy依靠真实服务器发送给客户端的cookie信息进行回话保持。
3) Haproxy保存真实服务器的session及服务器标识,实现会话保持功能。

Haproxy工作原理

Haproxy提供高可用性、负载均衡以及基于TCP(第四层)和HTTP(第七层)应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。Haproxy特别适用于那些负载特别大的web站点,这些站点通常又需要会话保持或七层处理。Haproxy运行在时下的硬件上,完全可以支持数以万计的并发连接,并且它的运行模式使得它可以很简单安全的整合进您当前的架构中,同时可以保护你的web服务器不被暴露到网络上。

Haproxy实现了一种事件驱动、单一进程模型,此模型支持非常大的并发连接数。多进程或多线程模型受内存限制、系统调度器限制以及无处不在的锁限制,很少能处理数千并发连接。事件驱动模型因为在有更好的资源和时间管理的用户端(User-Space)实现所有这些任务,所以没有这些问题。此模型的弊端是,在多核系统上,这些程序通常扩展性较差。这就是为什么他们必须进行优化以使每个CPU时间片(Cycle)做更多的工作。

Haproxy的优点
1)免费开源,稳定性也是非常好。单Haproxy也跑得不错,稳定性可以与硬件级的F5相媲美。
2)根据官方文档,Haproxy可以跑满10Gbps,这个数值作为软件级负载均衡器是相当惊人的。
3)Haproxy支持连接拒绝:因为维护一个连接的打开的开销是很低的,有时我们很需要限制攻击蠕虫(attack bots),也就是说限制它们的连接打开从而限制它们的危害。这个已经为一个陷于小型DDoS攻击的网站开发了而且已经拯救了很多站点,这个优点也是其它负载均衡器没有的。
4)Haproxy支持全透明代理(已具备硬件防火墙的典型特点):可以用客户端IP地址或者任何其他地址来连接后端服务器。这个特性仅在Linux 2.4/2.6内核打了tcp proxy补丁后才可以使用。这个特性也使得为某特殊服务器处理部分流量同时又不修改服务器的地址成为可能。
5)Haproxy现在多用于线上的Mysql集群环境,常用于它作为MySQL(读)负载均衡。
6)自带强大的监控服务器状态的页面,实际环境中我们结合Nagios进行邮件或短信报警。
7)Haproxy支持虚拟主机,许多朋友说它不支持虚拟主机是错误的,但是通过测试可知,Haproxy是支持虚拟主机的。

Haproxy主要工作位置

-  Haproxy支持http反向代理
-  Haproxy支持动态程序的反向代理
-  Haproxy支持基于数据库的反向代理

Haproxy 相关术语

访问控制列表(ACL)
在负载均衡当中,ACL用于测试某些状况,并根据测试结果执行某些操作(例如选定一套服务器或者屏蔽某条请求), 如下ACL示例

acl url_blog path_beg /blog

如果用户请求的路径以/blog开头,则匹配这条ACL。举例来说,http://yourdomain.com/blog/blog-entry-1请求即符合这一条件。要了解更为具体的AC使用方法,请参阅HAProxy配置指南

Backend
所谓backend是指一组服务器,负责接收各转发请求。Backend在HAProxy配置中的backend部分进行定义。一般来讲,backend的定义主要包括:
- 使用哪种负载均衡算法
- 一套服务器与端口列表

一条backend能够容纳一套或者多套服务器——总体而言向backend中添加更多服务器将能够将负载扩散至更多服务器,从而增加潜在负载容量。这种方式也能够提升可靠性,从而应对部分后端服务器发生故障的情况。

下面来看一套双backend配置示例,分别为web-backend与blog-backend,其各自包含两套Web服务器,且监听端口80:

backend web-backend
  balance roundrobin
  server web1 web1.kevin.com:80 check
  server web2 web2.kevin.com:80 check

backend blog-backend
  balance roundrobin
  mode http
  server blog1 blog1.kevin.com:80 check
  server blog2 blog2.kevin.com:80 check

其中:
.balance roundrobin行指定负载均衡算法, 具体细节请参阅负载均衡算法部分
.mode http则指定所使用的7层代理机制,具体请参阅负载均衡类型部分。
.结尾处的check选项指定在这些后端服务器上执行运行状态检查。

Frontend
一条frontend负责定义请求如何被转发至backend。Frontend在HAProxy配置中的frontend部分进行定义。其定义由以下几部分组成:
.一组IP地址与一个端口(例如10.1.1.7:80, *:443,等等)
.ACL
.use_backend规则,其负责根据当前ACL条件定义使用哪个backend,而default_backend规则处理一切其它情况
我们可以将同一frontend配置至多种不同网络流量类型

可以将同一frontend配置至多种不同网络流量类型!

下面了解负载均衡的基本类型。

无负载均衡
简单的无负载均衡Web应用环境, 用户会直接接入Web服务器,即kevin.com且其中不存在负载均衡机制。如果单一Web服务器发生故障,用户将无法接入该服务器。另外,如果多位用户同时访问该服务器,且其无法处理该负载,则可能出现响应缓慢或者无法接入的情况。

四层负载均衡
最为简单的负载均衡方式,将网络流量引导至多台服务器以使用四层(即传输层)负载均衡。这种方式会根据IP范围与端口进行用户流量转发(如果有请求指向http://kevin.com/anything,则该流量将被转发至backend,并由其处理全部指向kevin.com在端口80上的请求)

frontend web_80                             
   mode tcp
   bind :80 
   default_backend web-backend

backend web-backend
   mode tcp
   server 172.16.60.164 172.16.60.164:80 weight 1 check inter 1s rise 2 fall 2
   server 172.16.60.165 172.16.60.165:80 weight 1 check inter 1s rise 2 fall 2

用户访问负载均衡器,后者将用户请求转发至后端服务器的web-backend组。被选定的后端服务器将直接响应用户请求。总体而言,web-backend中的全部服务器都应当拥有同样的内容, 否则用户可能会遭遇内容不一致问题。请注意后端两个Web服务器都接入同样的数据库服务器。

七层负载均衡
另一种更为复杂的负载均衡方式,网络流量使用7层(即应用层)负载均衡。使用7层意味着负载均衡器能够根据用户的请求内容将请求转发至不同后端服务器。这种方式允许大家在同一域名及端口上运行多套Web应用服务器。下图为一套简单的7层负载均衡示例在本示例中,如果用户向kevin.com/blog发送请求,则会被转发至blog后端,其包含一组运行有同一blog应用的服务器。其它请求则会被转发至web-backend,其负责运行其它应用。本示例中的两套backend皆使用同样的数据库服务器。下面来看本示例中frontend配置片段

frontend http
   bind *:80
   mode http

  acl url_blog path_beg /blog
  use_backend blog-backend if url_blog

  default_backend web-backend

backend web-backend
    mode http
    balance roundrobin
    cookie SERVERID insert indirect nocache
    option httpclose
    option forwardfor
    server web01 172.16.60.150:80 weight 1 cookie 3 check inter 2000 rise 2 fall 5
    server web01 172.16.60.151:80 weight 1 cookie 3 check inter 2000 rise 2 fall 5

这部分片段配置一套名为http的frontend,其负责处理端口80上的所有输入流量。
.acl url_blog path_beg 这里的/blog表示匹配那些用户请求路径以/blog开头的请求。
.use_backend blog-backend if url_blog 这里采用该ACL将流量代理至blog-backend。
.default_backend web-backend 这里指定全部其它流量被转发至web-backend。

负载均衡算法
负载均衡算法用于检测后端中的哪套服务器被负载均衡机制选定进行请求响应。HAProxy提供多种算法选项。除了负载均衡算法之外,我们还能够为服务器分配一个weight参数以指定该服务器被选定的频率。由于HAProxy提供多种负载均衡算法,因此我们下面只提及其中的一部分。来看几种常用算法:

roundrobin
Round Robin会对服务器进行轮流选定,亦为HAProxy的默认算法。即客户端每访问一次, 请求就跳转打到后端不同的节点机器上

leastconn
选定连接数量最少的服务器——建议在周期较长的会话中使用这一算法。同一后端中的服务器亦会以轮循方式进行轮流选定。

source
其根据源IP(即用户IP地址)进行服务器选定。通过这种方式,我们可以确定同一用户接入同一服务器。

粘性会话
部分应用要求用户始终接入同一后端服务器,这一点需要利用粘性会话实现,其要求在backend中使用appsession参数。

运行状态检查
HAProxy利用运行状态检查来检测后端服务器是否可用于处理请求。通过这种方式,我们不必以手动方式撤下不可用的后端服务器。默认运行状态检查会与目标服务器建立一条TCP连接,即检查后端服务器是否在监听所配置的IP地址与端口。

如果某套服务器未能通过运行状态检查,并因此无法响应请求,则其会在后端中被自动禁用——意味着流量将不再被转发到该服务器处,直到其重新恢复正常。如果后端中的全部服务器皆发生故障,则服务将不再可用,直到至少一套后端服务器重新恢复正常。

对于特定后端类型,例如特定状态下的数据库服务器,默认运行状态检查可能无法正确识别其正常与否。

其它解决方案
如果大家认为HAProxy可能太过复杂,那么以下解决方案同样值得考虑:
.Linux虚拟服务器(LVS) - 一套简单且快速的4层负载均衡器,多数Linux发行版都内置有这套方案。
.Nginx - 一套快速且可靠的Web服务器,亦可用于代理及负载均衡。Nginx通常与HAProxy相结合以实现缓存及压缩功能。

Haproxy 使用细节梳理

以上简单介绍了Haproxy, 下面来整体梳理下Haproxy的使用:

Haproxy 程序环境

安装:yum install haproxy -y
主程序: /usr/sbin/haproxy
配置文件: /etc/haproxy/haproxy.cfg
主配置文件主要结构:1) global 全局配置段 ;  2) proxies代理配置段

一. global 全局配置段

1.1) log:全局日志配置
默认发往本机的日志服务器;
1) 系统默认:log 127.0.0.1 local2 //表示发往远端可添加:log 远端IP local2
2) 修改本机日志配置文件

[root@localhost ~]# vim  /etc/rsyslog.conf
$ModLoad imudp          #取消注释
$UDPServerRun 514    #取消注释
local2.*                                                /var/log/haproxy.log  #新增

3) 远端日志配置(配合前端log配置)

[root@localhost ~]# vim  /etc/rsyslog.conf
local2.*    /var/log/haproxy.log                 #新增

1.2) 性能调整(依据生产环境适当调整)
.maxconn <number>:设定每个haproxy进程所能接受的最大并发连接数
.maxconnrate <number>:设置每个进程每秒种所能建立的最大连接数量
.maxsessrate <number>:设置每个进程每秒种所能建立的最大会话数量
.maxsslconn <number>: 每进程支持SSL的最大连接数量
.spread-checks <0..50, in percent>: 健康检测延迟时长比建议2-5之间

二. proxies 代理配置段结构
1) defaults:为frontend, backend, listen提供默认配置;
2) fronted:前端,指定接收客户端连接侦听套接字设置;
3) backend:后端,指定将连接请求转发至后端服务器的相关设置;
4) listen:同时拥有前端和后端,适用于一对一环境;

三. 简单haproxy代理案例
实验拓扑:

3.1) 方法一
配置 /etc/haproxy/haproxy.cfg, 将frontend段、backend段注释,新建如下配置

[root@localhost ~]# vim /etc/haproxy/haproxy.cfg
............
............
frontend http *:80                #均衡器端采用http 协议,监听80端口
      default_backend websrvs   #引用后端自定义服务器组名websrvs
backend websrvs                   #设定默认后端,自定义名字为websrvs
      balance roundrobin        #轮询方式为加权轮询
      server web1 192.168.43.61:80 check    #设定后端服务器IP ,并引入健康检查
      server web2 192.168.43.63:80 check    #设定后端服务器IP ,并引入健康检查



[root@localhost ~]# service haproxy start

在浏览器访问http://172.18.43.62 刷新即可看到轮询效果, 即访问结果为192.168.43.61和192.168.43.63的web端口(80端口)展示的内容, 每次刷新, 访问结果都不一样, 即交替展示两个机器的web内容.

3.2) 方法二
上面两段配置也可以配置在一段实现相同功能,配置如下

[root@localhost ~]# vim /etc/haproxy/haproxy.cfg
............
............
listen http
   bind :80
   balance roundrobin
   server web1 192.168.43.61:80 check
   server web2 192.168.43.63:80 check

[root@localhost ~]# service haproxy start

配置参数 bind:指定一个或多个前端侦听地址和端口
语法: bind [<address>]:<port_range> [, ...] [param*]
示例如下:

listen http_proxy
bind :80,:443
bind 172.16.60.10:10080,172.16.60.10:10443

                                                        option选项说明                                                            

option httpclose
haproxy会针对客户端的第一条请求的返回添加cookie并返回给客户端,客户端发送后续请求时会发送此cookie到HAProxy,HAProxy会针对此cookie分发到上次处理此请求的服务器上,如果服务器不能忽略此cookie值会影响处理结果。如果避免这种情况配置此选项,防止产生多余的cookie信息。"option httpclose"  和 "no option httpclose" 是两个对立设置, 分别表示启用或禁止消极的HTTP连接关闭

默认的,客户端与服务端的通讯,HAProxy只做分析、日志和分析每个连接的第一个request。如果设置了 "option httpclose" , 则会检查双向的http头是否有"Connection: close",如果没有则自动添加,使每个客户端或服务端在每次传输后,都主动关闭TCP连接,使HTTP传输处于HTTP close模式下。任何 "Connection" 头如果不是"close",都会被移除。

很少会有服务器不正确的忽略掉头,即使收到"Connection: close"也不关闭连接,否则就是不兼容HTTP 1.0浏览器标准。 如果发生这种情况,可以使用"option forceclose",在服务端响应后主动关闭请求连接。选项 "forceclose"还可以及早释放服务连接,而不必等到客户端的应答确认。

这个选项可以设置在frontend或backend上,只要其上可以建立连接。如果同时设置了"option forceclose",那么它比"httpclose"优先。如果同时设置了 "option http-server-close",则会实现"option forceclose"的效果。

option forceclose  启用response后的主动关闭连接 (no option forceclose  表示禁止)

有的HTTP服务器收到"option httpclose"设置的"Connection: close",也不会关闭连接,如果客户端也不关闭,连接会 一直打开,直到超时。这会造成服务器上同一时段内的大量连接,日志中也会显示较高的全局会话时间。

此时,可以使用 "option forceclose",当完成响应时,立即关闭对外的服务通道。该选项隐式打开httpclose选项。需要注意,该选项允许解析完整的request 和 response,所以可以很快关闭至服务器的连接,比httpclose更早释放一些资源。

如果同时启用了"option http-pretend-keepalive",虽然会禁止发送 "Connection: close"头,但是依然会在整个response被接收后,关闭连接。

option http-server-close  启用关闭服务端的HTTP连接  (no option http-server-close 表示禁止)

默认的,客户端与服务端通讯,haproxy 只是分析、记日志,并处理每个连接的第一个请求。该选项设置server端为HTTP 连接关闭模式,并支持客户端为HTTP keep-alive的pipelining模式。提供了最低的客户端延迟和最快的服务端会话重用,以节省服务资源,类似"option forceclose"。还允许无keepalive能力的服务端在keep-alive模式下为客户端提供服务,但是需要符合 RFC2616。需要注意的是,有些服务器遇到"Connection: close" 时并不总是执行关闭,那么keep-alive 则无法使用,解决方法是启用 "option http-pretend-keepalive".

目前,日志无法指明请求是否来自同一会话;日志中的接收日期为前一个请求的结束;请求时间为新请求的等待时间;keep-alive request time 存活请求时间为超时时间,绑定 "timeout http-keep-alive" 或 "timeout http-request"的设置。

这个操作可以设置在frontend或backend上,只要其上可以建立连接。需要注意的是,这个选项可以与 "option httpclose"结合, 但 "option httpclose"优先级更高,结合后基本实现了forceclose的效果。

option http-pretend-keepalive 表示http-假装-长连接, 即haproxy 与服务器是否是 keepalive 的) (如果不开启该配置, 则为no option http-pretend-keepalive )

当声明了 "option http-server-close" 或 "option forceclose", haproxy会在给server的request头中添加 "Connection: close" 。然而有些服务器看到这个头,会返回未知长度的response,并自动避免chunked encoding,其实这是不对的。它会阻止haproxy保持客户端长连接,还会使客户端或缓存接收了未完成的响应,却认为响应结束了。

设置 "option http-pretend-keepalive", haproxy会在服务器端保持长连接,服务端则不会出现前面的问题。当 haproxy 获取了完整的response, 才会以类似forceclose的方式关闭服务端。这样客户端得到一个普通的响应,连接也在服务端被正常关闭。

建议不将其设为默认值,因为大部分服务器会在发送完最后一个包之后更高效的关闭连接,并释放缓存,而且网络上的数据包也会略微降低整体的峰值性能。但是启用该选项,haproxy会略微少做一些工作。所以如果haproxy在整个架构中是个瓶颈,可以启用该操作,以节省CPU。

这个选项可以设置在frontend或backend上,只要其上可以建立连接。这个选项可以与 "option httpclose"结合, 使服务端keepalive,客户端close,但并不建议这样做。

option forwardfor
如果服务器上的应用程序想记录发起请求的客户端的IP地址,需要在HAProxy上配置此选项,这样haproxy会把客户端的IP信息发送给服务器,在HTTP请求中添加"X-Forwarded-For"字段。 

option originalto
如果服务器上的应用程序想记录发起请求的原目的IP地址,需要在HAProxy上配置此选项,这样haproxy会添加"X-Original-To"字段。

option dontlognull (即记录空连接)
保证haproxy不记录上级负载均衡发送过来的用于检测状态没有数据的心跳包。

其他option相关设置:
option abortonclose      丢弃由于客户端等待时间过长而关闭连接但仍在haproxy等待队列中的请求
option accept-invalid-http-request      接受无效的http请求,建议关闭(开启可能有安全隐患)
option accept-invalid-http-response     接受无效的response ,建议关闭
option allbackups      应该是后备服务器,如果正常的后端无法使用,就使用这些后备的设备,balance方式还是用原来的,没有优先的选择,常用来提供错误的页面
option checkcache      分析后端response,阻止可缓存的cookie,它对response 进行严格检查,包括"Cache-control", "Pragma" and "Set-cookie" ,查看在客户端代理那边保存是否有风险,如果这个允许的话,符全以下条件 的response 将被允许,其它的将被阻止。

option clitcpka      是否允许客户端发送tcp keepalive 包,这个和http 的keepalive 没有关系
option contstats     允许连续的流量统计更新
option dontlog-normal     开启正常连接的日志
option forceclose      允许关闭session 在后端把response 发送后
option forwardfor [ except <network> ] [ header <name> ]      允许在request 中加入X-Forwarded-For header 发往server
option http-pretend-keepalive      定义是否haproxy要宣布同server keepalive
option http-server-close     是否开启在server 端 connection closing
option http-use-proxy-header    用non-standard Proxy-Connection 替换 connection

option httpchk <method> <uri> <version>      允许用http协议检查server 的健康
option httplog [ clf ]     定制日志格式
option http_proxy      开启http 代理模式,只有最基本的代理功能
option ignore-persist { if | unless } <condition>       在某条件下拒绝持续连接,适用于对静态文件的负载均衡
option independant-streams      启用双向超时处理,如socket 的read 和write
option log-health-checks       记录健康检查日志
option log-separate-errors        对非完全成功的连接改变日志记录等级
option logasap       大传输大文件时可以提前记录日志
option mysql-check      mysql 健康检查
option nolinger       清除肮脏连接后开成的tcp 状态及占用的资源,不过并不是强列要求你用这个选项,当然如果你有thousands of FIN_WAIT1 sessions on your system ,那肯定得用了
option originalto [ except <network> ] [ header <name> ]      允许在requests中加入X-Original-To header 发往server
option persist       强制将http请求发往已经down 掉的server
option redispatch       是否允许重新分配在session 失败后, 即serverId对应的服务器挂掉后,强制定向到其他健康的服务器!
option smtpchk        smtp 检查;
option socket-stats       允许对单个socket进行统计;
option srvtcpka       是否允许向server 发送keepalive;
option tcpka        是否允许向server和client发送keepalive;
option tcplog       允许记录tcp 连接的状态和时间;
option transparent       允许客户端透明代理;
rate-limit sessions <rate> 设置frontend 每秒处理的连接的上限,如果到达上限就停止建立新的connection;

mode http                 所处理的类别 (#7层 http;4层tcp);
mode tcp                  所处理的类别 (#7层 http;4层tcp);
stats hide-version     隐藏统计页面上的HAproxy版本信息;

四. 代理配置段常见配置参数

4.1) Balance相关

balance:后端服务器组内的服务器调度算法
语法: balance <algorithm> [ <arguments> ]
            balance url_param <param> [check_post]

调度算法:
roundrobin:基于权重轮询,动态算法, 支持权重的运行时调整,支持慢启动;每个后端backend中最多支持4095个server; haproxy把请求轮流的转发到每一个服务器上,依据每台服务器的权重,此权重会动态调整。这是最常见的默认调度算法的配置。即客户端每一次访问, 都跳转到后端不同的服务器上.
static-rr:基于权重轮询,静态算法,不支持权重的运行时调整及慢启动;后端主机数量无上限;
leastconn:加权最少连接,动态算法,最少连接的后端服务器优先分配接收新连接,相同连接时轮询,推荐在较长会话的场景使用,例如MySQL、 LDAP等,不适合http;
first:根据服务器在列表中的位置,自上而下进行调度;前面服务器的连接数达到上限,新请求才会分配给下一台服务器;
hdr(name):对于每个http请求,此处由<name>指定的http首部将会被取出做hash计算; 并由服务器总权重相除以后派发至某挑出的服务器; 无有效值的会被轮询调度;
例:hdr(host)     hdr(Cookie)     

hash类算法:
需配合参数:hash-type <method> <function> <modifier>
method:
     map-based:除权取余法,哈希数据结构是静态数组;
     consistent:一致性哈希,哈希数据结构是一棵树;
source:源地址hash,新连接先按权重分配,后续连接按source分配请求; 如果想让haproxy按照客户端的IP地址进行负载均衡策略,即同一IP地址的所有请求都发送到同一服务器时,需要配置此选项。
uri:对URI的左半部分或整个uri做hash计算,并除以服务器总权重取模,以后派发至某挑出的服务器,适用于后端缓存服务器;
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
左半部分: /<path>;<params>
整个uri: /<path>;<params>?<query>#<frag>
url_param:对用户请求的uri听<params>部分中的参数的值(通常为用户ID)作hash计算,并由服务器总权重相除以后派发至某挑出的服务器;通常用于追踪用户,以确保来自同一个用户的请求始终发往同一个Backend Server;

Haproxy中balance的算法总结,见下表

4.2) server:定义后端主机相关选项
语法:
server <name> <address>[:[port]] [param*]
    <name>:服务器在haproxy上的自定义名称;出现在日志及警告信息
    <address>:服务器地址,支持使用主机名
    [:[port]]:端口映射;省略时,表示同bind中绑定的端口

[param*]:server后可加的参数
weight <weight>:权重,默认为1
maxconn <maxconn>:当前server的最大并发连接数
backlog <backlog>:当server的连接数达到上限后的后援队列长度
backup:设定当前server为备用服务器
check:对当前server做健康状态检测,只用于四层检测

注意: httpchk, “smtpchk”, “mysql-check”, “pgsql-check” and “sslhello-chk” 用于定义应用层检测方法
         addr :检测时使用的IP地址(检测的不一定是vip)
         port :针对此端口进行检测
         inter <delay>:连续两次检测之间的时间间隔,默认单位为毫秒,默认为2000ms
         rise <count>:连续多少次检测结果为“成功”才标记服务器为可用;默认为2
         fall <count>:连续多少次检测结果为“失败”才标记服务器为不可用;默认为3

disabled:标记为不可用
redir <prefix>:将发往此server的所有GET和HEAD类的请求重定向至指定的URL
cookie <value>:为当前server指定cookie值,实现基于cookie的会话黏性。

基于cookie的session sticky的实现

frontend http 
   bind 172.18.43.62:80               
   default_backend websrvs  

backend websrvs                   
   balance roundrobin 
   cookie SRV insert nocache 
   #自定义会话添加cookie信息SRV,insert:插入 nocache:不缓存增加保密性     
   server web1 192.168.43.61:80 check   weight 2 cookie srv1 #自定义该server添加cookie信息为srv1
   server web2 192.168.43.63:80 check   maxconn 5000 cookie srv2 #自定义该server添加cookie信息为srv2
   server sorroyserver 192.168.43.62:80 backup

4.3) 实现图形化配置页面
stats enable 添加这条参数后会在web页面启用统计页;在frontend段添加stats enable ,重启haproxy。浏览器访问172.18.43.62/haproxy?stats即可。

相关参数:
stats refresh <delay>   设定自动刷新时间间隔
若服务器出现故障,默认手动刷新才能才能看到状态的变化,可设置自动刷新
    例:添加stats refresh 2s
stats uri <prefix> 自定义stats page uri
默认为/haproxy?stats 可自定义uri
    例:stats uri  /hastas
重启后访问http://172.18.43.62/hastas即可
stats hide-version
如上图所示界面会显示haproxy版本信息,若想隐藏版本加上此参数即可
stats auth <user>:<passwd> 认证时的账号和密码,可使用多次。如多个用户定义多行即可,例:
    stats auth ha1:centos1
    stats auth ha2:centos2
stats realm <realm> 认证时浏览器弹出对话框的提示信息
    例:stats realm "haproxy info"
stats admin { if | unless } <cond> 启用stats page中的管理功能
    例:stats  admin  if TRUE
将stats分离出单独语句块,采用内网的6666端口提高访问安全性示例

listen admin
    bind 192.168.43.62:6666
    stats enable
    stats uri /status
    stats realm "haproxy info"
    stats auth ha1:centos
    stats hide-version
    stats refresh 5s
    stats admin if TRUE

访问http://192.168.43.62:6666/status

4.4) default中定义的内容
可以在frontend、backend、listen中分别进行定义,如没有指定将默认default中设置,如:
    maxconn <conns>:为指定的frontend定义其最大并发连接数;默认为3000
    mode { tcp|http|health } 定义haproxy的工作模式(默认http)
        tcp:基于layer4实现代理;可代理mysql, pgsql, ssh,ssl等协议,https时使用此模式,默认模式
        http:仅当代理协议为http时使用,centos实际默认模式
        health:工作为健康状态检查的响应模式,当连接请求到达时回应“OK”后即断开连接,较少使用
TCP模式的健康状态检测示例

listen ssh
    bind :22022
    balance leastconn
    mode tcp
    server sshsrv1 172.16.100.6:22 check
    server sshsrv2 172.16.100.7:22 check 

4.5) forwardfor配置
语法 :option forwardfor [ except <network> ] [ header <name> ] [ if-none ]
在由haproxy发往后端主机的请求报文中添加“X-ForwardedFor”首部,其值为前端客户端的地址;用于向后端主发送真实的客户端IP
    [ except <network> ]:请求报请来自此处指定的网络时不予添加此首部,如haproxy自身所在网络
    [ header <name> ]:使用自定义的首部名称,而非“XForwarded-For”
    [ if-none ] 如果没有首部才添加首部,如果有使用默认值
默认defaults中有一条配置option forwardfor       except 127.0.0.0/8
若想后端日志记录真实请求客户端IP,需更改后端两台服务器配置文件

[root@localhost ~]# vim /etc/httpd/conf/httpd.conf
LogFormat "%{x-forwarded-for}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" haformat 

#添加日志格式
CustomLog logs/access_log haformat #修改记录日志

重载客户端httpd服务,浏览器刷新请求。在客户端观看日志即可看到真实请求服务器

[root@localhost ~]# tail -f /var/log/httpd/access_log 

4.6) 自定义错误页面
① errorfile <code> <file>   自定义错误页
        <code>: HTTP status code.  支持200, 400, 403, 408, 500, 502, 503, 504.
        <file>:错误页文件路径
    例:errorfile 400 /etc/haproxy/errorfiles/400badreq.http
② rrorloc <code> <url>    相当于errorloc302 <code> <url>,利用302重定向至指URL
    例:errorloc 503 http://www.magedu.com/error_pages/503.html

4.7) 修改报文首部
① reqadd <string> [{if | unless} <cond>]    在请求报文尾部添加指定首部(用于web端区分从哪个调度器发来请求)
例:在frontend中添加  reqadd  X-via:\  haproxy1
后端修改httpd.conf中logformat添加%{X-via}i
再次访问日志就会看到是通过哪个调度器调度到本机
② rspadd <string> [{if | unless} <cond>]  在响应报文尾部添加指定首部 (用于haproxy之前的调度器查看用于排错)
示例: rspadd X-Via:\ HAPorxy
③ reqdel <search> [{if | unless} <cond>]
reqidel <search> [{if | unless} <cond>] (ignore case) 不分大小写
从请求报文中删除匹配正则表达式的首部
④ rspdel <search> [{if | unless} <cond>]
rspidel <search> [{if | unless} <cond>] (ignore case) 不分大小写
从响应报文中删除匹配正则表达式的首部
示例: rspidel Server.*  用于隐藏web服务器版本信息
rspadd Server:\ Apache 15.1 结合上例可伪造server信息

4.8) 定义连接超时
① timeout client <timeout>    客户端最长空闲连接超时时长 默认单位是毫秒
② timeout server <timeout>   后端服务器最长空闲连接超时时长
③ timeout http-keep-alive <timeout>    持久连接的持久时长
④ timeout http-request <timeout>     一次完整的HTTP请求的最大等待时长
⑤ timeout connect <timeout>     成功连接后端服务器的最大等待时长
⑥ timeout client-fin <timeout>   客户端半连接的空闲时长
⑦ timeout server-fin <timeout>     后端服务器半连接的空闲时长

五. ACL灵活转发详解
acl:访问控制列表(ACL)的使用提供了一个灵活的解决方案来执行内容交换,并且通常基于从请求中提取的内容、响应或任何环境状态进行决策,是haproxy的重要特色。

5.1) 语法
acl <aclname> <criterion> [flags] [operator] [<value>]...
<aclname>: ACL名称,可使用字母 数字 : . - _区分字符大小写
<criterion>: 比较的标准和条件
        dst 目标IP
        dst_port 目标PORT
        src 源IP
        src_port 源PORT
        示例: acl invalid_src src 172.16.100.200
<flags>
        -i 不区分大小写
        -m 使用指定的pattern匹配方法
        -n 不做DNS解析
        -u 强制每个ACL必须唯一ID,否则多个同名ACL或关系
        --   强制flag结束. 当字符串和某个flag相似时使用
[operator]
    匹配整数值: eq、 ge、 gt、 le、 lt
    匹配字符串:
        - exact match (-m str) :字符串必须完全匹配模式
        - substring match (-m sub) :在提取的字符串中查找如果包含, ACL将匹配
        - prefix match (-m beg) :在提取的字符串首部中查找模式,如果其中任何一个被发现, ACL将匹配
        - suffix match (-m end) :将模式与提取字符串的尾部进行比较,如果其中任何一个匹配,则ACL进行匹配
        - subdir match (-m dir) :查看提取出来的用斜线分隔(“/”)的字符串, 如果其中任何一个匹配,则ACL进行匹配
        - domain match (-m dom) :查找提取的用点(“.”)分隔字符串,如果其中任何一个匹配,则ACL进行匹配
<value>的类型:
    - boolean
    - integer or integer range
    - IP address / network
    - string (exact, substring, suffix, prefix, subdir,domain)
    - regular expression
    - hex block

5.2) 匹配条件<criterion>进阶
(1)base : string
返回第一个主机头和请求的路径部分的连接,该请求从第一个斜杠开始,并在问号之前结束,对虚拟主机有用;
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
    base : exact string match      #字符串匹配
    base_beg : prefix match       #前缀匹配
    base_dir : subdir match            #目录匹配
    base_dom : domain match       #域名匹配
    base_end : suffix match       #后缀匹配
    base_len : length match      #长度
    base_reg : regex match        #正则
    base_sub : substring match       #字符串

(2)path : string
提取请求的URL路径,该路径从第一个斜杠开始,并在问号之前结束(无主机部分);
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
    path : exact string match
    path_beg : prefix match
    path_dir : subdir match
    path_dom : domain match
    path_end : suffix match
    path_len : length match
    path_reg : regex match
    path_sub : substring match

例:acl adminpath path_beg  -i  /admin
acl imagefile  path_end  .jpg  .png   .bmp

(3)url : string
提取请求中的URL。 一个典型的应用是具有预取能力的缓存,以及需要从数据库聚合多个信息并将它们保存在缓存中的网页门户入口
    url : exact string match
    url_beg : prefix match
    url_dir : subdir match
    url_dom : domain match
    url_end : suffix match
    url_len : length match
    url_reg : regex match
    url_sub : substring match

(4)req.hdr([<name>[,<occ>]]) : string
提取在一个HTTP请求报文的首部
    hdr([<name>[,<occ>]]) : exact string match
    hdr_beg([<name>[,<occ>]]) : prefix match
    hdr_dir([<name>[,<occ>]]) : subdir match
    hdr_dom([<name>[,<occ>]]) : domain match
    hdr_end([<name>[,<occ>]]) : suffix match
    hdr_len([<name>[,<occ>]]) : length match
    hdr_reg([<name>[,<occ>]]) : regex match
    hdr_sub([<name>[,<occ>]]) : substring match

(5)status : integer
返回在响应报文中的状态码

5.3) acl作为条件时的逻辑关系
    - 与:隐式(默认)使用
    - 或:使用“or” 或 “||”表示
    - 否定:使用“!“ 表示

同一个组名可定义多次
示例:
    if invalid_src invalid_port       #与关系
    if invalid_src || invalid_port    #或
    if ! invalid_src                        #非

5.4) 预定义ACL(部分)

5.5) 配置block拒绝访问
语法:block { if | unless } <condition> 阻止7层请求if/unless一个条件匹配
例1

frontend http
   acl deny_src src 172.18.0.108 
   #自定义源地址为172.18.0.108的acl组deny_src 
   acl deny_port dst_port 80:100 
   #自定义目标端口为80到100的acl组deny_port
   block if deny_src || deny_port
   #如果属于deny_src组或deny_port组则拒绝访问
   block unless deny_src #如果不属于acl组deny_src则拒绝访问

例2(阻止curl访问)

acl bad_curl hdr_sub(User-Agent) -i curl
block if bad_curl

5.6) 指定backend组
语法:use_backend <backend> [{if | unless} <condition>]
当if/unless一个基于ACL的条件匹配时切换指定backend(可实现动静分离)
例1

acl imagefile path_end .jpg .png .bmp
acl appfile path_end .php
use_backend websrvs1 if imagefile
use_backend websrvs2 if appfile

例2

例3

acl webhost hdr(host) web.kevin.com
acl apphost hdr(host) app.kevin.com
use_backend websrvs if webhost
use_backend appsrvs if apphost

5.7) http 7层访问控制
语法:http-request { allow | deny |add-header <name> <fmt>|set-header <name> <fmt> } [ { if | unless }<condition> ]
对7层请求的访问控制

5.8) tcp4层连接控制
语法:tcp-request connection {accept|reject} [{if | unless} <condition>]
根据第4层条件对传入连接执行操作
例子

listen ssh
bind :22022
balance leastconn
acl invalid_src src 172.16.200.2
tcp-request connection reject if invalid_src
mode tcp
server sshsrv1 172.16.100.6:22 check
server sshsrv2 172.16.100.7:22 check backup

5.9) 配置HAProxy支持https协议
① 支持ssl会话;
bind *:443 ssl crt /PATH/TO/SOME_PEM_FILE
crt 后证
为实验方便自签证书方法:
在etc/pki/tls/certs/目录下执行make命令可获得同时包含证书和所有私钥的证书

[root@localhost ~]# cd /etc/pki/tls/certs/
[root@localhost ~]# make /etc/haproxy/haproxy.pem

证书和私钥分离的情况可通过重定向获得:cat demo.crt demo.key > demo.pem
② 把80端口的请求重向定443
bind *:80
redirect scheme https if !{ ssl_fc }  #注意花括号里面有空格
③ 向后端传递用户请求的协议和端口(frontend或backend)
http_request set-header X-Forwarded-Port %[dst_port]
http_request add-header X-Forwared-Proto https if { ssl_fc }
例子

测试

向后端传递用户请求

修改后端httpd.conf中日志格式即可

六. 基于ACL的动静分离示例

frontend web *:80
           acl url_static path_beg -i /static /images /javascript /stylesheets
           acl url_static path_end -i .jpg .gif .png .css .js .html .txt .htm
           use_backend staticsrvs if url_static
           default_backend appsrvs
backend staticsrvs
           balance roundrobin
           server stcsrv1 172.16.100.6:80 check
backend appsrvs
           balance roundrobin
           server app1 172.16.100.7:80 check
           server app1 172.16.100.7:8080 check
listen stats
          bind :9091
          stats enable
          stats auth admin:admin
          stats admin if TRUE

                                                                      分享一个小案例                                                                    
如下的一个haproxy代理需求:

1) 域名跳转
客户端访问http://beijing.kevin.com时,要把请求分发到172.16.51.171:8080、172.16.51.174:8080、172.16.51.178:8080,这三台服务器上。
客户端访问http://anhui.kevin.com时,要把请求分发到web01.kevin.com这台服务器上。

2) IP地址跳转
客户端访问http://172.16.51.171时,要把请求分发到172.16.51.174:80、172.16.51.178:80这两台服务器上。同时还要求客户端每一次访问,都跳转到不同的服务器上。

2.3) 端口跳转
客户端访问http://beijing.kevin.com:8090和http://anhui.kevin.com:8090这两个地址时,要把请求分发到172.16.51.174:8090、172.16.51.178:8090这两台服务器上。

2.4) 默认跳转
如果客户端访问的不是beijing.kevin.com与172.16.51.171,这两个地址的话,要把请求全部分发到172.16.51.178:8080上。

2.5) 多ACL匹配
如果客户端的IP是172.16.51.140,同时访问的是http://172.16.51.171时,要把请求分发到www.anhui.com上。

proxy.cfg配置内容如下:

[root@localhost ~]# vim /etc/haproxy/haproxy.cfg
global
   log 127.0.0.1 local0
   log 127.0.0.1 local1 notice
   maxconn 4096
   uid 1005
   gid 1005
   daemon
 
defaults
   log global
   mode http
   option httplog
   option dontlognull
   retries 3
   option redispatch
   maxconn 2000
   contimeout 5000
   clitimeout 50000
   srvtimeout 50000
 
listen admin_stats
   bind 172.16.51.171:1080
   mode http
   option httplog
   maxconn 10
   stats refresh 30s
   stats uri /stats
   stats auth admin:admi
   stats hide-version
 
frontend weblb
   bind *:80
   acl is_beijing hdr_beg(host) beijing.kevin.com
   acl is_anhui hdr_beg(host) anhui.kevin.com
   acl is_171 hdr_beg(host) 172.16.51.171
   acl is_ip src 172.16.51.140
   use_backend acl if is_171 is_ip
   use_backend beijingserver if is_beijing
   use_backend anhui if is_anhui
   use_backend 171server if is_171
   default_backend backend_default
 
backend beijingserver
   balance source
   server web1 172.16.51.171:8080 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3
   server web2 172.16.51.174:8080 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3
   server web3 172.16.51.178:8080 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3
 
backend 171server
   balance roundrobin
   server beijing1 172.16.51.174:80 check
   server beijing2 172.16.51.178:80 check
 
backend anhui
   server web1 web01.kevin.com:80 weight 3 check inter 2000 rise 2 fall 3

backend acl
   balance source
   server web1 www.anhui.com:80 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3
 
backend backend_default
   server web1 172.16.51.178:8080 weight 3 check inter 2000 rise 2 fall 3
 
listen 8090
   bind 0.0.0.0:8090
   mode http
   balance roundrobin
   server web1 172.16.51.174:8090 maxconn 1024 weight 5 check inter 2000 rise 2 fall 3
   server web2 172.16.51.178:8090 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3

                                                                       补充下ACL规则的一些说明                                                                    

ACL(Access Control List)访问控制列表,HAProxy中的ACL的匹配条件和控制条件有许多种,功能很强大,可以通过源地址、源端口、目标地址、目标端口、请求的资源类型、请求的主机等。

haproxy的ACL用于实现基于请求报文的首部、响应报文的内容或其它的环境状态信息来做出转发决策,这大大增强了其配置弹性。其配置法则通常分为两 步,首先去定义ACL,即定义一个测试条件,而后在条件得到满足时执行某特定的动作,如阻止请求或转发至某特定的后端。
定义ACL的语法格式acl <aclname> <criterion> [flags] [operator] [<value>] 

aclname:自定义acl的名称,必填项,只能是大小写、数字、'-'、'_'、'.'、':' , 也就是说这个是定义ACL名称,区分字符大小写,且其只能包含大小写字母、数字、-(连接线)、_(下划线)、.(点号)和:(冒号);haproxy中,acl可以重名,这可以把多个测试条件定义为一个共同的acl;
criterion:表示检查那些数据或内容,例如USERAGENT这个首部的值. 测试标准,即对什么信息发起测试;测试方式可以由[flags]指定的标志进行调整;而有些测试标准也可以需要为其在<value>之前指定一个操作符[operator];
    四个最为常用的criterion为:
     src:ip 源IP
     src_port:integer 源端口
     dst:ip 目标IP
     dst_port:integer 目标端口
flags:定义控制条件,例如是否区分字符大小写等,flags的可选参数如下:
     -i   忽略字符大小写
     -m   启用特定的匹配方式,一般不用
     -n   禁止DNS反向解析
     -u   不允许aclname重复,默认是可以重名的,当两个acl的名称相同时,运算为或机制。
            --    标志符的强制结束标记,在模式中的字符串像标记符时使用;
operator:判断匹配条件,与<criterion>相比较的条件
    若匹配整数值:eq,ge,gt,le,lt
    若匹配字符串:
value: 访问控制的具体内容或值。这是acl测试条件支持的值。value的类型如下:
    boolean:布尔值
    integer or integer range:整数或整数范围. 如1024:65535表示从1024至65535;仅支持使用正整数(如果出现类似小数的标识,其为通常为版本测试),且支持使用的操作符有5个,分别为eq、ge、gt、le和lt;
    IP address/network:网络地址
    string(exact, substring, suffix, prefix, subdir, domain):字符串. 支持使用“-i”以忽略字符大小写,支持使用“\”进行转义;如果在模式首部出现了-i,可以在其之前使用“--”标志位;  
    regular expression:正则表达式
    hex block

同一个acl中可以指定多个测试条件,这些测试条件需要由逻辑操作符指定其关系。条件间的组合测试关系有三种:“与”(默认即为与操作)、“或”(使用“||”操作符)以及“非”(使用“!”操作符);

常用的测试标准(criteria):
1) be_sess_rate(backend) <integer>
用于测试指定的backend上会话创建的速率(即每秒创建的会话数)是否满足指定的条件;常用于在指定backend上的会话速率过高时将用户请求转发至另外的backend,或用于阻止攻击行为。例如:
     backend dynamic
          mode http
          acl being_scanned be_sess_rate gt 50
          redirect location /error_pages/denied.html if being_scanned
2) fe_sess_rate(frontend) <integer>
用于测试指定的frontend(或当前frontend)上的会话创建速率是否满足指定的条件;常用于为frontend指定一个合理的会话创建速率的 上限以防止服务被滥用。例如下面的例子限定入站邮件速率不能大于50封/秒,所有在此指定范围之外的请求都将被延时50毫秒。
      frontend mail
          bind :25
          mode tcp
          maxconn 500
          acl too_fast fe_sess_rate ge 50
          tcp-request inspect-delay 50ms
          tcp-request content accept if ! too_fast
          tcp-request content accept if WAIT_END
3) hdr(header) <string>
用于测试请求报文中的所有首部或指定首部是否满足指定的条件;指定首部时,其名称不区分大小写,且在括号“()”中不能有任何多余的空白字符。测试服务器 端的响应报文时可以使用shdr()。例如下面的例子用于测试首部Connection的值是否为close。
          hdr(Connection) -i close
4) method <string>
测试HTTP请求报文中使用的方法。
5) path_beg <string>
用于测试请求的URL是否以<string>指定的模式开头。下面的例子用于测试URL是否以/static、/iilannis、/javascript或/stylesheets头。
        acl url_static path_beg -i /static /iilannis /javascript /stylesheets
                                     #url 目录
6) path_end <string>
用于测试请求的URL是否以<string>指定的模式结尾。例如,下面的例子用户测试URL是否以jpg、gif、png、css或js结尾。
       acl url_static path_end -i .jpg .gif .png .css .js
                                    #url 结尾文件
7) hdr_beg <string>
用于测试请求报文的指定首部的开头部分是否符合<string>指定的模式。例如,下面的例子用记测试请求是否为提供静态内容的主机img、video、download或ftp。
       acl host_static hdr_beg(host) -i img. video. download. ftp.
8) hdr_end <string>
用于测试请求报文的指定首部的结尾部分是否符合<string>指定的模式。例如,下面的例子用记测试请求是否为
9) hdr_reg <string>
正则匹配
       acl bbs hdr_reg(host) -i ^(bbs.test.com|shequ.test.com|forum)
            use_backend bbs_pool if bbs or bbs_path #注意 "or"

                                                     Haproxy 会话保持 (三种方式)                                                          

Haproxy保持客户端session会话同步的三种方式梳理如下:

============第一种方式: 源地址hash(用户IP识别)==========
haroxy 将用户IP经过hash计算后 指定到固定的真实服务器上(类似于nginx 的IP hash 指令)。
缺陷: 当后端一台服务器挂了以后会造成部分session丢失。

配置示例:

backend SOURCE_srv
  mode   http
  balance  source
  server app-node1  172.16.60.179:80  check port 80 inter 3000  rise 3  fall 3
  server app-node2  172.16.60.191:80  check port 80 inter 3000  rise 3  fall 3
  server app-node3  172.16.60.135:80  check port 80 inter 3000  rise 3  fall 3  

===========第二种方式: cookie 识别 ===========
haproxy 将WEB服务端返回给客户端的cookie中插入haproxy中特定的字符串(或添加前缀)在后端的服务器cookie id。

配置指令例举: cookie SESSION_COOKIE insert indirect nocache
用firebug可以观察到用户的请求头的cookie里 有类似" Cookie jsessionid=0bc588656ca05ecf7588c65f9be214f5;SESSION_COOKIE=app1"
其中SESSION_COOKIE=app1就是haproxy添加的内容。

配置示例:

backend COOKIE_srv
   mode    http
   cookie SERVERID insert indirectnocache
   server app-node1 172.16.60.179:80 check  port 80 cookie  a  inter 3000  rise 3  fall 3
   server app-node2 172.16.60.191:80 check  port 80 cookie  b  inter 3000  rise 3  fall 3
   server app-node3 172.16.60.135:80 check  port 80 cookie  c  inter 3000  rise 3  fall 3

cookie参数说明:
cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ] [ postonly ] [ preserve ] [ httponly ] [ secure ] [ domain <domain> ]* [ maxidle <idle> ] [ maxlife <life> ]

特别注意:   rewrite | insert | prefix   这三个参数相互排斥,只能选一!
rewrite: 表示cookie由服务器生成并且haproxy会在其值中注入该服务器的标识符;此关键字不能在HTTP隧道模式下工作。

insert: 表示如果客户端没有cookie信息且有权限访问服务器时,持久性cookie必须通过haproxy穿插在服务器的响应报文中。当服务器收到相同名称的cookie并且没有“preserve(保存)”选项时,将会移除之前已存的cookie信息。因此,insert可视作"rewrite"的升级版。cookie信息仅仅作为会话cookie且不会存到客户端的磁盘上。默认除非加了“indirect(间接)”选项,否则服务器端会看到客户端端发送的cookie信息。由于缓存的影响,最好加上“nocache”或“postonly”选项。

prefix: 表示不依赖专用的cookie做持久性,而是依赖现成的。用在某些特殊的场景,如客户端不支持一个以上的cookie和应用程序需求它。每当服务器建立一个名为<name>的cookie时,它将以服务器的标识符和分隔符为前缀。来自于客户端的请求报文中的前缀将会被删除以便服务器端能识别出它所发出的cookie,由于请求和响应报文都被修改过,所以此模式不能工作在隧道模式中。且不能和“indirect”共用,否则服务器端更新的cookie将不会被发到客户端.

indirect: 指定此选项时,将不会向客户端发送服务器已经处理过请求的且可用的cookie信息。如果服务器设置这样一个cookie本身,它将被删除,除非“保存”选项也设置。在“插入”模式下,将从发送给服务器的请求中删除cookie,使持久机制从应用程序的角度完全透明。

nocache: 当客户端和haproxy间存在缓存时,使用此选项和insert搭配最好,以便确保如果一个cookie需要被插入时,可被缓存的响应会被标记成不可缓存。这很重要,举个例子:如果所有的持久cookie被添加到一个可缓存的主页上,之后所有的客户将从外部高速缓存读取页面并将共享相同的持久性cookie,会造成服务器阻塞。

在LB服务器上配置好HAProxy后,LB服务器将接受用户的所有请求。如果一个用户请求不包含任何cookie,那这个请求将被HAProxy转发到一台可用的WEB服务器。可能是webA,webB,webC或webD。然后HAProxy将把处理这个请求的WEB服务器的cookie值插入到请求响应中。如SERVERID=A。当这个客户端再次访问并在HTTP请求头中带有SERVERID=A,HAProxy将会把它的请求直接转发给webA处理。在请求到达webA之前,cookie将被移除,webA将不会看到这个cookie。如果webA不可用,对应的请求将被转发到其他可用的WEB服务器,相应的cookie值也将被重新设置。

==============第三种方式: 基于session识别 ============
haproxy 将后端服务器产生的session和后端服务器标识存在haproxy中的一张表里。客户端请求时先查询这张表。
配置参数:appsession JSESSIONID len 64 timeout 5h request-learn

配置示例:

backend APPSESSION_srv
    mode    http
    appsession JSESSIONID len 64 timeout 5h request-learn
    server REALsrv_70     172.16.60.70:80 cookie 11 check inter 1500 rise 3 fall 3 weight 1
    server REALsrv_120   172.16.60.120:80 cookie 12 check inter 1500 rise 3 fall 3 weight 1

注意使用事项
1) 如果客户端使用HTTP1.1(keep-alive),只有第一个响应才会被插入cookie,并且HAProxy只会分析每个session的第一个请求。在使用cookie的插入模式下,可能不会造成什么问题,因为HAProxy会立即在第一个响应中插入cookie,同一个session中的所有请求将被转发到同一台服务器上。但是,到达服务器端的请求中的cookie不会被删除,所以这要求后端服务器对来历不明的cookie不作敏感处理。如果不想引起其他的问题,可以使用"option httpclose"参数关掉keep-alive

2) 由于一些原因,一些客户端不能识别多个cookie,并且后端应用已经设置了cookie,如果HAProxy再对响应插入cookie后,这些客户端可能不能识别cookie。这种情况下,可以使用cookie的prefix模式。

3) LB服务器成为整个架构中的瓶颈,如果LB不可用,那么客户端的所有请求都得不到响应。可以使用Keepalived配置HAProxy解决LB单点故障的问题。
4) 在以上配置中后端服务器是看不到客户端的真实IP地址的; 可以使用 forwardfor 参数,它能够在客户端的请求头中增加 X-Forwarded-For 字段; 同时需要配置使用 httpclose 参数,确保每个请求都被重写,而不只是第一个请求被重写。即使用配置下面两个参数来实现.

option httpclose
option forwardfor

后端Realserver的WEB服务器上的Nginx的日志格式需要增加$http_x_forwarded_for 变量

log_format  main  ‘$remote_addr - $remote_user [$time_local] "$request" ‘
         ‘$status $body_bytes_sent "$http_referer" ‘
        ‘"$http_user_agent" "$http_x_forwarded_for"‘;

5) 在有些情况下,一些用户会将他们的浏览器的cookie功能关闭。这时候可能没法访问WEB服务器的内容。这种情况下,可以使用HAProxy的 source 负载均衡算法替代 roundroubin算法。source 算法可以确保来自同一个IP的所有请求都到达同一台WEB服务器,但是前提是,可用的服务器的数量保持不变。

6) 不要在一个小型网络和代理服务器后面使用source 算法,因为请求分发会不太公平,但是在大型内部网络或互联网上使用source算法,转发效率很好。对于那些具有动态IP地址的客户端,只要它们能够接收cookie,那么请求转发就不会受到影响,因为HAProxy对cookie的处理具有较高优先级。

===========================================================================================
以上总结的指令和参数都是为了设置或定义ACL匹配条件的,即ACL仅仅只是将匹配条件进行分类归纳而不进行处理。若要将定义好的ACL规则做处理,需下面参数来设置

1) 当符合指定的条件时使用特定的backend,<backend>表示设置的backend名,if和unless为判断条件,<condition>为比较的对象,可以是ACL规则,要注意的是在if和unless后面可以接两个ACL,默认表示两个ACL同时满足时才use_backend执行。格式如下

use_backend <backend> [{if | unless} <condition>] #Switch to a specific backend if/unless an ACL-based condition is matched.

2) 阻塞一个七层请求满足/不满足某一ACL匹配条件。格式如下

block { if | unless } <condition> #Block a layer 7 request if/unless a condition is matched

例如

acl invalid_src src 192.18.29.101  #acl匹配条件为源地址为192.18.29.101,acl名为invalid_src
block if invalid_src                        #阻断满足名为invalid_src的acl匹配条件
errorfile 403 /etc/fstab                  #并定义错误页

3) 配置七层的请求访问控制,与block阻塞不同,http-request更灵活,可做黑白名单控制。只能用在mode http中. 

http-request { allow | deny } [ { if | unless } <condition> ]

4) 配置四层的请求访问控制

tcp-request connection {accept|reject}  [{if | unless} <condition>]

例如:

listen ssh
bind :22022
balance leastconn
acl invalid_src src 172.16.200.2         #定义acl匹配规则
tcp-request connection reject if invalid_src  #在四层拒绝满足名为invalid_src的acl匹配规则
mode tcp
server sshsrv1 172.16.100.6:22 check
server sshsrv2 172.16.100.7:22 check        

=======ACL示例======
要注意到的是acl关键字可用在frontend、listen、backend中,不能用在default中。

例1:设置HAProxy状态页,只允许指定IP访问,设置如下

listen stats #定义名称
        bind *:9099 #监听在9099端口
        acl sta src 192.168.29.1 #匹配名为sta且源IP地址为192.168.29.1的ACL规则
        block if ! sta #阻断不匹配sta规则的所有条件,!为非
        stats enable #启用stats页
        stats uri /myhaproxy?admin #自定义stats页面uri
        stats realm "Hello World" 
        stats auth admin:admin #设置状态页登录账号和密码

说明只有来源为192.168.29.1的机器才能访问这个haproxy的stats状态, 访问地址假设为http://192.168.29.101:9099/myhaproxy?admin

例2:不适用block,使用http-request来达到例1的效果。
在没有设置访问规则限制时,用IP为192.168.29.104的主机访问stats主页

提示错误401,只需输入账号密码即可访问,方法为

curl --basic -u admin:admin http://192.168.29.101:9099/myhaproxy?admin

说明IP为29.104的主机可以访问,并无限制。
添加限制后

listen stats      #定义名称
        bind *:9099    #监听在9099端口
        acl sta src 192.168.29.1     #匹配名为sta且源IP地址为192.168.29.1的ACL规则
        http-request deny unless sta      #拒绝除匹配sta规则以外的规则访问
        stats enable      #启用stats页
        stats uri /myhaproxy?admin     #自定义stats页面uri
        stats realm "Hello World" 
        stats auth admin:admin     #设置状态页登录账号和密码

再用IP为29.104的主机访问效果如下

此时错误为403,而29.1的主机是可以访问的(图太大了就省略了),说明ACL控制生效了。

例3: 七层规则匹配
七层ACL规则匹配中,常用的参数是path,它用来做URL规则匹配,path包括以下参数:
path :   精确匹配
path_beg :   匹配字符串开头的所有内容
path_dir :   子路径匹配
path_dom :  域名匹配
path_end :   匹配字符串结尾的所有内容
path_len :   字符串长度匹配
path_reg :   正则表达式匹配
path_sub :  域名子串匹配

下面来举一个使用path的具体例子,选两台主机,安装Nginx并用Nginx虚拟为4台主机,两台用来处理图片请求,两台用来处理文本请求,利用HAProxy负载均衡的ACL控制机制实现,结构图如下:

1) 在192.168.29.102上添加监听8080端口的虚拟主机(安装的是Nginx),修改Nginx配置,在主配置中添加如下信息

server {
        listen       80 default_server;
        listen       [::]:8080 default_server;
        server_name  _;
        root         /usr/share/nginx/html/test; #路径要修改,尽量不使用默认,尽量模拟为两台不同物理机的效果

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

2) 在80端口的主机root目录下创建文件static.txt,内容为static 1;在8080端口主机root目录下创建文件static.txt,内容为static 2。重启Nginx服务,并确保能正常访问,如下图

3) 用同样的方法在192.168.29.103上创建分别监听在80和8080端口的虚拟主机,并在根目录下创建图片文件,确保能正常访问,如下图:

 4) 在主机192.168.29.101上配置HAProxy

frontend myweb
        bind *:80
        acl image path_end .png #匹配以.png结尾的path规则
        acl txt path_end .txt #匹配以.txt结尾的path规则
        use_backend imagesv if image #将规则image负载均衡到服务器组imagesv
        use_backend txtsv if txt  #将规则txt负载均衡至服务器组txtsv
        default_backend app #默认组,无匹配时负载均衡至此

backend imagesv
        balance roundrobin
        server image1 192.168.29.103:80 check
        server image2 192.168.29.103:8080 check

backend txtsv
        balance roundrobin
        server txt1 192.168.29.102:80 check
        server txt2 192.168.29.102:8080 check

backend app
        balance leastconn
        cookie server insert  nocache
        server app1 192.168.29.102:80 check cookie svr1
        server app2 192.168.29.103:80 check cookie svr2

配置完成后重启HAProxy,分别访问192.168.29.101/image.png和192.168.29.101/static.txt,并刷新,会发现内容会不停变化,如下图

这说明ACL规则培植成功,HAProxy会根据请求的结尾来判断负载均衡规则。
简单总结:  上面举了3个很简单的HAProxy ACL访问控制的例子,虽然例子中的配置很粗糙,但也可以初步领略到HAProxy有着比较智能的负载均衡功能,在后面的博客中我会更深入的介绍HAProxy的细节配置与调优

================Haproxy ACL规则小例==============
1) 按请求的主机头(名)负载
[root@localhost ~]# cat haproxy.cfg

global 
    log 127.0.0.1 local1 
    maxconn 65000             #最大连接数 
    chroot /usr/local/haproxy #安装目录 
    uid 99                    #用户haproxy 
    gid 99                    #组haproxy 
    daemon                    #守护进程运行 
    nbproc 1                  #进程数量 
    pidfile /usr/local/haproxy/logs/haproxy.pid #haproxy pid 
 
defaults 
   log     global 
   mode    http               #7层 http;4层tcp  
   option  httplog            #http 日志格式 
   option  httpclose          #主动关闭http通道 
   option  redispatch         #serverId对应的服务器挂掉后,强制定向到其他健康的服务器 
   option  forwardfor 
   option  dontlognull 
   maxconn 50000              #最大连接数 
   contimeout      5000       #连接超时(毫秒) 
   clitimeout      50000      #客户端超时(毫秒) 
   srvtimeout      50000      #服务器超时(毫秒) 
 
   #errorfile 502 /usr/local/haproxy/html/maintain.html 
   #errorfile 503 /usr/local/haproxy/html/maintain.html 
   #errorfile 504 /usr/local/haproxy/html/maintain.html 
  
 
frontend test.com             #定义前端服务器(haproxy) 
        bind *:80             #监听地址 
        acl web-client path_beg -i /vsphere-client 
        acl bbs hdr_reg(host) -i ^(bbs.test.com|shequ.test.com|forum) 
        acl monitor hdr_beg(host) -i monitor.test.com    #定义ACL名称,对应的请求的主机头是monitor.test.com  
        acl www hdr_beg(host) -i www.test.com 
        use_backend  cache.test.com if static    
        use_backend  monitor.test.com if bbs or monitor 
        use_backend  www.test.com if www 
        use_backend  vsphere-client if web-client 
 
        default_backend www.test.com  #指定默认的后端服务器 
 
 
backend monitor.test.com              #定义后端服务器群(web server/apache/nginx/iis..) 
        mode http 
        option  forwardfor    #后端服务器(apache/nginx/iis/*),从Http Header中获得客户端IP 
        balance leastconn     #负载均衡的方式,最小连接 
        cookie SERVERID       #插入serverid到cookie中,serverid后面可以定义 
        option  httpchk HEAD /check.html #用来做健康检查html文档 
        #option httpchk HEAD /index.php HTTP/1.1\r\nHost:monitor.test.com #HTTP && Host 
        server server1 10.0.100.70:80 cookie server1 check inter 2000 rise 3 fall 3 weight 3 
        #服务器定义: 
        #cookie server1表示serverid为server1; 
        #check inter 2000 是检测心跳频率(check 默认 ); 
        #rise 3 表示 3次正确认为服务器可用; 
        #fall 3 表示 3次失败认为服务器不可用; 
        #weight 表示权重。 
 
backend www.test.com 
        mode http 
        option  forwardfor 
        balance roundrobin    #负载均衡的方式,轮询方式 
        cookie SERVERID   
        option  httpchk HEAD /check.html  
        server server1 10.0.100.71:80 cookie server1 check inter 2000 rise 3 fall 3 weight 3 
 
backend vsphere-client 
        mode http 
        option  forwardfor header ORIG_CLIENT_IP 
        balance roundrobin 
        server server1 10.0.100.81:80 redir https://192.168.57.81:443 check inter 2000 rise 3 fall 3 weight 3 
 
backend cache.test.com 
        option  forwardfor 
        #balance uri len 15 #url hash 
        balance roundrobin 
        server server1 10.0.100.73:80  check inter 2000 rise 3 fall 3 weight 3 
        server server2 10.0.100.75:80  check inter 2000 rise 3 fall 3 weight 3 
 
listen admin_stat                   #status 
    bind 0.0.0.0:8080               #监听端口 
    mode http                       #http的7层模式 
    stats refresh 30s               #统计页面自动刷新时间 
    stats uri /haproxy_stats_url    #统计页面URL 
    stats realm Haproxy\ Statistics #统计页面密码框上提示文本 
    stats auth admin:admin          #统计页面用户名和密码设置 
    stats hide-version              #隐藏统计页面上HAProxy的版本信息 
    stats admin if TRUE             #手工启用/禁用,后端服务器 

2) 其它ACL规则

###########acl 开始了############ 
acl bbs       hdr_reg(host) -i ^(bbs.test.com|forum.test.com)  #使用正则匹配 
acl bbs_path  path_beg -i /bbs                #url 目录 
acl youxi     path_beg -i /youxi               
acl static    path_end -i .html .css .js      #url 结尾文件 
acl php       path_end -i .php  
acl jsp       path_end -i .jsp .do  
 
use_backend bbs_pool if bbs or bbs_path       #注意 "or"  
use_backend youxi_pool if youxi 
use_backend static_pool if static  
use_backend php_pool if php 
use_backend jsp_pool if jsp 
default_backend www.test.com                 
###########acl 结束了############ 

use_backend 参数
or      用于匹配多个acl 名称
default_backend     没有满足条件的时候使用默认的后端服务器

========HAProxy 七层层模型下强大的ACL规则配置示例========

global
    maxconn     20000
    #设定HAProxy进程可接受的最大并发数
    ulimit-n    41000
    #linux命令行选项,等同于上参数
    log         127.0.0.1 local0
    #全局的日志中配置,local0 是日志设备 info(err,warnig,minfo,debug)为日志级别,使用rsyslog
    uid         200
    gid         200
    #用户和组 ,可以用uid,gid代替
    chroot      /var/empty
    nbproc      1
    #HAProxy启动时可创建的进程数,配合daemon参数使用,默认只启动一个进程,该值应小于cpu核数。
    daemon
    #进程后台运行,(推荐模式)
 
defaults
    mode        http
    retries     3
    timeout     connect 10s
    timeout     client  20s
    timeout     server  30s
    timeout     check   5s
 
listen  admin_stats
    bind        *:9188
    mode        http
    log         global
    stats       refresh 30s
    stats       uri /haproxy-status
    stats       realm welcome login\ Haproxy
    stats       auth    admin:admin~!@
    stats       hide-version
    stats       admin if TRUE
 
frontend test-proxy
    bind        *:80
    mode        http
    log         global
    option      httplog
    option      forwardfor
    option      httpclose
    #HAProxy在完成一次请教请求连接后,将主动关闭该连接,对性能非常有帮助
    option      dontlognull
    option      nolinger
    option      http_proxy
    maxconn     8000
    timeout client  30s
 
    #layer3: Valid users
    #acl allow_host src 192.168.200.150/32
    acl allow_host src 192.168.10.0/24
    #acl allow_host src 0.0.0.0/24
    http-request deny if !allow_host
 
   #layer7: prevent private network relaying
   #acl forbidden_dst url_ip 192.168.0.0/24
   #acl forbidden_dst url_ip 172.16.0.0/12
    acl forbidden_dst url_ip 192.168.20.0/24
    http-request deny if forbidden_dst
    acl host_a hdr_reg(host) -i www.a.cn
    acl host_b hdr_dom(host) -i www.b.cn
    acl url_policy  url_sub -i buy_sid
 
    use_backend test-proxy-srv-a    if  host_a
    use_backend test-proxy-srv-b    if  host_b
    use_backend test-proxy-srv-c    if  url_policy
    default_backend test-proxy-srv-default
 
backend test-proxy-srv-default
    mode        http
    retries     2
    option      redispatch
    option      abortonclose
    option      nolinger
    option      http_proxy
   #option      httpchk GET /index.php
    balance     roundrobin
    cookie      SERVERID
    server web0 192.168.10.101:8999 cookie  server0 weight 4    check inter 2000 rise 2 fall 3
 
backend test-proxy-srv-a
    mode            http
    timeout connect 5s
    timeout server  5s
    retries         2
    option      redispatch
    #应用于cookie保持的环境
    option      abortonclose
    #自动结束长时间连接
    option          nolinger
    option          http_proxy
   #option      httpchk GET /index.php
    balance     roundrobin
    cookie      SERVERID
    server web1 192.168.10.101:8080 cookie  server1 weight 6 check inter 2000 rise 2 fall 3
    server web2 192.168.10.101:8888 cookie  server2 weight 6 check inter 2000 rise 2 fall 3
 
backend test-proxy-srv-b
    mode        http
    retries     2
    option      redispatch
    option      abortonclose
    option      nolinger
    option      http_proxy
   #option      httpchk GET /index.php
    balance     roundrobin
    cookie      SERVERID
    server web3 192.168.10.182:8080 cookie  server3 weight 8 check inter 2000 rise 2 fall 3
 
backend test-proxy-srv-c
    mode        http
    retries     2
    option      redispatch
    option      abortonclose
    option      nolinger
    option      http_proxy
   #option      httpchk GET /index.php
    balance     roundrobin
    cookie      SERVERID
    server web4 192.168.10.182:8888 cookie  server4 weight 6 check inter 2000 rise 2 fall 3
 
    #layer7: Only GET method is valid
    acl valid_method        method GET
    acl valid_method    method POST
    http-request deny if !valid_method
 
    #layer7: protect bad reply
    http-response deny if { res.hdr(content-type) audio/mp3 }

以上haproxy.cfg配置文件的acl控制主要是在frontend里设置:
acl host_a hdr_reg(host) -i ^(www.a.cn|a.cn)
acl host_b hdr_dom(host) -i www.b.cn
acl url_policy url_sub -i buy_sid

use_backend test-proxy-srv-a if host_a
use_backend test-proxy-srv-b if host_b
use_backend test-proxy-srv-c if url_policy
default_backend test-proxy-srv-default

第一个acl控制,当主机为www.a.cn或者a.cn时,规则返回TRUE,对应第一个use_backend 请求访问后端服务器池test-proxy-srv-a
第二个acl控制,当主机为www.b.cn时,规则返回TRUE,对应第二个use_backend请求访问后端服务器池test-proxy-srv-b
第三个acl控制,当请求url路径出现buy_sid 字符串时,规则返回TRUE,对应第三个use_backend请求访问后端服务器池test-proxy-srv-c
当所有规则均不为TRUE时,请求访问默认后端服务器池test-proxy-srv-default

当然acl还有更多的用法,如下:
acl url_static path_end .gif .png .jpg .css .js
acl host_www hdr_beg(host) -i  www
acl host_static hdr_beg(host) -i img. video. download. ftp.

use_backend static if host_static || host_www url_static
use_backend www if host_www
default_backend server_cache

第一个acl,通过path_end参数定义请求的url以.gif,.png,.jpg,.css,.js结尾时返回TRUE
第二个acl,通过hdr_beg(host)参数定义如果客户端以www开头的域名发送请求时返回TRUE
第三个acl,也是通过hdr_beg(host)参数定义以img.,video.,download.,ftp.开头域名发送请求返回TRUE
第四行backend,定义了当请求需同时满足host_static与url_static时,或者满足host_www与url_static时请求将发往名为static 的backend
第五行backend,定义了当请求满足host_www规则时,请求发往名为www的backend
第六行backend,定义将用户请求默认调度到名为server-cache的backend

以上就是Haproxy的ACL常用控制用法,基本上可以满足日常负载需求。

========================设置haproxy负载均衡的最大并发连接数=======================

从三个方面来进行设置
a) 查看内核
[root@haproxy-test ~]# sysctl -a | grep file
fs.file-nr = 1024       0       386459
fs.file-max = 386459

b) 查看应用层面的需求
[root@haproxy-test ~]# vim /usr/local/haproxy/conf/haproxy.cfg
global                                                   #全局参数设置
        maxconn         65535                    #设置最大连接数

c) 更改系统层面
[root@haproxy-test ~]# vim /etc/security/limits.conf                #最后一行增加
*                -       nofile          65535

===========================下面分析一个haproxy的负载均衡配置=============================

global
   log 127.0.0.1 local3
   chroot /etc/haproxy
   pidfile /var/run/haproxy.pid
   user haproxy
   group haproxy
   daemon
   nbproc 1         #单进程
   tune.ssl.default-dh-param 2048

defaults
   log global
   mode http
   maxconn 20480    #最大连接数
   balance roundrobin
   retries 3
   option httplog
   option httpclose
   option forwardfor
   option dontlognull
   option redispatch
   timeout connect 5000
   timeout client 50000
   timeout server 50000
   timeout check 1000 #心跳检测超时

listen web_status
   bind 0.0.0.0:9088
   mode http
   option httplog
   option dontlognull
   option logasap
   option forwardfor
   option httpclose
   stats admin if TRUE         #手工启用/禁用,后端服务器(haproxy-1.4.9以后版本)
   stats refresh 15s
   stats uri /admin?stats
   stats realm "请输入用户名密码"
   stats auth admin:xxxxxx
   stats hide-version

frontend public
   bind 0.0.0.0:80
   bind 0.0.0.0:443 ssl crt /home/hemin/installs/haproxy/kevin.com.pem
   maxconn 20400
   acl secure dst_port 443
   capture request header Host len 50
   capture request header Connection len 20
   capture response header Connection len 20

   #定义域名
   acl wihtout_www_domain hdr_beg(host) kevin.com
   acl www_domain hdr_beg(host) www.kevin.com
   acl wiki_domain hdr_beg(host) wiki.kevin.com
   acl jira_domain hdr_beg(host) jira.kevin.com
   acl oms_domain hdr_beg(host) oms.kevin.com
   acl static_domain hdr_beg(host) static.kevin.com
   acl company_domain hdr_beg(host) company.kevin.com
   acl archive_domain hdr_beg(host) -i archive.kevin.com
   acl m_domain hdr_beg(host) -i m.kevin.com
   acl s_domain hdr_beg(host) -i s.kevin.com
   acl oms_domain hdr_beg(host) -i oms.kevin.com
   acl wx_domain hdr_beg(host) -i wx.kevin.com wxdev.kevin.com

   #限定OMS访问IP
   acl oms_ip_valid src 102.100.24.35
   acl oms_ip_valid src 101.18.124.19
  #acl pay_callback_ip_valid src 115.238.xx.xx 115.236.xx.xx

   #首页根路径(http://www.kevin.com/ )
   acl root path /
   acl aboutUs path_beg -i /aboutUs
   acl index path_beg -i /index
   acl login_page path_beg /login.htm
   acl register_page path_beg /register.htm

   #标列列,标详情
   acl product_no_secure path_beg /claims/info/show /claims/product/list /claims/product/detail

   #用户中心,需要走https
   acl user_resource path_beg /user

   #用户中心,查询用户信息时,不需要走https,并且走https时,有奖推广不正常
   acl userInfo path_beg /user/userInfo

   #活动页
   acl activity path_beg -i /prom/activity/recommend

   #投标面
   acl bid path_beg -i /claims/bid.htm

   #计算收益
   acl bid_getReceivable path_end -i /bid/getReceivable

   #新手指引
   acl newbieGuide path_beg -i /newbieGuide/newbieGuide
   acl favicon path_beg -i /favicon.ico

   #有奖推广
   acl invite path_beg -i /activity/invite

   #忘记密码页面
   acl forgetPwd path_beg -i /forgetPwd.htm

   #支付回调白名单控制
   acl pay_return path_beg /pay/return_url
   acl pay_notify path_beg /pay/notify_url
   acl pay_withDraw path_beg /pay/withDraw_notify_url

   #http-request deny if pay_return !pay_callback_ip_valid
   #http-request deny if pay_notify !pay_callback_ip_valid
   #http-request deny if pay_withDraw !pay_callback_ip_valid
   
    redirect prefix http://www.kevin.com if root secure www_domain
    redirect prefix http://www.kevin.com if invite secure www_domain
    redirect prefix http://www.kevin.com if index secure www_domain
    redirect prefix http://www.kevin.com if secure www_domain wihtout_www_domain
    redirect prefix https://www.kevin.com if login_page    !secure www_domain
    redirect prefix https://www.kevin.com if register_page !secure www_domain
    redirect prefix https://www.kevin.com if user_resource !secure !userInfo www_domain
    redirect prefix http://www.kevin.com if bid_getReceivable secure
    redirect prefix https://www.kevin.com if bid !secure www_domain
    redirect prefix https://static.kevin.com if favicon  www_domain
    redirect prefix https://www.kevin.com if forgetPwd !secure www_domain
    redirect prefix http://www.kevin.com if aboutUs secure www_domain
    redirect prefix http://www.kevin.com if activity secure www_domain
    redirect prefix http://www.kevin.com if newbieGuide secure www_domain
    redirect prefix http://www.kevin.com if product_no_secure secure www_domain
    redirect prefix https://company.kevin.com if company_domain !secure
    redirect prefix https://static.kevin.com if s_domain
    use_backend web_haproxy_group if www_domain
    use_backend web_haproxy_group if wihtout_www_domain

    #非www的acl
    acl index url_beg -i (/|/index.htm)
    acl login_page url_beg /login.htm
    acl register_page url_beg /register.htm
    acl static_resources path_beg -i /resources

    use_backend file_server if archive_domain
    use_backend static_server if static_resources static_domain
    use_backend static_server if static_domain
    use_backend company_server if company_domain
    use_backend wap_server if m_domain
    use_backend oms_server if oms_domain
    use_backend wxdev_server if wx_domain
    use_backend wiki_server if wiki_domain
    use_backend jira_server if jira_domain
    #errorloc 503 http://static.kevin.com/resources/error/503.html
    errorloc302 500 http://www.kevin.com/500.htm
    errorloc302 403 http://www.kevin.com

backend web_haproxy_group
    balance roundrobin
    server 17_8080 172.16.60.51:8080 check inter 1000 rise 3 fall 3

backend file_server
    server 18_80994 172.16.60.51:8094 check inter 1000 rise 3 fall 3

backend static_server
    balance roundrobin
    server 18_8084 172.16.60.51:8084 check inter 1000 rise 3 fall 3 maxconn 2000

backend company_server
    balance roundrobin
    server 18_8083 172.16.60.51:8083 check inter 1000 rise 3 fall 3

backend oms_server
     server 18_8093 172.16.60.51:9093 check inter 1000 rise 3 fall 3

backend wap_server
     server webdev 172.16.60.51:8081 check inter 1000 rise 3 fall 3

backend wxdev_server
     server wxdev 172.16.60.51:8088 check inter 1000 rise 1 fall 1

backend wiki_server
      server wiki 172.16.60.30:8090 check inter 1000 rise 3 fall 3

backend jira_server
      server jira 172.16.60.12:80 check inter 1000 rise 3 fall 3

==========================整体总结下Haproxy的参数说明============================

一. Haproxy 配置说明
haproxy的配置段有"global","defaults","listen","frontend"和"backend"等:
global: 配置中的参数为进程级别的参数,且通常与其运行的操作系统有关
defaults: 用于为所有其他配置段提供默认参数,这配置默认配置参数可由下一个"defaults"所重新设定
forntend: 用于定义一系列监听的套接字,这些套接字可以接受客户端请求并与子建立连接
backend: 用于定义一系列"后端"服务器,代理将会将对应客户端的请求转发至这些服务器
listen: 用于定义通过关联"前段"和"后端"一个完整的代理,通常只对TCP流量有用

所有代理的名称只能使用大写字母、小写字母、数字、-(中线)、_(下划线)、.(点号)和:(冒号)。此外,ACL名称会区分大小写.

时间格式一些包含了值得参数表示时间,如超时时长。
这些值一般都以毫秒为单位,但也可以使用其他的时间单位做后缀,如us(微妙,1/10000000秒),ms(毫秒,1/1000秒),s(秒),m(分钟),h(小时),d(天)

二. global 全局配置
chroot: 修改haproxy的工作目录至指定的目录,并在放弃权限之前执行chroot()操作,可以提升haproxy的安全级别,不过需要注意的是确保指定的目录为空目录且任何用户均不能有写权限;
daemon: 让haproxy以守护进程的方式工作于后台,其等同于"-D"选项的功能,当然,也可以在命令行中以"-db"选项将其禁用;
gid: 以指定的GID运行haproxy,建议使用专用于运行haproxy的GID,以避免因权限带来的风险;
group: 同gid,不过这里为指定的组名;
uid: 已指定的UID身份运行haproxy进程;
user: 同uid,但这里使用的为用户名;
log: 定义全局的syslog服务器,最多可以定义两个;
nbproc: 指定启动的haproxy进程个数,只能用于守护进程模式的haproxy;默认为止启动一个进程,鉴于调试困难等多方面的原因,一般只在但进程仅能打开少数文件描述符的场中才使用多进程模式;
pidfile: pid文件的存放位置;
ulimit-n:设定每个进程所能够打开的最大文件描述符,默认情况下其会自动进行计算,因此不建议修改此选项;
node: 定义当前节点的名称,用于HA场景中多haproxy进程共享同一个IP地址时;
description: 当前实例的描述信息;
maxconn: 设定每个haproxy进程所接受的最大并发连接数,其等同于命令行选项"-n","ulimit-n"自动计算的结果正式参照从参数设定的;
maxpipes: haproxy使用pipe完成基于内核的tcp报文重组,此选项用于设定每进程所允许使用的最大pipe个数,每个pipe会打开两个文件描述符,因此,"ulimit -n"自动计算的结果会根据需要调大此值,默认为maxcoon/4;
noepoll: 在linux系统上禁用epoll机制;
nokqueue: 在BSE系统上禁用kqueue机制;
nopoll: 禁用poll机制;
nosepoll: 在linux系统上禁用启发式epoll机制;
nosplice: 禁止在linux套接字上使用tcp重组,这会导致更多的recv/send调用,不过,在linux2.6.25-28系列的内核上,tcp重组功能有bug存在;
spread-checks<0..50,in percent>: 在haprorxy后端有着众多服务器的场景中,在紧缺是时间间隔后统一对中服务器进行健康状况检查可能会带来意外问题,此选项用于将检查的时间间隔长度上增加或减少一定的随机时长,为当前检查检测时间的%;
tune.bufsize: 设定buffer的大小,同样的内存条件下,较小的值可以让haproxy有能力接受更多的并发连接,较大的值了可以让某些应用程序使用较大的cookie信息,默认为16384,其可以在编译时修改,不过强烈建议使用默认值;
tune.chksize: 设定检查缓冲区的大小,单位为字节,更大的值有助于在较大的页面中完成基于字符串或模式的文本查找,但也会占用更多的系统资源,不建议修改;
tune.maxaccept: 设定haproxy进程内核调度运行时一次性可以接受的连接的个数,较大的值可以带来较大的吞吐量,默认为单进程模式下为100,多进程模式下为8,设定为-1可以禁止此限制,一般不建议修改;
tune.maxpollevents: 设定一次系统调用可以处理的事件最大数,默认值取决于OS,其至小于200时可介于带宽,但会略微增大网络延迟,但大于200时会降低延迟,但会稍稍增加网络带宽的占用;
tune.maxrewrite: 设定在首部重写或追加而预留的缓存空间,建议使用1024左右的大小,在需要更大的空间时,haproxy会自动增加其值;
tune.rcvbuf.client: 设定内核套接字中客户端接收缓存区的大小,单位为字节,强烈推荐使用默认值;
tune.rcvbuf.server: 设定内核套接字中服务器接收缓存区的大小,单位为字节,强烈推荐使用默认值;
tune.sndbuf.client: 设定内核套接字中客户端发送缓存区的大小,单位为字节,强烈推荐使用默认值;
tune.sndbuf.server: 设定内核套接字中服务器端发送缓存区的大小,单位为字节,强烈推荐使用默认值;
debug: 调试模式,输出启动信息到标准输出;
quiet: 安装模式,启动时无输出;

三. defaults 默认配置
defaults:用于为所有其他配置段提供默认参数,这配置默认配置参数可由下一个"defaults"所重新设定

1) balance
balance <algorithm> [<arguments>]
balance url_param <param> [check_post [<max_wait>]]
定义负载均衡算法,可用于"defaults"、"listen"和"backend"中。<algorithm>用于在负载均衡场景中挑选一个server,其仅用于持久信息不可用的条件下或需要将一个连接重新派发至另一个服务器时。支持的算法有:

roundrobin:基于权重进行轮询,在服务器的处理时间保持均匀分布时 ,这是最平衡、最公平的算法。此算法是动态的,这表示某权重可以在运行时进行调整,不过,在设计上,每个后端服务器仅能最多支持4128个连接; 即客户端请求每次都转发到不同的节点服务器上;

static-rr:基于权重进行轮询,与roundrobin类似,但是为静态方法,在运行时调整期后端权重不会生效,不过,其在后端服务器连接数上没有限制;

leastconn:新的连接强求笨哦派发至具有最少连接数目的后端服务器,在有这较长会话的场景中推荐使用此算法,如LDAP、SQL等。其并不太适合用于较短会话的应用层协议,如HTTP,此算法是动态的,可以在运行时调整其权重;

source:将请求的源地址进行hash运算,并有后端的服务器的权重总数相处后派发至某匹配的服务器,这可以使得同一个客户端IP的请求始终被派发至某特定的服务器,不过,当服务器权重总数发生变化时,如某服务器宕机或者添加新服务器,许多的请求可能会被派发至与此前请求不同的服务器,常用于负载均衡无cooki功能的基于TCP的协议,默认为动态,不过可以使用hash-type修改此特性;

uri:对URI的左半部分(“问号”标记之前的部分)或整个URI进行hash运算,并由服务器的总权重相除后派发至某匹配的服务器;这可以使得对同一个URI的请求总是派发至某匹配的服务器,除法服务器的权重总数发生了变化,此算法常用于代理缓存或反病毒代理以提高缓存的命中率,需要注意的是,此算法仅应用于HTTP后端服务器场景,其默认为静态算法,不过可以使用hash-type修改此特性;

url_param:通过<argument>为URL指定的参数在每个HTTP GET请求中将会被索引,日过找到了指定的参数且其通过等于号“=”被赋予了一个值,那么此值将被执行hash运算并被服务器的总权重相处后派发至某匹配的服务器,此算法可以通过追踪请求中的用户标识进而确保同一个用户的ID请求被发送同一个特定的服务器,除非服务器的总权重发生了变化;如果某请求中没有出现指定的参数或其没有有效值,则使用轮询算法对其想用请求进行调度,此算法默认为静态,不过可以使用hash-type修改此特性;

har(<name>):对于每个HTTP请求,通过<name>指定的HTTP首部将会被检索,如果对于那个的首部没有出现或其没有有效值,则使用轮询算法对响应请求进行调度,其有一个可选项“use_domain_only”可以指定检索类似host类的首部时仅计算域名部分以降低hash算法的运算量,此算法默认为静态,不过可以使用hash-type修改此特性;

2) bind
bind [<address>]:<port_range>[,.....]
bind [<address>]:<port_range>[,.....] interface <interface>
该指令仅能用于frontend和listen区段,用于定义一个或多个监听的套接字;
<address>: 可选项,其可以为主机名、IPV4地址、IPV6地址或*:省略此选项、将其指定为*或0.0.0.0时,将监听当前系统的所有IPv4地址;

<port_range>: 可以是一个特定的TCP端口,也可是一个端口范围(如6604-6610),代理服务器将通过制定的端口来接受客户端请求,需要注意的是,每组监听的套接字;

<address:prot>: 在同一个实例上只能使用一次,而且小于1024的端口需要有特定的权限的用户才能使用,这可能需要通过uid参数来定义;

<interface>:指定物理接口的名称,仅能在linux系统上使用,其不能使用接口别名,二进程使用物理端口名称,而且只有管理有权限指定绑定的物理端口;

3) mode
mode{ tcp|http|health }
设定实例的运行模式或协议,当实现内容交换时,前段和后端必须工作与统一中模式(一般说来时tcp模式),否则将无法启动实例;

tcp: 实例运行于纯tcp模式,在客户端和服务器端之间将建立一个全双工的连接,且不会对7层报文做任何类型的检查,此为默认模式,通常用于SSL、SSH、SMTP等应用;

http:实例运行于http模式,客户端请求在转发至后端服务器之前将被深度分析,所有不与RFC模式兼容的请求都会被拒绝;

health:实例运行于health模式,其对入站请求仅响应“OK”信息并关闭连接,且不会记录任何日志信息 ,此模式将用于相应外部组件的监控状态检测请求;目前来讲,此模式已经废弃,因为tcp或http模式中的monitor关键字可完成此类功能;

4) log
log global
log<address><facility>[<level>[<minlevel>]]
为每个实例启用事件和流量日志,因此可用于所有区段。每个实例最多可硬定义两个log参数,不过,如果使用了“log global”且“global”端定义了两个log参数时,多余的log参数将会倍忽略;
global:当前实例的日志系统参数同“global”段中的定义时,将使用此格式,每个实例仅能定义一个“log global”语句,且其没有额外的参数;

<address>:定义日志发往的位置,其格式之一可以为<ipv4_address:port>,其中prot为udp协议,默认为514,格式之二为Unix套接字文件路径,当需要留心chroot应用及用户读写权限;

<facility>: 可以为syslog系统的标准facility之一;

<level>: 定义日志级别,即输出信息过滤器,默认为所有信息,指定级别时,所有等于或高于此级别的日志信息将会被发送;

5) maxconn
maxconn <conns>
设定一个前段的最大并发连接数,因此,其不能用于backend区段,对于大型站点来说,可以尽可能提高此值以便让haproxy管理连接队列,从而便面无法应答用户请求。当然,此最大值不能超过“global”段中的定义。此外,需要留心的是,haproxy会为每个连接维持两个缓冲,每个缓存的大小为8KB,在加上其他的数据,每个连接将大约占用17KB的RAM空间,这意味着经过适当优化后 ,有着1GB的可用RAM空间时将维护40000-50000并发连接;

如果为<conns>指定了一个过大值,极端场景中,其最终所占据的空间可能会超过当前主机的可用内存,这可能会带来意想不到的结果,因此,将其设定一个可接受值放为明智绝对,其默认为2000;

6) default_backend
default_backend <backend>
在没有匹配的“use_backend”规则时为实例指定使用的默认后端,因此,其不可应用于backend区段,在“frontend”和“backend”之间进行内容交换时,通常使用“use-backend”定义其匹配规则,而没有被匹配到的请求将有此参数指定的后端接收;

<backend>:指定使用的后端名称;

7) server
server<name><address>[:port][param*]
在后端声明一个server,因此,不能用于defaults和frontend区段。

<name>: 为此服务器指定的内部名称,其将会出现在日志及警告信息中;如果设定了“http-send-server-name”,他还将会被添加至发往此服务器的请求首部中;

<adderss>:此服务器的IPv4地址,也支持使用可解析的主机名,只不过在启动时需要解析主机名至响应的IPV4地址;

<:port>:指定将连接请求所发往此服务器时的目标端口,其为可选项,为设定是,将使用客户端请求时的同一相同端口;

[param*]:为此服务器设定的一系列参数:其可以得参数非常多,下面仅说明几个常用的服务器或默认服务器参数:
   backup:设定为备用服务器,仅在负载均衡场景中的其他server均不可以启用此server;
   check:启动对此server执行监控状态检查,其可以借助于额外的其他参数完成更精细的设定,如:
       inter<delay>: 设定监控状态检查的时间间隔,单位为毫秒,默认为2000,也可以使用fastinter和downinter来根据服务器端专题优化此事件延迟;
       rise<count>:设定检查状态检查中,某离线的server从离线状态转换至正常状态需要成功检查的次数;
       fall<count>:设定检查状态检查中,某离线的server从正常状态转换至离线状态需要成功检查的次数;
   cookie<value>:为指定server设定cookie值,此处指定的值将会在请求入站时被检查,第一次为此值挑选的server将会倍后续的请求所选中,其目的在于实现持久连接的功能;
   maxconn<maxconn>:指定此服务器接受的最大并发连接数,如果发往此服务器的连接数目高于此处指定的值,其将被放置于请求队列,以等待其他连接被释放;
   maxqueue<maxqueue>:通过观察服务器的通信状况来判断其健康状态,默认为禁用,其支持的类型有“layer 4”和“layer 7”,“layer 7”仅能用于http代理场景;
   redir<prefix>:启用重定向功能,将发往此服务的GET和HEAD请求均以302状态码响应,需要注意的是,在prefix后面不能使用/,且不能使用相对地址,以避免造成循环,例如

server srv1 192..168.1.202:80 redir http://www.kevin.com check

   weight<weight>: 权重,默认为1,最大值为256,0表示不参与负载均衡;

   检查方法
      option httpchk
      option httpchk<uri>
      option httpchk<method><uri>
      option httpchk<method><uri><version>:不能用于frontend端,例如:

backend https_relay
mode tcp
option httpchk OPTIONS * HTTP/1.1rnHost: www
server apache1 192.168.1.1:443 check port 80

8) capture request header
capture request header <name> len <length>
捕获并记录指定的请求首部最近一次出现时的第一个值,仅能用于“frontend”和“listen”区段,捕获的首部值使用花括号{}括起来后添加进日志中,如果需要捕获多个首部值,他们将以指定的次序出现在日志文件中,并以竖线“|”作为分隔符,不存在的首部记录为空字符串,最长需要捕获的首部包括在虚拟主机环境中使用的“host”、上传请求首部的“Content-length”、快速区别现实用户和网络机器人“User-agent”,已经代理环境中距离请求来源的“X-Forword-For”;

<name>: 要捕获的首部的名称,此名称不区分大小写,但建议与他们出现在首部中的格式相同,比如大写首字母,需要注意的是,记录在日志的是首部的值,而非首部名称;

<length>: 指定距离首部值时所记录的精确长度,超出的部分将会倍忽略;

可以捕获的请求首部的个数没有限制,但每个捕获最多能记录64个字符,为了保证同一个frontend中日志格式的统一性,首部捕获仅能在frontend中定义;

9) capture response header
capture response header <name> len <length>
捕获并记录响应首部。其格式和要点同捕获的请求首部响应.

10) stats enable
启用基于程序编译时默认设置的统计报告,不能用于"frontend"区段,只要没有额外的其他设定,他们就会使用如下的配置:
-  stats uri : /haproxy?stats
-  stats realm : "HAProxy Statistics"
-  stats auth : no authentication
-  stats scope : no restriction
尽管"stats enable"一条就能够启用统计报告,但还是建议设定其他所有的参数,以避免其依赖默认设定而带来非预期后果,下面是一个配置示例:

backend public_www
    server srv1 192.168.1.201:80
    stats enable
    stats hide-version
    stats scope   .
    stats uri     /admin?stats
    stats realm   Haproxy Statistics
    stats auth    admin1:AdMiN123
    stats auth    admin2:AdMiN321

11) stats hide-version
启用统计报告并隐藏HAProxy版本报告,不能用于"frontend"区域,默认情况下,统计页面会显示一些有用信息,包括HAProxy的版本号,然后,向所有人公开HAproxy的准确版本号是非常有危险的,因为他能够版主恶意用户快速定位版本的缺陷和漏洞,尽管"stats hide-version"一条就能够启用统计报告,但还是建议设定其他所有的参数,以避免其依赖默认设定而带来非预期后果.

12) stats realm
stats realm <realm>
启用统计报告并高精认证领域,不能用于"frontend"区域,haproxy在读取realm是会讲是做一个单词,因此,中间的空白字符都必须使用反斜线进行转移。此参数仅在与"stats auth"配置使用时有意义;

<realm>:实现HTTP基本认证时显示在浏览器中的领域名称,用于提示用户输入一个用户名和密码;

尽管"stats realm"一条就能够启用统计报告,但还是建议设定其他所有的参数,以避免其依赖默认设定而带来非预期.

13) stats scope
stats scope {<name>|"."}
启用统计报告并限定报告的区段,不能用于“frontend”区域,当指定此语句时,统计报告将仅显示其列举出区段的报告信息,所有其他区段的信息将被隐藏,如果需要显示多个区段的统计报告,此语句可以定义多次,需要注意的是,区段名称进程仅仅是以字符串比较的方式进行,他不会真检查指定的区段是否真正存在;

<name>:可以是一个“listen”、“frontend”或“backend”区段的名称,而“.”则表示stats scope语句所定义的当前区段;

尽管“stats scope”一条就能够启用统计报告,但还是建议设定其他所有的参数,以避免其依赖默认设定而带来非预期后果.

14) stats auth
stats auth <user>:<password>
启用带认证的统计报告功能并授权一个用户账号,不能用于"frontend"区域;

<user>:授权进行访问的用户名;

<password>:此用户的访问密码,明文格式;

此语句将给予默认设定启用统计功能报告,并仅允许其定义的用户访问,其也可以定义多次以手段多个用户账号,可以结合"stats realm"参数在提示用户认证是给出一个领域说明信息,在使用非法用户访问统计功能时,其将会响应一个"401 Forbidden"页面,其认证方式为HTTP Basic认证,密码传输会以明文方式进行,因此,配置文件中也使用存储明文方式存储以说明其非保密信息故此不能想用与其他关键性账号的密码。

尽管"stats auth"一条就能够启用统计报告,但还是建议设定其他所有的参数,以避免其依赖默认设定而带来非预期后果.

15) stats admin
atsts admin {if|unless}<cond>
在指定的条件满足时启用统计报告页面的管理级别功能,它允许通过web接口启用或禁用服务器,不过,基于安全的角度考虑,统计报告页面应该尽可能为只读的,此外,如果启用了HAproxy的多进程模式,启用此管理级别将会可能导致异常行为;

目前来说,POST请求方法被限制于仅能使用缓冲区减去保留之外的空间,因此,服务器列表不能过长,否则,此请求将无法正常工作,因此,建议一次仅调整少数几个服务器.

16) option httplog
option httplog [clf]
启用记录HTTP请求、会话状态和计时器的功能;

clf:使用CLF格式来代替HAproxy默认的HTTP格式,通常在使用仅支持CLF格式的特定日志分析器时才需要使用此格式;

默认情况下,日志输入格式非常简陋。因为其仅包括源地址、目标地址和实例名称、而"option httplog"参数将会使得日志变得丰富许多,其通常包括但不局限于HTTP请求、连接计时器、会话状态、连接数、捕获的首部及cookie、"frontend"、"backend"及服务器名称。当然也包括源地址和端口号等。

17) option logasap
no option logasap
启用或禁用提前将HTTP请求记入日志,不能用于“frontend”区段。

默认情况下,HTTP请求是在请求结束时进行记录以便能够将其整体输入时长和字节数记入日志,由此,传较大的对象时,其记入日志的市场可能会略有延迟,“option logasap”参数能够在服务器发送complete首部时及时记录日志,只不过,此时将不记录整体传输时长和字节数。此情形下,捕获“Content-Length”响应报文来记录的字节数是以一个较好的选择;

18) option forwardfor
option forwardfor[ except <network> ][ header <name> ][ if-none ]
允许在发往服务器的请求首部中插入"X-Forwarded-For"首部;

<network>:可选参数,当指定时,源地址为皮至此网络中的请求都禁用此功能;

<name>:可选参数,可使用一个自定义的首部,如"X-Cluster-Client-IP"来代替"X-Forwarded-For",有些独特的web服务器的确需要用一个独特的首部;

if-none: 仅在此首部不存在时才会将其添加至请求报文中;

HAproxy工作与反向代理模式,其发往服务器的请求中的客户端IP均为HAproxy主机的地址而非真正的客户端地址,这会使得服务器的日志记录不了真正的请求来源,"X-Forwarded-For"首部则可用于解决此问题,HAproxy可以向每个房网服务器的请求上添加此首部,并以客户端IP为其value;

需要注意的是: HAproxy工作与隧道模式,其仅检查每一个连接的第一个请求,仅第一个请求报文中被附加此首部,请确保同时使用"option httpclose"、"option forceclose"和"option http-server-close"几个option.

19) errorfile
errorfile <code> <file>
在用户请求不存在的页面时,返回一个页面给客户端而非有haproxy生成的错误代码,可用于所有段中;

<code>: 指定对HTTP的那些状态码发回指定的页面,这里可用的状态码有200、400、403、408、500、502、503和504;

<file>:指定用于响应的页面文件;

例如:

errorfile 400 /etc/haproxy/errorfiles/400badreq.http
errorfile 403 /etc/haproxy/errorfiles/403forbid.http
errorfile 503 /etc/haproxy/errorfiles/503sorry.http

20) errorloc和errorloc302
errorloc <code> <url>
errorloc302 <code> <url>
请求错误时,返回一个HTTP重定向至某URL的信息,可以用于所有端中;

<code>: 指定对HTTP的那些状态码发回指定的页面,这里可用的状态码有200、400、403、408、500、502、503和504;

<url>:Location首部中指定的页面位置的具体路径,可以是在当前服务器上的页面的相对路径,也可以使用绝对路径,需要注意的是,如果URI之神错误时禅师某特定状态码信息的话,有可能会导致循环定向;

需要留意的是: 这两个关键字都会返回302状态码,浙江使得客户端使用同样的HTTP方法获取指定的URL。对于非GET方法获取指定的URL,对于非GET方法的场景(如POST)来说会产生问题,因为返回客户端的URL是不允许使用GET意外的其他方法的,如果的确有这种问题,可以使用errorloc303来返回303状态码给客户端;

21) errorloc303
errorloc303 <code> <url>
<code>: 指定对HTTP的那些状态码发回指定的页面,这里可用的状态码有400、403、408、500、502、503和504;

<url>:Location首部中指定的页面位置的具体路径,可以是在当前服务器上的页面的相对路径,也可以使用绝对路径;

需要注意的是,如果URI之神错误时禅师某特定状态码信息的话,有可能会导致循环定向. 

posted @ 2016-12-06 16:43  散尽浮华  阅读(21220)  评论(2编辑  收藏  举报