HAProxy 是一款高性能TCP/HTTP 反向代理负载均衡服务器,具备以下功能:html
根据静态分配的cookies完成HTTP请求转发前端
在多个服务器间实现负载均衡,而且根据HTTP cookies 实现会话粘性mysql
主备服务器切换nginx
接受访问特定端口实现服务监控git
实现平滑关闭服务,不中断已创建链接的请求响应,拒绝新的请求github
在请求或响应HTTP报文中添加,修改,或删除首部信息web
根据正则规则阻断请求正则表达式
提供带有用户认证机制的服务状态报告页面算法
HAProxy特别适用于那些负载特大的web站点,这些站点一般又须要会话保持或七层处理。HAProxy运行在时下的硬件上,彻底能够支持数以万计的 并发链接。而且它的运行模式使得它能够很简单安全的整合进您当前的架构中, 同时能够保护你的web服务器不被暴露到网络上。sql
HAProxy 实现了一种事件驱动、单一进程模型,此模型支持很是大的并发链接数。多进程或多线程模型受内存限制 、系统调度器限制以及无处不在的锁限制,不多能处理数千并发链接。事件驱动模型由于在有更好的资源和时间管理的用户端(User-Space) 实现全部这些任务,因此没有这些问题。此模型的弊端是,在多核系统上,这些程序一般扩展性较差。这就是为何他们必须进行优化以 使每一个CPU时间片(Cycle)作更多的工做。
HAProxy实际工做中,它占用用户空间时间要比内核运行时间少20倍,因此对系统参数调优是十分必要的一项工做。
另外衡量一个负载均衡服务器主要考量三个指标
session rate
此项指标很是重要,它决定了一个load balancer 能不能分发全部接受的请求。这项指标一般是由CPU性能决定。测量指标的大小跟传输的每一个对象的大小有关,一般用空对象来测试,Session rates 在 100,000 sessions/s 左右,使用 Xeon E5 在 2014测试。
session concurrency
该指标与前一指标相关联。这一指标与服务器内存和系统能够处理的文件描述符数量有关。 一般每一个session占用34KB,即大概3W个session占用1GB内存空间,实际上,socket buffer也会占用内存空间,2W个session socket占用1GB内存。
data forwarding rate
这一指标与 session rate 相对立,它的衡量单位一般是 Megabytes/s (MB/s), 或者 Gigabits/s (Gbps)。传输较大的对象有利于该指标的提高,由于较大的对象传输能够减小session创建和关闭浪费的时间。而测量session rate 则在传输小对象时有利于指标提高。haproxy 在2014年使用 Xeon E5 测试成绩为40 Gbps。
本文环境:CentOS7.2 haproxy 1.5 经过yum 安装
程序环境: 配置文件:/etc/haproxy/haproxy.cfg Unit File: haproxy.service 主程序:/usr/sbin/haproxy 配置文件: global:全局配置段 进程及安全配置相关的参数 性能调整相关的参数 Debug相关的参数 proxies:代理配置段 defaults:为frontend, backend以及listen提供默认配置; frontend:前端,至关于Nginx中的server{ ... }; backend:后端,至关于nginx中的upstream { ... }; listen:先后端的直接组合; **关于前端与后端的关系:一个前端能够指向多个后端;同时一个后端能够被多个调用。
定义日志系统相关属性
log <address> [len <length>] <facility> [max level [min level]]
harpoxy 将日志发送到指定的rsyslog服务器,在本地记录也要开启rsyslog服务;
全局端最多可配置两个log 服务器;
< address> :日志服务器地址
[ len ] 指定记录的日志最大长度
定义运行用户,所属组
username
group groupname
运行方式
意味着后台守护进程
maxconn <number>:设定单haproxy进程的最大并发链接数; maxconnrate <number>:设定单haproxy进程每秒接受的链接数; maxsslconn <number>:设定单haproxy进程的ssl链接最大并发链接数; maxsslrate <number>:单haproxy进程的ssl链接的建立速率上限; spread-checks <0..50, in percent>:避免对于后端检测同时并发形成 的问题,设置错开时间比,范围0到50,通常设置2-5较好。
用于对haproxy 状态监控页面的用户认证。至少要定义一个用户列表而且添加一个用户
密码能够加密或明文。
Example:
userlist L1 group G1 users tiger,scott group G2 users xdb,scott user tiger password $6$k6y3o.eP$JlKqe4(...)xHSwRv6J.C0/D7cV91 user scott insecure-password elgato user xdb insecure-password hello userlist L2 group G1 group G2 user tiger password $6$k6y3o.eP$JlKBx(...)xHSwRv6J.C0/D7cV91 groups G1 user scott insecure-password elgato groups G1,G2 user xdb insecure-password hello groups G2
这部分配置在下列定义区域下使用
- defaults < name > - frontend < name > - backend < name > - listen < name >
“defaults” 区域定义了frontend,backend,listen 的默认参数
“frontend“ 区域描述了接收客户端请求的监听配置
”backend“ 区域描述接受请求处理的后端服务器配置
”listen“ 区域描述一组前端和后端直接一对一绑定的组配置
HAProxy 配置的关键字与区域限制特性,即有些关键字在某个区域不可使用
下面开始讲解关键字的用法
1. bind [<address>]:<port_range> [, ...] [param*]
仅在frontend和listen区域使用。定义服务监听端口地址等参数
[ param* ] 参数根据系统而定,通常不须要指定
example:
bind :80 #监听本机全部IP的80端口 bind *:80 #监听本机全部IP的80端口 bind 192.168.12.1:8080,10.1.0.12:8090
2. mode {tcp|http|health}
tcp:基于layer4实现代理,可代理大多数基于tcp的应用层协议,例如ssh/mysql/pgsql等;
http:客户端的http请求会被深度解析;
health:工做为健康状态检查响应模式,当请求到达时仅回应“OK”即断开链接;
3. balance <algorithm> [ <arguments> ] balance url_param <param> [check_post]
在backend区域定义调度算法
< algorithm > 以下:
roundrobin
带有权重的轮询调度算法; server后面使用weight来定义权重; 动态算法:支持权重的运行时调整,支持慢启动(缓慢接收大量请求在刚启动时);仅支持最大4095个后端活动主机
static-rr
静态的roundrobin算法;
不支持权重的运行时调整及慢启动;但后端主机数量无限制;
leastconn
带权重的最少链接分配动态算法;
适用长链接应用协议,如ssh等
first
第一优先算法;
若是第一个服务端可接受请求则老是把链接分配给它,直到第一个服务端处于繁忙,分配给下一个,顺序按服务端的数字ID从小到大排列
source
源IP hash 算法;
该算法保证在后端服务器组没有减小或增长的状况下,能未来自同一客户端IP的请求分配至同一个服务端;
该算法适合在没法使用cookie插入的TCP模式下使用
动态算法或静态算法取决于hash-type;
uri
uri hash 算法;
该算法hash uri 的查询标记的左侧部分,或者指定whole 参数时hash所有uri;
该算法保证访问同一uri的请求分配至同一服务端,适用于后端为缓存服务器的状况,以提升缓存命中率;
动态算法或静态算法取决于hash-type;
另外:该算法支持追加参数[ < arguments > ]:
(1) whole :hash完整uri
(2) len number:hash指定uri的长度
(3) depth nubmer:hash指定目录深度,每一个"/"表明一个深度
uri_param
param hash 算法;
对用户请求的url中的< param >部分中的指定的参数的值(uri中"="部分)做hash计算;
该算法适用于有用户识别参数的uri ,它保证同一user id 的请求分配至同一服务端;
若果check_post 标识启用,则在uri中没有找到"?"参数时,对HTTP Post 请求实体查找参数声明;
动态算法或静态算法取决于hash-type;
Example:
balance url_param userid balance url_param session_id check_post 64
hdr(< name >)
HTTP 首部字段hash算法;
指定的http首部将会被取出作hash计算。若是没有值,则降至轮询调度;
动态算法或静态算法取决于hash-type;
4. hash_type < method >
在balance 指令中选定与hash 有关的算法,都会受此影响。
默认采起的方法为map-based
< method > 以下:
map-based:取模法,hash数据结构是静态数组;
该hash是静态的,不支持在线调整权重,不支持慢启动;
该算法调度平滑,后端服务器可以均匀承受负载;
缺点也是明显的:当服务器的总权重发生变化时,即有服务器上线或下线,都会致使调度结果总体改变。若是想避免此种状况应采用consistent 方法;
consistent:一致性哈希,哈希的数据结构是“树”;
该hash是动态的,支持在线调整权重,支持慢启动
每个server 会在"树"中出现屡次, 在树中查找hash key,并选择最近的server;
该方法的优势在于,当服务器的总权重发生变化时,对调度结果影响是局部的,不会引发大的变更。因此十分适合缓存服务器;
缺点:该算法不够平滑,很容易致使后端服务器负载不均衡。因此颇有必要对服务器的权重以或者服务器ID进行调整;
为保持均匀负载,应该保证全部服务器ID保持一致;
5. server <name> <address>[:[port]] [param*] default-server [param*]
server用于在backend和listen中定义一个主机;
default-server 用于设定server的默认参数;
[param*] 以下:
weight < weight >:当前server的权重;
id < number > :设定server ID
cookie < value >:为当前server指定其cookie值,此值会在收到请求报文时进行检测,其功能在于实现基于cookie会话保持;
check:对当前server进行健康状态检测;
inter < delay >:时间间隔;
rise < count >:断定为“健康”状态须要检测的次数,默认2;
fall < count >:断定为“不健康”状态须要检测的次数,默认3;
addr <ipv4|ipv6>:健康状态检测时使用的地址;
port < port >:健康状态检测时使用的端口;
注意:默认为传输层检测,即探测端口是否能响应;须要执行应用层检测,则须要httpchk, smtpchk, mysql-check, pgsql-check, ssl-hello-chk;
maxconn <maxconn>:当前server的最大并发链接数;
maxqueue <maxqueue>:当前server的等待队列的最大长度;
disabled:将主机标记为不可用;
redir <prefix>:将发往当前server的全部请求GET和HEAD类的请求均重定向至指定的URL;
Examples : server first 10.1.1.1:1080 id 3 cookie first check inter 1000 maxconn 10000 maxqueue 2000 server second 10.1.1.2:1080 id 4 cookie second check inter 1000
6. option httpchk option httpchk <uri> option httpchk <method> <uri> option httpchk <method> <uri> <version>
基于http协议做7层健康状态检测机制,默认是基于tcp层进行检测;
TCP 模式也可使用该检测机制
< method > < uri > < version >:请求报文的超始行;
method 默认方法为 OPTIONS;返回状态码2XX,3XX意味成功;
Examples : # Relay HTTPS traffic to Apache instance and check service availability # using HTTP request "OPTIONS * HTTP/1.1" on port 80. backend https_relay mode tcp option httpchk OPTIONS /index.html HTTP/1.1\r\nHost:\ www server apache1 192.168.1.1:443 check port 80
7. http-check expect [!] <match> <pattern>
定义检测有效指望值;
! 表示认定的错误值;< match > 可取值为:
status < string >
rstatus < regex > 正则方式
string < string >
rstring < regex >
Examples : # only accept status 200 as valid http-check expect status 200 # consider SQL errors as errors http-check expect ! string SQL\ Error # consider status 5xx only as errors http-check expect ! rstatus ^5 # check that we have a correct hexadecimal tag before /html http-check expect rstring <!--tag:[0-9a-f]*</html>
8. cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ] [ postonly ] [ preserve ] [ httponly ] [ secure ] [ domain <domain> ]* [ maxidle <idle> ] [ maxlife <life> ]
启用基于cookie的会话黏性,要结合server指定的cookie参数一块儿实现;
经常使用形式:cookie WEBSRV insert nocache indirect
Example: backend websrvs balance roundrobin cookie WEBSRV insert nocache indirect server web1 10.1.0.68:80 check weight 2 maxconn 5000 cookie web1 server web2 10.1.0.69:80 check weight 1 maxconn 3000 cookie web2
9. default_backend <backend>
当use_backend 的使用规则没有被匹配时,由default_backend 指定默认服务器组;
关于use_backend 使用后续会在acl 章节中讲解;
为frontend或backend定义日志记录机制;
log global :使用全局定义的日志记录方式 log <address> [len <length>] <facility> [<level> [<minlevel>]]:自定义 no log :不记录 capture request header <name> len <length> -->记录请求报文中的指定的首部的值于日志中;len用于指定要记录的信息的长度; capture response header <name> len <length> -->记录响应报文中的指定的首部的值于日志中;len用于指定要记录的信息的长度; 示例: capture request header Referer len 30
- errorfile <code> <file>
< code > 指定HTTP返回的状态码。200, 400, 403, 408, 500, 502, 503, and 504 可以使用;
< file > 指定一个文件代替HTTP响应;
Example:errorfile 503 /etc/haproxy/errorfiles/503sorry.http
- errorloc <code> <url> - errorloc302 <code> <url>
发生错误时由haproxy重定向至指定url,以上两个命令等同,响应状态码为302
Example:errorloc 503 http://www.mydomain.com/index...
- errorloc303 <code> <url>
响应状态码为303,表示以GET方法从新请求页面
option forwardfor [ except <network> ] [ header <name> ] [ if-none ]
HAProxy把请求报文发日后端主机以前在请求报文添加“X-Forwared-For”首部
目的为使后端服务器可记录发出请求客户端的IP地址
[ except < network> ] :选择排除的网络地址
[ header < name> ] :不使用X-Forwared-For,自定义名称
[ if-none ]:有时请求原来带有该字段,此时再也不更改
Example:option forwardfor if-none
reqadd <string> [{if | unless} <cond>] rspadd <string> [{if | unless} <cond>]
在HTTP请求或响应首部内容尾部添加值
Example:rspadd X-Via: HAProxy/1.5
reqdel <search> [{if | unless} <cond>] reqidel <search> [{if | unless} <cond>] (不区分大小写)
删除HTTP请求中正则匹配的全部首部
rspdel <search> [{if | unless} <cond>] rspidel <search> [{if | unless} <cond>] (不区分大小写)
删除HTTP响应中正则匹配的全部首部。属于安全增强策略,删除一些服务器版本信息,防止针对攻击
Example:rspidel Server.*
timeout client <timeout>
设定客户端最大非活动时长, 默认单位是ms;最好与timeout server一致
timeout server <timeout>
设定服务端最大非活动时长, 默认单位是ms;
timeout connect <timeout>
设定最大与服务端创建链接的时长
timeout http-keep-alive <timeout>
设定最大等待新请求的空闲时长,默认单位为ms;
timeout client-fin <timeout>
在客户端侧设定半关闭链接非活动超时
timeout server-fin <timeout>
在服务端侧设定半关闭链接非活动超时
Example:
defaults http timeout connect 5s timeout client 30s timeout server 30s timeout client-fin 10s timeout http-keep-alive 500
Haproxy 可以从请求报文,响应报文,从客户端或者服务端信息,从表,环境信息等等中提取数据。提取这样的数据的动做咱们称之为获取样本。进行检索时,这些样本能够用来实现各类目的,好比做为粘滞表的键,最经常使用的用途是,根据预约义的模式来进行匹配。
访问控制列表(ACL)提供一个灵活方案进行内容切换,或者在从请求,响应,任何环境状态中提取的数据基础之上作出决策。控制列表的原则很简单:
从数据流,表,环境中提取数据样本
对提取的样本可选地应用格式转换
对一个样本应用一个或多个模式匹配
当模式匹配样本时才执行动做
执行的动做一般是阻断请求,选择一个后端服务器或者添加一个HTTP首部
须要提醒的是,获取的样本数据不光可使用在acl中,也可使用别处,例如记录log中
定义ACL的语法为:
acl <aclname> <criterion> [flags] [operator] [<value>] ...
这样一条语句创建了一个acl 测试;
这些测试应用在请求或响应中被"标准"< criterion > 部分所指定的内容,并且能够指定[ flags] 进行特性调整,有些< criterion > 支持操做符[operator] 进行运算,同时一些转换格式的关键字能够跟在< criterion >后面,使用" , "隔开。而值[< value >] 要求被
< criterion > 所支持的数据形式,多个值使用空格分隔。
< criterion > 一般是指获取样本方法的名称。使用一个获取样本方法,暗含着其输出样本的类型,类型是如下列出的一种:
boolean
integer (signed or unsigned)
IPv4 or IPv6 address
string
data block
ACL引擎匹配数据使用的模式类型以下:
boolean
integer or integer range
IP address / network
string (exact, substring, suffix, prefix, subdir, domain)
regular expression
hex block
ACL flags 可用列表以下:
-i : 忽略大小写
-f filename : 从文件中载入模式
-m method : 指定模式匹配方法
-n : 禁止DNS解析
-M : -f 载入的文件做为映射文件使用
-u : 强制ACL的名称惟一
-- : 强制结束flag结束,避免了字符串中含有的- 引发混淆
其中flag中的 -m 选项可以使用的模式匹配方法以下,须要说明的是有些方法已被默认指定无需声明,例如int,ip
"found" : 只是用来探测数据流中是否存在指定数据,不进行任何比较
"bool" : 检查结果返回布尔值。匹配没有模式,能够匹配布尔值或整数,不匹配0和false,其余值能够匹配
"int" : 匹配整数类型数据;能够处理整数和布尔值类型样本,0表明false,1表明true
"ip" : 匹配IPv4,IPv6地址类型数据。该模式仅被IP地址兼容,不须要特别指定
"bin" : 匹配二进制数据
"len" : 匹配样本的长度的整数值
"str" : 精确匹配,根据字符串匹配文本
"sub" : 子串匹配,匹配文本是否包含子串
"reg" : 正则匹配,根据正则表达式列表匹配文本
"beg" : 前缀匹配,检查文本是否以指定字符串开头
"end" : 后缀匹配,检查文本是否以指定字符串结尾
"dir" : 子目录匹配,检查部分文本中以" / "做为分隔符的内容是否含有指定字符串
"dom" : 域匹配。检查部分文本中以" . "做为分隔符的内容是否含有指定字符串
若是获取样本值为整数,数值比较符可以使用,:
eq : true if the tested value equals at least one value
ge : true if the tested value is greater than or equal to at least one value
gt : true if the tested value is greater than at least one value
le : true if the tested value is less than or equal to at least one value
lt : true if the tested value is less than at least one value
想必前面一堆理论性的论述已经把你们搞的晕头转向,下面结合获取样本方法和访问控制动做指令具体阐述ACL使用方法
先介绍控制动做指令
layer 4 传输层控制指令
tcp-request connection <action> [{if | unless} <condition>]
对tcp请求控制指令
< condition > 即为ACL定义的访问控制列表
< action > 经常使用值有 "accept", "reject"
layer 7 应用层控制指令
#阻断符合ACL的访问请求 block { if | unless } <condition> #http请求的控制指令 http-request { allow | deny} [ { if | unless } <condition> ]
后端主机调用
#根据条件来调用指定后端 use_backend <backend> [{if | unless} <condition>]
由ACL定义的多个< condition > 组成联合条件,逻辑符为
and (默认操做符,可省略)
or (或者使用 "||")
! (取反)
# 与后端创建会话速率,每秒钟创建的新会话 be_sess_rate([<backend>]) : integer
Example :
# 某后端被请求过于繁忙,则重定向至错误页 mode http acl being_scanned be_sess_rate gt 100 redirect location /denied.html if being_scanned
在传输层获取样本,一般是TCP/IP 协议的IP和端口,以及创建链接速率等等。并且此部分样本一般用于"tcp-request connection"指令中的规则之中。
dst : ip #目标地址 dst_port : integer src : ip #源地址 src_port : integer
Example:
#阻断来自非指定IP的访问8080端口的请求 acl myhost src 10.1.0.200 acl myport dst_port 8080 tcp-request connection reject if !myhost myport
/1
path : string
提取请求url的地址信息,从第一个"/"开始,不包含host,不包含参数
ACL 衍生,即包含了-m 选项中匹配模式方法 :
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
Example:
#请求资源为图片,则调用图片服务器后端 acl picture path_end -i .jpg .png .gif use_backend server_pic if picture
/2
url : string
提取URL的所有内容,包含host和参数
ACL 衍生相似,再也不列举
/3
req.hdr([<name>[,<occ>]]) : string
提取http请求的指定首部字段值,< occ >可指定出现的位置
ACL 衍生 :
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
Example:
#阻断火狐浏览器发送的请求 acl firefox hdr_reg(User-Agent) -i .*firefox.* block if firefox
/4
method : integer + string
提取请求报文中的请求方法
Example:
#拒绝GET HEAD 方式以外的HTTP请求 acl valid_method method GET HEAD http-request deny if ! valid_method
HAProxy有众多内建的ACLs,这些ACLs可直接调用,例如
LOCALHOST 匹配来自本地IP的链接,127.0.0.1/8
HTTP_1.1 匹配http版本1.1
METH_GET 匹配http请求GET或HEAD方法
TRUE
FALSE
Example:
#拒绝GET HEAD 方式以外的HTTP请求 http-request deny if ! METH_GET
传送门:官方1.5使用手册--- EOF ---