HAProxy是一个使用C语言编写的自由及开放源代码软件,其提供高可用性、负载均衡,以及基于TCP和HTTP的应用程序代理。
画的不太好,有理解问题请批评指正
frontend负责给用户请求一个接口,backend可以定义后端一组服务器,一个frontend可以拥有多个backend,一个backend也可以让多个不同的frontend调用
具体流程就是当frontend接受到用户请求,根据我们的配置交给指定的backend处理请求。backend再将请求分发到真正的后端服务器
而listen定义一个完整的代理,其前端和后端部分组合在一个部分中。看到后面示例的配置项就能更好理解了。
HAProxy的配置文件为/etc/haproxy/haproxy.cfg
配置文件分为几个部分
虽然说是调整性能的参数,但是一般情况下没有特殊需求,不建议修改
格式:bind \[\]: [, ...] [param*]
格式:balance [ ]
常用的调度算法算法:
roundrobin:动态算法:支持权重的运行时调整,支持慢启动;每个后端中最多支持4095个server;
static-rr:静态算法:不支持权重的运行时调整及慢启动;后端主机数量无上限;
leastconn:推荐使用在具有较长会话的场景中,例如MySQL、LDAP等;
first:根据服务器在列表中的位置,自上而下进行调度;前面服务器的连接数达到上限,新请求才会分配给下一台服务器;
source:基于源地址hash;把每个IP和第一次调度处理的后台服务器的对应关系映射成hash表存放在内存中,这里的hash算法有2种:
第一种是除权取余算法,举个例子:将源地址进行hash除权再取余,假如得到的数字是1,则分配到第一台服务器,假如最后得到的是2,则分配到第二台服务器上,得到的是3这个值则分配到第三台服务器上,以此类推。
只要源地址不变,服务器组权重不变,则hash值不会变,余数也不会变。所以可以做到会话保持,同一个ip可以发送给同一个后端服务器。但是如果这时候服务器组数量发生增减,权重发生变化会怎么样?
很容易理解,得到的值可能会发生变化,并且由于服务器组数量增减,导致大部分ip绑定全部失效....这个就很严重了。
第二种是一致性哈希算法,形象来说就是维持一个hash环,这个环的整数分布范围是[0, 2^32-1],然后将后端服务器分布在环上,这时候再对源地址进行hash,得到的值投射在环上,顺时针寻找离这个值最近的一台服务器。
由它来负责响应。同理只要是同一个ip进来 hash值一定是一样的。服务器组结构没有发生变化也一定会分配到同一个服务器上,这时候如果服务器增减,会发生什么呢?比如第二台服务器down了,
于是顺时针找最近的原则,会分配到下一台,这时候只影响了一台服务器。这样影响的服务器就会大大减少。好很多。但是维持一个hash环的成本显然高一些。所以看情况使用吧。
算法可以在hash-type这个配置项设置
参考
://:@:/;?#
左半部分:/;
整个uri:/;?#
uri:对URI的左半部分做hash计算,并由服务器总权重相除以后派发至某挑出的服务器;
url_param:对用户请求的uri听部分中的参数的值作hash计算,并由服务器总权重相除以后派发至某挑出的服务器;通常用于追踪用户,以确保来自同一个用户的请求始终发往同一个Backend Server;
hdr():对于每个http请求,此处由指定的http首部将会被取出做hash计算; 并由服务器总权重相除以后派发至某挑出的服务器;没有有效值的会被轮询调度;
例子:hdr(Cookie)
格式:hash-type
method有:
map-based:除权取余法,哈希数据结构是静态的数组;
consistent:一致性哈希,哈希数据结构是一个树;
格式:
server [:[port]] [param*]
server [:port] [settings ...]
default-server [settings ...] :server的默认参数
:服务器在haproxy上的内部名称;出现在日志及警告信息;
:服务器地址,支持使用主机名;
[:[port]]:端口映射;省略时,表示同bind中绑定的端口;
[param*]:常用的参数如下
maxconn :当前server的最大并发连接数;
maxqueue :队列的最大长度。maxconn满了,多余的请求就需要放在队列中。
backlog :当前server的连接数达到上限后的后援队列长度;
backup:设定当前server为备用服务器;即sorry server
check:对当前server做健康状态检测;
addr :设置检测时使用的IP地址
port :设置端口进行健康检测;
inter :连续两次检测之间的时间间隔,默认为2000ms;
rise :连续多少次检测结果为“成功”才标记服务器为可用;默认为2;
fall :连续多少次检测结果为“失败”才标记服务器为不可用;默认为3;
注意:httpchk,"smtpchk", "mysql-check", "pgsql-check" and "ssl-hello-chk" 用于定义应用层检测方法;
cookie :为当前server指定其cookie值,用于实现基于cookie的会话黏性;
disabled:标记为不可用;
on-error :后端服务器故障时的行动策略
- fastinter: force fastinter
- fail-check: 快速强制检测,还没到下一个检测周期,快速触发一次故障探测
- sudden-death:一次失败直接标记为down
- mark-down: 立即标记为down并强制down
redir :将发往此server的所有GET和HEAD类的请求重定向至指定的URL;
weight :权重,默认为1;
示例:
server first 10.1.1.1:1080 cookie first check inter 1000
server second 10.1.1.2:1080 cookie second check inter 1000
server backup ${SRV_BACKUP}:1080 backup
stats enable:启用统计页;基于默认的参数启用stats page;
stats auth ::认证时的账号和密码,可使用多次;默认不需要认证
stats realm :认证时的标题,提示;默认为 "HAProxy Statistics"
stats uri :自定义stats page uri,访问的接口,默认 /haproxy?stats,
stats refresh :设定自动刷新时间间隔;
stats admin { if | unless } :启用stats page中的管理功能
stats hide-version 隐藏版本信息
配置示例:
listen stats
bind :9099
stats enable
stats uri /haproxy?admin
stats realm HAPorxy\ Stats\ Page
stats auth admin:haproxy
stats admin if TRUE
访问uri为:http://HAProxy_IP:9099/haproxy?admin
maxconn
格式:mode { tcp|http|health }
tcp:基于layer4实现代理;可代理mysql, pgsql, ssh, ssl等协议;
http:仅当代理的协议为http时使用;
health:工作为健康状态检查的响应模式,当连接请求到达时回应“OK”后即断开连接;
代理ssh示例:
listen ssh
bind :22022
balance roundrobin
mode tcp
server sshsrv1 192.168.253.158:22 check
server sshsrv1 192.168.253.128:22 check
格式:cookie [ rewrite | insert | prefix ] [ indirect ] [ nocache ] [ postonly ] [ preserve ] [ httponly ] [ secure ] [ domain ]* [ maxidle ] [ maxlife ]
:自定义名称作为键
rewirte:重写;将已有的cookie重写
insert:插入;
prefix:前缀;
基于cookie的session sticky的实现:
backend websrvs
cookie WEBSRV insert nocache indirect #仅对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
格式:option forwardfor [ except ] [ header ] [ if-none ]
[ except ]:请求报请来自此处指定的网络时不予添加此首部;
[ header ]:使用自定义的首部名称,而非“X-Forwarded-For”;
示例:
backend static
mode http
option forwardfor header X-Client
......
如果是nginx,自定义日志格式的时候需要写成$http_X_Client 来获取值,若为httpd,%{X-Client}i获取指定首部信息。
errorfile 这里需要是文件路径
:响应码,常用以下几个200, 400, 403, 408, 500, 502, 503, and 504.
:响应的文件路径
示例:
errorfile 400 /etc/haproxy/errorfiles/400badreq.http
errorfile 408 /dev/null # workaround Chrome pre-connect bug
errorfile 403 /etc/haproxy/errorfiles/403forbid.http
errorfile 503 /etc/haproxy/errorfiles/503sorry.http
格式:errorloc
示例:
errorfile 403 http://www.magedu.com/error_pages/403.html
格式:reqadd [{if | unless} ]
rspadd [{if | unless} ]
例子:
rspadd X-Via:\ HAPorxy
格式:reqdel [{if | unless} ]
格式:rspdel [{if | unless} ]
log
格式:log [len ] [ []]
haproxy默认没有记录日志的文件,需要依赖rsyslog收集,具体方法,首先在配置文件的global段添加一条配置项
log 127.0.0.1 local2
再修改/etc/rsyslog.conf
$ModLoad imudp #取消注释
$UDPServerRun 514 #取消注释
local2.* /var/log/haproxy.log #添加一行
然后重启
systemctl restart rsyslog haproxy
log-format :设置日志格式
格式:log-format
示例:
log-format %{+Q}o\ %t\ %s\ %{-Q}r
compression algo ...:启用http协议的压缩机制,指明压缩算法gzip, deflate;
compression type ...:指明压缩的MIMI类型;
示例:
compression algo gzip
compression type text/html text/plain
格式:
option httpchk:定义基于http协议的7层健康状态检测机制
option httpchk
option httpchk
option httpchk
示例:
backend https_relay
mode tcp
option httpchk OPTIONS * HTTP/1.1\r\nHost:\ www
server apache1 192.168.1.1:443 check port 80
timeout client : 客户端一侧链接的非活动时长,默认单位是毫秒;
timeout server :连接后端服务器一侧的非活动时长,如果时长足够长,就可以减少一些连接创建的开销。所以尽量长会好一些
timeout http-keep-alive :持久连接的持久时长;
timeout http-request :请求报文的超时时长,如果客户端一侧非常慢的发送,则服务器要维持这个连接就很浪费资源,这个就是请求报文的超时时长
timeout connect :创建连接的超时时长。如果一直连接后端服务器不成功,
timeout client-fin :客户端一侧非活动的半连接的超时时长
timeout server-fin :服务端一侧非活动的半连接的超时时长
格式: use_backend [{if | unless} ]
例子:
acl static path_beg -i /static /images /javascript /stylesheets
acl static path_end -i .jpg .gif .png .css .js .html
acl php path_end -i .php
use_backend static if static
use_backend dynamic if php
格式:block { if | unless }
例子:
acl invalid_src src 0.0.0.0/7 224.0.0.0/3
acl invalid_src src_port 0:1023
acl local_dst hdr(host) -i localhost
block if invalid_src || local_dst
格式:http-request { allow | deny } [ { if | unless } ]
示例:
http-request replace-value X-Forwarded-For ^192\.168\.(.*)$ 172.16.\1
报文首部为: X-Forwarded-For: 192.168.10.1, 192.168.13.24, 10.0.0.37
输出之后为: X-Forwarded-For: 172.16.10.1, 172.16.13.24, 10.0.0.37
格式:tcp-request connection {accept|reject} [{if | unless} ]
示例:
mode tcp
acl invalid_src src 172.16.200.2
tcp-request connection reject if invalid_src
格式:acl [flags] [operator] [] ...
:自定义的acl名,ACL名称必须由大写和小写字母,数字,' - '(短划线)组成,'_'(下划线),'.'(点)和':'(冒号)。ACL名称区分大小写
的类型:
- 布尔值
- 整数
- IP address / network ip地址
- 字符串
- 正则表达式
- 16进制
-i : 忽略字符大小写
-m : 使用特定的匹配方式(一般不用)
-n : 禁止dns主机名反解
-u : 每个acl必须使用独有的名称,默认可以重名,如果重名,表示的是或条件,满足其中一个即可
-- : 强行指名flag到哪结束,避免混淆
[operator]
匹配整数值:eq、ge、gt、le、lt
匹配字符串:不怎么用
- exact match (-m str) : 精确匹配
- substring match (-m sub) : 子串匹配
- prefix match (-m beg) :前缀匹配
- suffix match (-m end) : 后缀匹配
- subdir match (-m dir) : 子路径匹配
- domain match (-m dom) : 域名子串匹配
acl作为条件时的逻辑关系:
- AND (implicit)
- OR (explicit with the "or" keyword or the "||" operator)
- Negation with the exclamation mark ("!")
示例:
if invalid_src invalid_port
if invalid_src || invalid_port
if ! invalid_src invalid_port
:
dst : ip
dst_port : 端口
src : ip
src_port : 端口
示例:
acl invalid_src src 172.16.200.2
path : string
path : exact string match 精确匹配,例如:/imgs/logos/logo.jpg
path_beg : prefix match 前缀匹配,例如: /imgs 表示/imgs下的所有内容都匹配
path_dir : subdir match 路径子串匹配
path_dom : domain match 域名子串匹配
path_end : suffix match 后缀匹配 ,例如:.jpg ;以.jpg结尾都匹配
path_len : length match 长度匹配
path_reg : regex match 正则匹配 ,例如:^/imgs/.*\.jpg 表示/imgs开头以.jpg结尾
path_sub : substring match 子串匹配 只要包含该子串就可以匹配到
下面的例子用于测试URL是否以/static、/images、/javascript或/stylesheets头。
acl url_static path_beg -i /static /images /javascript /stylesheets
例如,下面的例子用户测试URL是否以jpg、gif、png、css或js结尾。
acl url_static path_end -i .jpg .gif .png .css .js
url : string
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([[,]]) : string
hdr([[,]]) : exact string match
hdr_beg([[,]]) : prefix match
hdr_dir([[,]]) : subdir match
hdr_dom([[,]]) : domain match
hdr_end([[,]]) : suffix match
hdr_len([[,]]) : length match
hdr_reg([[,]]) : regex match
hdr_sub([[,]]) : substring match
下面的例子用于测试首部Connection的值是否为close。
hdr(Connection) -i close
下面的例子用记测试请求是否为提供静态内容的主机img、video、download或ftp。
acl host_static hdr_beg(host) -i img. video. download. ftp.
示例:
acl bad_curl hdr_sub(User-Agent) -i curl 拒绝curl访问
block if bad_curl
global
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
stats socket /var/lib/haproxy/stats
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
frontend webservs
bind *:788
acl static path_beg -i /static /images /javascript /stylesheets
acl static path_end -i .jpg .gif .png .css .js .html
acl php path_end -i .php
use_backend static if static
use_backend dynamic if php
default_backend dynamic
backend static
balance roundrobin
server sta1 192.168.253.128:6080 check maxconn 3000
server sta2 192.168.253.128:7080 check maxconn 3000
backend dynamic
balance source
server dyn 192.168.253.128:7080 check maxconn 1000
listen ssh
bind :22022
balance roundrobin
mode tcp
server sshsrv1 192.168.253.158:22 check
server sshsrv1 192.168.253.128:22 check
参考链接
http://cbonte.github.io/haproxy-dconv/1.5/configuration.html