HAProxy代理
---------------------------------------------------------------------------------------------------------------------------------------------
一、介绍
1、应对客户端c10k以上同时连接的高性能的TCP和HTTP负载均衡器,其功能是用来提供基于cookie的持久性,基于内容的交换,过载保护的高级流浪管制,自动故障切换,以正则表达式为基础的控制运行时间,基于web的报表,高级日志记录以帮助排除故障的应用或网络及其他功能
2、LB Cluster
四层:lvs,nginx(stream),haproxy(mode tcp)
七层:http:ngxin(http),haproxy(mode httpd),httpd
3、
官网:www.haproxy.org,www.haproxy.com
文档:https://cbonte.github.io/haproxy-dconv/
二、功能
HAProxy是TCP/HTTP反向代理服务器,尤其适合于高可用环境
可以针对HTTP请求添加cookie,进行路由后端服务器
可平衡负载至后端服务器,并支持持久连接
支持基于cookie进行调度
支持所有主服务器故障切换至备用服务器
支持专用端口实现监控服务
支持不影响现有连接情况下停止接受新连接请求
可以在双向添加,修改或删除HTTP报文首部
支持基于pattern实现连接请求的访问控制
通过特定的URI为授权用户提供详细的状态信息
支持http反向代理
支持动态程序的反向代理
支持基于数据库的反向代理
三、haparoxy组成
1、光盘base源有安装包,安装好后服务名称叫haproxy,systemctl start haproxy打开5000端口
2、程序环境:
主程序:/usr/sbin/haproxy
配置文件:/etc/haproxy/haproxy.cfg
Unit file:/usr/lib/systemd/system/haproxy.service
3、配置段:
(1)global:全局配置段
进程及安全配置相关的参数
性能调整相关参数
Debug参数
(2)proxies:代理配置段
defaults:为frontend, backend, listen提供默认配置
frontend:前端,相当于nginx中的server {}
backend:后端,相当于nginx中的upstream {}
listen:同时拥有前端和后端,适用于一对一环境
配置文件 vim /etc/haproxy/haproxy
代理设置,一端面对客户端,一面面对服务器端
4、配置示例
简单的配置示例:
frontend web 发布到外网的应用
bind *:80 请求到本机器的端口
default_backend websrvs 这个请求就会调度到后端的某个名叫websrvs的backend服务器上
backend websrvs
balance roundrobin 轮询算法
server srv1 192.168.0.101:80 check 健康性检查
server srv2 192.168.0.102:80 check 健康性检查
此时已经简单实现调度
当关闭一台设备时,有现象
四、global配置
1、global配置参数:
进程及安全管理:chroot, deamon,user, group, uid, gid
nbproc
ulimit-n
daemon 后端方式运行,建议使用
log 定义全局的syslog服务器;最多可以定义两个
log
[lenaddress: rsyslog服务器地址
len: 记录日志的长度,默认1024
2、log:
log global
log
[lenlength 日志行的长度,默认1024
no log
注意:
默认发往本机的日志服务器
(1) local2.* /var/log/local2.log
(2) $ModLoad imudp
$UDPServerRun 514
3、log-format:自定义log格式,https://cbonte.github.io/haproxy-dconv/1.9/configuration.html#8.2.4
4、演示打开log方式
vim /etc/rsyslog.cfg
启用514端口
并在此处
已打开进程
日志已经生成
5、日志管理
将特定信息记录在日志中
(1)capture cookie
捕获请求和响应报文中的 cookie并记录日志
(2)capture request header
捕获请求报文中指定的首部并记录日志
示例:
capture request header X-Forwarded-For len 15
(3)capture response header
捕获响应报文中指定的首部并记录日志
示例:
capture response header Content-length len 9
capture response header Location len 15
五、性能调整
maxconn
maxconnrate
maxse***ate
maxsslconn
spread-checks <0..50, in percent> 健康检测延迟时长百分比,建议2-5之间
六、配置段
1、代理配置段:
- defaults
- frontend
- backend
- listen
2、Frontend段:指定接收客户端连接侦听套接字设置
3、Backend段:指定将连接请求转发至后端服务器的相关设置
4、Listen段:指定完整的前后端设置
5、proxy 名称:使用字母 数字 - _ . : 并区分字符大小写
6、配置参数:
bind:指定一个或多个前端侦听地址和端口,只能放在frontend和listen
bind [
]:示例:
listen http_proxy
bind :80,:443
bind 10.0.0.1:10080,10.0.0.1:10443
bind /run/ssl-frontend.sock user root mode 600 accept-proxy ---->对本地的用户root,用套接字提供服务,权限是600
注意:listen只能实现一对一的方式,一对多,多对多还是用frontend和backend,但在一对一的方式中推荐还是用frontend和backend方式,便于修改和拓展
七、调度算法
1、balance:后端服务器组内的服务器调度算法,不能放在frontend,可放在defaults、listen和 backend
balance
balance url_param [check_post]
2、调度算法:
(1)roundrobin:基于权重轮询,动态算法,支持权重的运行时调整,支持慢启动;每个后端backend中最多支持4095个server
server options: weight #
(2)static-rr:基于权重轮询,静态算法,不支持权重的运行时调整及慢启动;后端主机数量无上限
(3)leastconn:加权最少连接,动态算法,最少连接的后端服务器优先分配接收新连接,相同连接时轮询,推荐在较长会话的场景使用,例如MySQL,LDAP等,不适合http
(4)first:根据服务器在列表中的位置,自上而下进行调度;前面服务器的连接数达到上限,新请求才会分配给下一台服务,不支持权重
(5)source:源地址hash,新连接先按权重分配,后续连接按source分配请求,实现会话绑定
举例:除权取余法说明,对ip做哈希运算并对3进行取模,值只会出现0、1、2,当三台设备权重一样时,就可以将取模值为0的调入rs1,取模为1时调入rs2,取模为2时调入rs3
hash(ip1)%3 0 rs1 1
hash(ip2)%3 1 rs2 1
hash(ip3)%3 2 rs3 1
当权重不一样时,对于取模的值进行权重的累加,计算后按比例分配,取模值为0时调入rs1,取模为1、2 时调入rs2,取模为3、4、5时调入rs3
hash(ip1)%6 0 rs1 1
hash(ip2)%6 1,2 rs2 2
hash(ip3)%6 3,4,5 rs3 3
优点:会话绑定,同一个ip调入同一个rs服务器
缺点:增加rs服务器后一切都需要重新计算;也有可能一个外网ip后面有很多私网ip设备,造成设备分配很粗糙
(6)uri:对URI的左半部分或整个uri做hash计算,并除以服务器总权重取模,以后派发至某挑出的服务器,适用于后端缓存服务器,一般配合varnish缓存服务器
左半部分:/
整个uri:/
(7)url_param:对用户请求的uri中的
http://www.chenux.com/bbs/hello;type=title
(8)hdr(
根据浏览器类型调度
curl -A,模仿哪种浏览器进行访问
(9)hdr(Cookie),根据cookie调度
(10)rdp-cookie 远程桌面相关
rdp-cookie(
八、哈希算法
1、hash-type:哈希算法
hash-type
method:
map-based:除权取余法,哈希数据结构是静态数组,刚才上述的举例已说明
consistent:一致性哈希,哈希数据结构是一棵树
function : 哈希函数,取值:sdbm,djb2,wt6
modifier: 取值avalanche时,将修改哈希值,而非直接使用
2、default_backend
无use_backend 匹配时,使用默认的backend,用于frontend中
3、default-server [param*]
为backend中的各server设定默认选项,为后端服务器定义默认值
一致性哈希算法说明:在除权取余法的例子中,如果3台服务器突然故障一台变成2台或者3台服务器不够用需要增加1台,之前该服务器上的文件的缓存位置必定发生改变,以前缓存的图片也失去缓存的作用和意义。如果是服务器故障,由于大量缓存同一时间失效,造成了缓存的雪崩,此时前端缓存已经无法起到承担部分压力的作用,后端服务器将会承受巨大压力,整个系统也很有可能崩溃。该种情况是无法避免,一致性哈希算法就是来解决这种问题的。
一致性哈希还是取余的做法,只不过是对ip进行hash后,再对2^32进行取余,如果有3台服务器,我们将这3台服务器映射到hash环上,当某个缓存服务器的缓存文件被访问时,该文件也是经过了hash后对2^32取余
被访问的文件经过hash取余运算后,从被缓存对象的位置出发,沿顺时针方向遇到的第一个服务器,将会是该文件将要缓存与服务器,在服务器不变情况下,一个文件必定会被 缓存到固定的服务器上,当下次想要访问这个文件时,再次使用相同的算法即可算出这个图片被缓存在哪个服务器上,图中所示file将被缓存到B上
假如B和C之间也有个file2,file2将会缓存到C上,当B被移除,file2的缓存不变,file1缓存将会移动至C,服务器数量发生改变,并不是所有缓存都失效,而是只有部分会失效,前端仍然能分担整个系统的压力
由于实际情况不可能说三台设备均匀分布在环上,所以引入虚拟节点,虚拟节点越多缓存被均匀分布的概率越大
九、配置
server
定义后端主机的各服务器及其选项
server
default-server [settings ...]
[:[port]]:端口映射;省略时,表示同bind中绑定的端口
[param*]:参数
weight
maxconn
backlog
backup:设定当前server为备用服务器Sorry Server
示例:在haproxy中建立sorry server
1、安装httpd或者nginx
在配置文件中更改监听端口,80被haproxy监听,需要更改不被监听的端口
2、更改haproxy配置文件
3、测试
十、健康状态监测
1、check:对当前server做健康状态检测,只用于四层检测
注意:httpchk,“smtpchk”, “mysql-check”, “pgsql-check” and “ssl-hello-chk” 用于定义应用层检测方法
addr :检测时使用的IP地址
port :针对此端口进行检测
inter
rise
fall
2、disabled:标记为不可用,加入此项后将不往标记该台的后端设备调度
3、redir
十一、cookie配置
1、cookie
cookie
rewrite:重写
insert:插入
prefix:前缀
nocache:当client和hapoxy之间有缓存时,不缓存cookie
2、基于cookie的session sticky的实现
backend websrvs
cookie WEBSRV insert nocache
server srv1 172.16.0.6:80 weight 2 check rise 1 fall 2 maxconn 3000 cookie srv1
server srv2 172.16.0.7:80 weight 1 check rise 1 fall 2 maxconn 3000 cookie srv2
十二、统计接口启用相关的参数
1、stats enable
启用统计页;基于默认的参数启用stats page
之后访问http://ip/haproxy?stats,即出现
2、stats hide-version 隐藏版本
3、stats refresh
设定自动刷新时间间隔
4、stats uri
自定义stats page uri,默认值:/haproxy?stats
5、stats realm
认证时的realm,示例:stats realm : HAProxy\ Statistics
6、stats auth
认证时的账号和密码,可使用多次,默认:no authentication
7、stats admin { if | unless }
启用stats page中的管理功能
配置示例
listen stats
bind :9527
stats enable
stats hide-version
stats uri /hastats
stats realm HAPorxy\ Stats\ Page
stats auth admin1:password1
stats auth admin1:password2
stats refresh 3s
stats admin if TRUE
drain:排干,将服务器上的用户踢掉,之后逐渐下线
十三、工作模式
1、maxconn
2、mode { tcp|http|health }
定义haproxy的工作模式
tcp:基于layer4实现代理;可代理mysql, pgsql, ssh, ssl等协议,https时使用此模式,默认模式
http:仅当代理协议为http时使用,CentOS中haproxy实际的默认模式
health:工作为健康状态检查的响应模式,当连接请求到达时回应“OK”后即断开连接,较少使用
3、示例
listen ssh
bind :22022
balance leastconn
mode tcp
server sshsrv1 172.16.0.6:22 check
server sshsrv2 172.16.0.7:22 check
ssh IP -p 22022,即可ssh登录
十四、健康状态检测,应用层检查
对后端服务器做http协议健康状态检测:通常用于bendend
option httpchk 默认向后端服务器发请求:OPTIONS / HTTP/1.0
option httpchk
option httpchk
option httpchk
定义基于http协议的7层健康状态检测机制
http-check expect [!]
http协议健康状态检测响应内容或指定响应码
十五、forwardfor配置
1、option forwardfor [ except
在由haproxy发往后端主机的请求报文中添加“X-Forwarded-For”首部,其值为前端客户端的地址;用于向后端主发送真实的客户端IP
在后端RS服务器上/etc/httpd/conf/httpd.conf中,添加X-Forwarded-For
[ except
如haproxy自身所在网络
[ header
示例:在haproxy主机上
在RS服务器上改
[ if-none ] 如果没有首部才添加首部,如果有使用默认值
2、为指定的MIME类型启用压缩传输功能
compression algo
compression type
十六、错误页配置
1、errorfile
:HTTP status code.
支持200, 400, 403, 408, 500, 502, 503, 504.
2、示例:
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
3、errorloc
相当于errorloc302
示例:errorloc 503 http://www.chenux.com/error_pages/503.html
十七、修改报文首部
1、在请求报文尾部添加指定首部
reqadd
2、在响应报文尾部添加指定首部
rspadd
示例:rspadd X-Via:\ HAPorxy
3、 从请求报文中删除匹配正则表达式的首部
reqdel
reqidel
4、从响应报文中删除匹配正则表达式的首部
rspdel
rspidel
示例: rspidel server.*
十八、连接超时
1、timeout client
客户端最长空闲连接超时时长 默认单位是毫秒
2、timeout server
后端服务器最长空闲连接超时时长
3、timeout http-keep-alive
持久连接的持久时长
4、timeout http-request
一次完整的HTTP请求的最大等待时长
5、timeout connect
成功连接后端服务器的最大等待时长
6、timeout client-fin
客户端半连接的空闲时长
7、timeout server-fin
后端服务器半连接的空闲时长
十九、ACL
1、acl:访问控制列表(ACL)的使用提供了一个灵活的解决方案来执行内容交换,并且通常基于从请求中提取的内容、响应或任何环境状态进行决策
2、acl
acl acl名称 参数 [选项] 匹配 [值]
(1)
- boolean
- integer or integer range
- IP address / network
- string (exact, substring, suffix, prefix, subdir, domain)
- regular expression
- hex block
(2)
-i 不区分大小写
-m 使用指定的pattern匹配方法
-n 不做DNS解析
-u 强制每个ACL必须唯一ID,否则多个同名ACL或关系
-- 强制flag结束. 当字符串和某个flag相似时使用
(3)[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进行匹配
(4)acl作为条件时的逻辑关系:
- 与:隐式(默认)使用
- 或:使用“or” 或 “||”表示
- 否定:使用“!“ 表示
示例:if invalid_src invalid_port 与关系
if invalid_src || invalid_port 或
if ! invalid_src 非
(5)
dst 目标IP
dst_port 目标PORT
src 源IP
src_port 源PORT
示例:acl invalid_src src 172.16.100.200
演示1
演示2
结果
(6)base : string
返回第一个主机头和请求的路径部分的连接,该请求从第一个斜杠开始,并在问号之前结束,对虚拟主机有用
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
(7)path : string,官方建议最好用path,比url好用
提取请求的URL路径,该路径从第一个斜杠开始,并在问号之前结束(无主机部分)
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
示例:
path_beg /images/
path_end .jpg .jpeg .png .gif
path_reg ^/images.*\.jpeg$
path_sub image
path_dir jpegs
path_dom magedu
/images/jpegs/20180123/logo.jpg
(8)url : string
提取请求中的URL。一个典型的应用是具有预取能力的缓存,以及需要从数据库聚合多个信息并将它们保存在缓存中的网页门户入口,推荐使用path
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
(9)req.hdr([
提取在一个HTTP请求报文的首部
hdr([
hdr_beg([
hdr_dir([
hdr_dom([
hdr_end([
hdr_len([
hdr_reg([
hdr_sub([
示例:
acl bad_agent hdr_sub(User-Agent) -i curl wegt
block if bad_agent
可引申出:
(10)status : integer
返回在响应报文中的状态码
(11)预定义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方法 |
METH_GET |
method GET HEAD |
match HTTP GET or HEAD method |
METH_HEAD |
method HEAD |
match HTTP GET 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_END |
wait_end |
wait for end of content analysis |
3、配置
(1)use_backend
当if/unless一个基于ACL的条件匹配时切换指定backend
(2)block { if | unless }
阻止7层请求if/unless一个条件匹配
示例:
acl invalid_src src 172.16.200.2
block if invalid_src
errorfile 403 /usr/share/haproxy/403.http
(3)http-request { allow | deny |add-header
对7层请求的访问控制
(4)tcp-request connection {accept|reject} [{if | unless}
根据第4层条件对传入连接执行操作
示例:
listen ssh
bind :22222
mode tcp
balance leastconn
acl invalid_src src 172.16.0.200
tcp-request connection reject if invalid_src
server sshsrv1 192.168.1.101:22 check
server sshsrv2 192.168.1.102: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 staticsrv1 192.168.0.100:80 check
backend appsrvs
balance roundrobin
server app1 192.168.0.101:80 check
server app1 192.168.0.102:8080 check
二十一、支持https协议
1、配置HAProxy支持https协议:
2、支持ssl会话;
bind *:443 ssl crt /PATH/TO/SOME_PEM_FILE
crt 后证书文件为PEM格式,且同时包含证书和所有私钥
cat demo.crt demo.key > demo.pem
3、把80端口的请求重向定443
bind *:80
redirect scheme https if !{ ssl_fc }
4、向后端传递用户请求的协议和端口(frontend或backend),加入此项意义在于抓取log时便于查看
http_request set-header X-Forwarded-Port %[dst_port]
http_request add-header X-Forwared-Proto https if { ssl_fc }
实现过程:该模式需要在http模式下进行
1、cd /etc/pki/tls/certs/
make a.pem
注意:如果按照以往方法是生成a.key和a.crt,将它们用cat a.key a.crt > a.pem就可以合到一起,a.pem里面包含证书和私钥
cp a.pem /etc/haproxy
2、更改haproxy配置文件,此时curl -k http和https都能通,但curl -k http时没有实现跳转
3、继续改配置文件,重启后完成