1.HAProxy介绍
HAProxy: 是法国人Willy Tarreau开发的一个开源软件,是 一款应对客户端10000以上的同时连接的高性能的TCP
和 HTTP负载均衡器。其功能是用来提供基于cookie持久性, 基于内容的交换,过载保护的高级流量管制,自动故障切换 ,
以正则表达式为基础的标题控制运行时间,基于Web的报 表,高级日志记录以帮助排除故障的应用或网络及其他功能
LB Cluster:
四层:lvs, nginx(stream),haproxy(mode tcp)
七层:http: nginx(http), haproxy(mode http), httpd...
HAProxy:http://www.haproxy.org
文档:https://cbonte.github.io/haproxy-dconv/
● HAProxy是TCP / HTTP反向代理服务器,尤其适合于高可用 性环境
● 可以针对HTTP请求添加cookie,进行路由后端服务器
● 可平衡负载至后端服务器,并支持持久连接
● 支持基于cookie进行调度
● 支持所有主服务器故障切换至备用服务器
● 支持专用端口实现监控服务
● 支持不影响现有连接情况下停止接受新连接请求
● 可以在双向添加,修改或删除HTTP报文首部
● 支持基于pattern实现连接请求的访问控制
● 通过特定的URI为授权用户提供详细的状态信息
版本:1.4 1.5 1.6 1.7 1.8
2.Haproxy功能
● 支持http反向代理
● 支持动态程序的反向代理
● 支持基于数据库的反向代理
3. HAProxy组成
https://cbonte.github.io/haproxy-dconv/
程序环境:
主程序:/usr/sbin/haproxy
配置文件:/etc/haproxy/haproxy.cfg
Unit file:/usr/lib/systemd/system/haproxy.service
配置段:
● global:全局配置段
进程及安全配置相关的参数
性能调整相关参数
Debug参数
● proxies:代理配置段
defaults:为frontend, backend, listen提供默认配置
fronted:前端,相当于nginx, server {}
backend:后端,相当于nginx, upstream {}
listen:同时拥有前端和后端,适用于一对一环境 (最好前后端分开,以后
好调整)
简单的配置示例:
frontend web
bind *:80 绑定所有端口
default_backend websrvs 默认的backend
backend websrvs
balance roundrobin
server srv1 172.16.0.6:80 check
server srv2 172.16.0.7:80 check
haproxy -f haproxy 检查配置文件
systemctl status haproxy 检查一下haproxy状态
eg:
4.global配置 :
global配置参数:
进程及安全管理:chroot, deamon,user, group, uid, gid
nbproc :要启动的haproxy的进程数量,系统 默认单进程,要求使用daemon模式
ulimit-n :每个haproxy进程可打开的最大文件数,系统自动会指定,不建议设置
daemon:后端方式运行,建议使用
log:定义全局的syslog服务器;最多可以定义两个
log <address> [len <length>] <facility>[max level [min level]]
address: rsyslog服务器地址
len: 记录日志的长度,默认1024 10
5.日志系统
log:
log global
log <address> [len <length>] <facility>[<level>[<minlevel>]]
no log
注意:
默认发往本机的日志服务器;
(1) local2.* /var/log/local2.log
(2)#vim /etc/rsyslog.conf
$ModLoad imudp
$UDPServerRun 514
log-format <string>:
课外实践:参考文档实现combined格式的记录
记录日志到本机
存放日志到远程服务器
6.日志管理
将特定信息记录在日志中
capture cookie len <name> len <length>
捕获请求和响应报文中的 cookie并记录日志
capture request header <name> len <length>
捕获请求报文中指定的首部并记录日志
示例: capture request header X-Forwarded-For len
capture response header <name> len <length>
捕获响应报文中指定的首部并记录日志
示例: capture response header Content-length len 9
capture response header Location len 15
7.性能调整
性能调整:
maxconn <number>:设定每个haproxy进程所能接受的最大并发连接数
maxconnrate <number>:设置每个进程每秒种所能建立的最大连接数量
maxsessrate <number>:设置每个进程每秒种所能建立的最大会话数量
maxsslconn <number> : 每进程支持SSL的最大连接数量
spread-checks <0..50, in percent> 健康检测延迟时长百分比
建议2%-5%之间
8.配置段
* 代理配置段:
- defaults
- frontend
- backend
- listen
Frontend段:指定接收客户端连接侦听套接字设置
Backend段:指定将连接请求转发至后端服务器的相关设置
Listen段:指定完整的前后端设置,只对 TCP 有效
proxy 名称:使用字母 数字 - _ . : 并区分字符大小写
9.配置参数
bind:指定一个或多个前端侦听地址和端口
bind [<address>]:<port_range> [, ...] [param*]
示例:
listen http_proxy
bind :80,:443 监听所有IP的80和443端口
bind 10.0.0.1:10080,10.0.0.1:10443
bind /var/run/ssl-frontend.sock user root mode 600 accept-proxy
10.Balance配置
balance:后端服务器组内的服务器调度算法
balance <algorithm> [ <arguments> ]
balance url_param <param> [check_post]
调度算法:
* roundrobin:基于权重轮询,动态算法,支持权重的运行时调整,支持慢启 动;每个后端backend中最多支持4095个server
server options: weight #
* static-rr:基于权重轮询,静态算法,不支持权重的运行时调整及慢启动;后端主机数量无上限
* leastconn:加权最少连接,动态算法,最少连接的后端服务器优先分配接收新连接,相同连接时轮询,推荐在较长会话的场景使用,例如 MySQL、LDAP等,不适合http
* first:根据服务器在列表中的位置,自上而下进行调度;前面服务器 的连接数达到上限,新请求才会分配给下一台服务
* source:源地址hash,新连接先按权重分配,后续连接按source分配 请求 16 Balance配置
* uri: 对URI的左半部分或整个uri做hash计算,并除以服务器总权 重取模,以后派发至某挑出的服务器,适用于后端缓存服务器
<scheme>://<user>:<passwd>@<host>:<port>/<path>;<params>?<query>#<frag>
左半部分:/<path>;<params>
整个uri:/<path>;<params>?<query>#<frag>
* url_param: 对用户请求的uri听部分中的参数的值作hash计算,并由服务器总权重相除以后派发至某挑出的服务器;通常用于追踪用 户,以确保来自同一个用户请求始终发往同一个Backend Server
* hdr():对于每个http请求,此处由<name>指定的 http首部将会被取出做hash计算; 并由服务器总权重相除以后派发至某挑出的服务器;无有效值的会被轮询调度
hdr(Cookie)
* rdp-cookie 远程桌面相关
* rdp-cookie()
11.哈希算法
hash-type:哈希算法
hash-type <method> <function> <modifier>
method:
map-based:除权取余法,哈希数据结构是静态数组
consistent:一致性哈希,哈希数据结构是一棵树
<function> : 哈希函数
sdbm djb2 wt6
default_backend <backend>
无use_backend 匹配时,使用默认的backend,用于 frontend中
default-server [param*]
为backend中的各server设定默认选项
配置
server <name> <address> [:[port]] [param*]
定义后端主机的各服务器及其选项
server <name> <address> [:port] [settings ...]
default-server [settings ...]
<name>:服务器在haproxy上的内部名称;出现在日志及警告信息
<address>:服务器地址,支持使用主机名
[:[port]]:端口映射;省略时,表示同bind中绑定的端口
[param*]:参数
weight :权重,默认为1
maxconn :当前server的最大并发连接数
backlog :当server的连接数达到上限后的后援队列长度
backup:设定当前server为备用服务器 20 健康状态检测
check:对当前server做健康状态检测,只用于四层检测
注意:httpchk, “smtpchk”, “mysql-check”, “pgsql-check” and “sslhello-chk” 用于定义应用层检测方法
addr :检测时使用的IP地址
port :针对此端口进行检测
inter <delay> :连续两次检测之间的时间间隔,默认为2000ms
rise <count>:连续多少次检测结果为“成功”才标记服务器为可用 ;默认为2
fall <count>:连续多少次检测结果为“失败”才标记服务器为不可 用;默认为3
cookie <value>:为当前server指定cookie值,实现基于cookie的会话黏性
disabled:标记为不可用
redir <prefix>:将发往此server的所有GET和HEAD类的请求重定向至指定的URL
12.cookie配置
cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ] [ postonly ] [ preserve ] [ httponly ] [ secure ] [ domain ]* [ maxidle ] [ maxlife <life> ]
<name> :cookie名称,用于实现持久连接
rewrite:重写
insert:插入
prefix:前缀
配置示例
基于cookie的session sticky的实现:
backend websrvs
cookie WEBSRV insert nocache indirect
server srv1 172.16.100.6:80 weight 2 check rise 1 fall 2 maxconn 3000 cookie srv1
server srv2 172.16.100.7:80 weight 1 check rise 1 fall 2 maxconn 3000 cookie srv2
13. 统计接口启用相关的参数
stats enable
启用统计页;基于默认的参数启用stats page
- stats uri : /haproxy?stats uri默认值
- stats realm : HAProxy\ Statistics
- stats auth : no authentication
stats uri <prefix>
自定义stats page uri
stats auth <user>:<passwd>
认证时的账号和密码,可使用多次
stats realm <realm>
认证时的realm
stats hide-version
隐藏版本
stats refresh <delay>
设定自动刷新时间间隔
stats admin { if | unless } <cond>
启用stats page中的管理功能
配置示例:
listen stats
bind :9099
stats enable
stats realm HAPorxy\ Stats\ Page
stats auth admin:admin
stats admin if TRUE
14.工作模式
maxconn :为指定的frontend定义其最大并发连接 数;默认为2000
mode { tcp|http|health }
定义haproxy的工作模式
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
15.健康状态检测
对后端服务器做http协议的健康状态检测:
option httpchk 默认为:/ OPTIONS HTTP/1.0
option httpchk <uri>
option httpchk <method> <uri>
option httpchk <method> <uri> <version>
定义基于http协议的7层健康状态检测机制
http-check expect [!] <match> <pattern>
http协议健康状态检测响应内容或指定响应码
16.forwardfor配置
option forwardfor [ except <network> ] [ header <name> ] [ if-none ]
在由haproxy发往后端主机的请求报文中添加“X-ForwardedFor”首部,其值为前端客户端的地址;用于向后端主发送真实的客户端IP
[ except <network> ]:请求报请来自此处指定的网络时不予 添加此首部,如haproxy自身所在网络
[ header <name> ]:使用自定义的首部名称,而非“XForwarded-For”
[ if-none ] 如果没有首部才添加首部,如果有使用默认值
为指定的MIME类型启用压缩传输功能
compression algo ...:启用http协议的压缩机 制,指明压缩算法gzip, deflate
compression type ...:指明压缩的MIMI类型
17.错误页配置
errorfile <code> <file> 自定义错误页
<code> :HTTP status code.
支持200, 400, 403, 408, 500, 502, 503, 504\.
<file>:错误页文件路径
示例:
errorfile 400 /etc/haproxy/errorfiles/400badreq.http
errorfile 408 /dev/null # workaround Chrome preconnect bug
errorfile 403 /etc/haproxy/errorfiles/403forbid.http
errorfile 503 /etc/haproxy/errorfiles/503sorry.http
errorloc <code> <url>
相当于errorloc302 ,利用302重定向至指URL
errorloc 503 http://www.magedu.com/error_pages/503.html
报文首部
修改报文首部
* reqadd <string>[{if | unless} <cond> ]
在请求报文尾部添加指定首部
* rspadd <string> [{if | unless} <cond> ]
在响应报文尾部添加指定首部
示例: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.*
连接超时
* 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> 后端服务器半连接的空闲时长
18.ACL
acl:访问控制列表(ACL)的使用提供了一个灵活的解决方 案来执行内容交换,并且通常基于从请求中提取的内容、响 应或任何环境状态进行决策
acl <aclname> <criterion> [flags] [operator] [<value>]
...
<aclname>:ACL名称,可使用字母 数字 : . - _
区分字符大小写
<criterion>: 比较的标准和条件
<value>的类型:
- boolean
- integer or integer range
- IP address / network
- string (exact, substring, suffix, prefix, subdir, domain)
- regular expression
- hex block
<flag>
-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进行匹配
acl作为条件时的逻辑关系:
- 与:隐式(默认)使用
- 或:使用“or” 或 “||”表示
- 否定:使用“!“ 表示
示例: if invalid_src invalid_port 与关系
if invalid_src || invalid_port 或
if ! invalid_src 非
<criterion>:各种条件
dst 目标IP
dst_port 目标PORT
src 源IP
src_port 源PORT
示例:acl invalid_src src 172.16.100.200
base : string
返回第一个主机头和请求的路径部分的连接,该请求从第一个斜杠开始,并在问号之前结束,对虚拟主机有用
<scheme>://<user>:<passwd>@<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
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
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
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
示例:
acl bad_curl hdr_sub(User-Agent) -i curl
block if bad_curl
status : integer
返回在响应报文中的状态码
* 预定义ACL
ACL名称 等价于 说明
TRUE always_true 总是匹配
FALSE always_false 从不匹配
HTTP req_proto_http 匹配HTTP协议
HTTP_1.0 req_ver 1.0 匹配HTTP协议1.0
HTTP_1.1 req_ver 1.1 匹配HTTP协议1.1
HTTP_CONTENT hdr_val(content-length) gt 0 匹配已存在内容长度
HTTP_URL_ABS url_reg ^[^/:]*:// 匹配URL绝对路径
HTTP_URL_SLASH url_beg / 匹配URL相对路径
HTTP_URL_STAR url * 匹配 URL 等于 "*"
LOCALHOST src 127.0.0.1/8 匹配从localhost来的连接
METH_CONNECT method CONNECT 匹配HTTP CONNECT方法
* ACL
METH_GET method GET HEAD match HTTP GET or HEAD method
METH_HEAD method HEAD match HTTP HEAD method
METH_OPTIONS method OPTIONS match HTTP OPTIONS method
METH_POST method POST match HTTP POST method
METH_TRACE method TRACE match HTTP TRACE method
RDP_COOKIE req_rdp_cookie_cnt gt 0 match presence of an RDP cookie
REQ_CONTENT req_len gt 0 match data in the request buffer
WAIT_ENDwait_end wait for end of content analysis
19.配置
use_backend <backend>[{if | unless} <condition>]
当if/unless一个基于ACL的条件匹配时切换指定backend
block { if | unless } <condition>
阻止7层请求if/unless一个条件匹配
示例:
acl invalid_src src 172.16.200.2
block if invalid_src
errorfile 403 /etc/fstab
http-request { allow | deny |add-header <name> <fmt> |set-header <name> <fmt>} [ { if | unless } <condition> ]
对7层请求的访问控制
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
基于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
20.支持https协议
配置HAProxy支持https协议:
1 支持ssl会话;
bind *:443 ssl crt /PATH/TO/SOME_PEM_FILE
crt 后证书文件为PEM格式,且同时包含证书和所有私钥
cat demo.crt demo.key > demo.pem
2 把80端口的请求重向定443
bind *:80
redirect scheme https if !{ ssl_fc }
3 向后端传递用户请求的协议和端口(frontend或backend)
http_request set-header X-Forwarded-Port %[dst_port]
http_request add-header X-Forwared-Proto https if { ssl_fc }