haproxy高级功能-进阶
高级功能
基于cookie会话保持:
为当前server指定cookie值,实现基于cookie的会话黏性,相对于基于source地址hash调度算法对客户端的粒度更精准,但同时也加大了haproxy负载,目前此模式使用较少, 已经被session共享服务器代替
仅支持http
配置:
cookie name [ rewrite | insert | prefix ][ indirect ] [ nocache ][ postonly ] [ preserve ][ httponly ] [ secure ][ domain ]* [ maxidle <idle> ][ maxlife ]
选项:
name cookie的key名称,用于实现持久连接
inster 把name当新cookie键插入,默认不插入cookie
indirect 如果客户端已有cookie,则不会再发送cookie信息
nocache 当client和haproxy之间有缓存服务器,如CDN时,不允许中间缓存服务器缓存cookie,因为这会导致很多经过同一个CDN的请求到发送到同一台后端服务器
例:
#haproxy配置
listen web
balance roudrobin
mode http
cookie sessionid insert nocache indirect
server web1 1.1.1.10:80 weight 1 check cookie host1
server web2 1.1.1.20:80 weight 1 check cookie host2
#测试访问
curl -b "sessionid=host1" 2.2.2.25 #curl默认不使用cookie,所以要指定
haproxy状态页:
web界面显示运行状态
官方文档:http://cbonte.github.io/haproxy-dconv/2.0/configuration.html#4-stats admin
状态页配置项:
stats enable 基于默认的参数启用stats page
stats hide-version 将状态页中haproxy版本隐藏
stats refresh <delay> 设定自动刷新时间间隔,默认不自动刷新
stats uri <prefix> 自定义访问路径,默认值:/haproxy?stats
stats realm <realm> 账户认证时的提示信息,示例:stats realm HAProxy\ Statistics
stats auth <user>:<passwd> 认证时的账号和密码,可定义多个用户,每行指定一个用户.默认:no
authentication
stats admin { if | unless } <cond> 允许用户有管理功能
例1: 启用状态页
listen stats
bind 1.1.1.25:1000
mode http
stats enable
stats uri /ha-status
stats realm haproxy stats page #提示信息有的浏览器不呢个正常显示
stats auth admin:123456
stats auth user1:123456
stats admin if true #生产环境酌情
stats refresh 3
curl -I http://admin:123456@1.1.1.25:1000/ha-status
状态页信息:
pid = 27134 (process #1, nbproc = 1, nbthread = 1) #pid为当前pid号,process为当前进程号,nbproc和nbthread为一共多少进程和每个进程多少个线程
uptime = 0d 0h00m04s #启动了多长时间
system limits: memmax = unlimited; ulimit-n = 200029 #系统资源限制:内存/最大打开文件
数/
maxsock = 200029; maxconn = 100000; maxpipes = 0 #最大socket连接数/单进程最大连接数/
最大管道数maxpipes
current conns = 2; current pipes = 0/0; conn rate = 2/sec; bit rate = 0.000 kbps
#当前连接数/当前管道数/当前连接速率
Running tasks: 1/14; idle = 100 % #运行的任务/当前空闲率
active UP: #在线服务器
backup UP: #标记为backup的服务器
active UP, going down: #监测未通过正在进入down过程
backup UP, going down: #备份服务器正在进入down过程
active DOWN, going up: #down的服务器正在进入up过程
backend显示的详细信息
session rate(每秒的连接会话信息)
cur | 每秒的当前会话数量 |
max | 每秒新的最大会话数量 |
limit | 每秒新的会话限制量 |
sessions(会话信息)
cur | 当前会话量 |
max | 最大会话量 |
limit | 限制会话量 |
Total | 总共会话量 |
LBTot | 选中一台服务器所用的总时间 |
Last | 和服务器的持续连接时间 |
Bytes(流量统计)
In | 网络的字节输入总量 |
Out | 网络的字节输出总量 |
Denied(拒绝统计信息)
Req | 拒绝请求量 |
Resp | 拒绝回复量 |
Errors(错误统计信息)
Req | 错误请求量 |
conn | 错误链接量 |
Resp | 错误响应量 |
Warnings(警告统计信息)
Retr | 重新尝试次数 |
Redis | 再次发送次数 |
Server(real server信息)
Status | 后端机的状态,包括UP和DOWN |
LastChk | 持续检查后端服务器的时间 |
Wght | 权重 |
Act | 活动链接数量 |
Bck | 备份的服务器数量 |
Chk | 心跳检测时间 |
Dwn | 后端服务器连接后都是DOWN的数量 |
Dwntme | 总的downtime时间 |
Thrtle | server 状态 |
IP透传:
记录真实客户端ip,用于做访问统计、安全防护、行为分析、区域排行等
透传方式有两种:
- 4层:tcp协议转发,伪4转发(与lvs不一样)
- 7层:http协议+内容交换(客户端到后端的报文,必须由haproxy构建,于nginx代理一样)
- client-->haproxy-->server-->haproxy-->client
四层透传:
- 在四层负载设备中,传统的是把client发送的报文目标地址(原来是负载均衡设备的IP地址),根据均衡设备设置的选择web服务器的规则选择对应的web服务器IP地址,这样client就可以直接跟此服务器建立TCP连接并发送数据,而四层负载自身不参与建立连接
- 而和LVS不同,haproxy是伪四层负载均衡,因为haproxy需要分别和前端客户端及后端服务器建立连接
属于异构模型:client到haproxy的协议是http,haproxy到server的是proxy_protocol协议
利用server指令的send-proxy选项,开启四层ip透传功能。较少使用4层
4层ip透传配置
haproxy设置
listen web
bind 2.2.2.25:80
mode tcp
balance roudrobin
server web1 www.hj.com:80 check inter 3000 fall 2 rise 5 send-proxy
nginx设置:
#在访问日志中通过变量$proxy_protocol_addr 记录透传过来的客户端IP
http {
log_format main '... ...
"$proxy_protocol_addr"'
server {
listen 80 proxy_protocol; #启用此项,将无法直接访问此网站,只能通过四层代理
访问
}
}
tail -f /var/log/nginx/access.log
七层:
- 七层负载均衡服务器起了一个反向代理服务器的作用,服务器建立一次TCP连接要三次握手,而client要访问Web Server要先与七层负载设备进行三次握手后建立TCP连接,把要访问的报文信息发送给七层负载均衡;然后七层负载均衡再根据设置的均衡规则选择特定的 Web Server,然后通过三次握手与此台Web Server建立TCP连接,然后Web Server把需要的数据发送给七层负载均衡设备,负载均衡设备再把数据发送给client;所以,七层负载均衡设备起到了代理服务器的作用,七层代理需要和Client和后端服务器分别建立连接
client到haproxy到server是同一种协议:http
在haproxy发往后端主机的请求报文中添加“X-Forwarded-For"首部,其值为前端客户端的地址;用于向后端主发送真实的客户端IP
配置说明:
option forwardfor指令实现7层ip透传,较多使用
option forwardfor [except <network>] [header <name>] [if-none]
except <network> 请求报请来自此处指定的网络时不予添加此首部,如haproxy自身所在网络
header <name> 使用自定义的首部名称,不指定时默认为“X-Forwarded-For",可换成如:X-client
if-none 如果没有首部才添加首部,如果有使用默认值
7层ip透传
haproxy配置:
defaults
option forwardfor
listen web
bind 2.2.2.25:80
mode http
server web1 1.1.1.10:80 weight 1 check inter 3000 fall 2 rise 5
server web2 1.1.1.20:80 weight 1 check inter 3000 fall 2 rise 5
nginx配置:
#使用$proxy_add_x_forwarded_for或http_x_forwarded_for变量
log_format main '"$proxy_add_x_forwarded_for"' ...;
自定义首部名称
haproxy配置:
defaults
option forwardfor except 1.0.0.0/8 header X-clientip
nginx配置:
使用变量:$http_首部字段,即可记录到日志,大小写不敏感
vim nginx.conf
http {
log_format main '"$http_x_clientip"' ...;
}
修改报文:
在http模式下,基于实际需求修改客户端的请求报文与响应报文
reqadd、reqdel指令在请求报文添加删除字段。代理的第二步
rspadd、rspidel指令在响应报文中添加与删除字段。代理的第四步
与nginx的原理一样,修改2、4步的报文
支持正则表达式
代理步骤:
- 第一步: client与代理建立连接,client请求代理
- 第二步: 代理与后端rs建立连接,代理请求rs
- 第三步: 后端rs响应代理
- 第四步: 代理响应client
注意:
- 此功能的以下相关指令在2.1版本中已经取消
2.0版本的指令使用:
官方文档:http://cbonte.github.io/haproxy-dconv/2.0/configuration.html#4-rspadd
第二步修改:haproxy-->server的请求报文
reqadd 字段名 值 向后端的请求头添加字段,值有空格时必须转义,且只能有一个
例:
reqadd X-via:\ haproxy
reqdel 字段名 向后端的请求报文中删除字段
reqidel 字段名 同上,但忽略大小写
例:
reqidel user-agent
第四步修改:haproxy-->client的响应报文
rspadd 字段名 值 响应报文中添加字段
例:
rspadd X-via:\ haproxy
rspadd Server:\ 123456
rspdel 字段名 值 响应报文删除字段
rspidel 字段名 值 同上,但忽略大小写
例:
rspidel ^server:.* 从响应报文删除server信息
rspidel X-Powerd-By:.* 从响应报文删除X-Powered-By信息,一般此首部字段保存php版本信息
例: 添加某指定字段,并在nginx记录
vim haproxy.cfg
frontend web *:80
bind *:80
reqadd X-via:\ haproxy-server
reqidel user-agent
rspidel server
vim nginx.conf
log_format main "$http_x_via" ...
2.1以上版本的指令使用:
改用为: http-request、http-response指令代替
官方文档:
- http://cbonte.github.io/haproxy-dconv/2.1/configuration.html#4-http-request
- http://cbonte.github.io/haproxy-dconv/2.1/configuration.html#4-http-response
http-request 选项 [ { if | unless } <condition> ]
选项:
add-header 字段名 值
del-header 字段名 值
deny 拒绝请求
例:
http-request add-header X-Haproxy-Current-Date %T
http-response 选项 [ { if | unless } <condition> ]
选项:
add-header 字段名 值
del-header 字段名 值
例:
http-response del-header Server
自定义日志格式:
log global 开启日志功能,默认只会在记录普通格式的日志
option httplog 指令把http格式记录下来,并且可以使用相关指令将特定信息记录在haproxy的日志中,但一般不建议开启,这会加重HAProxy负载
配置参数
log global 开启日志记录,默认不开启
option httplog 开机记录http的日志格式
capture 选项
选项:
cookie name len 长度 捕获请求和响应报文中的cookie以及值的长度,并记录到日志
request header name len 长度 捕获请求报文中的指定首部内容和长度,并记录到日志
response header name len 长度记录响应保温中的指定内容和长度,并记录到日志
例:
listen web
log global
option httplog
capture request header Host len 256
capture request header User-Agent len 512
capture request header Referer len 15
capture request header X-Forwarded-For len 15
压缩功能:
与nginx一样,支持数据压缩传输
对响应给客户端的报文进行压缩,以节省网络带宽,但是会占用部分CPU性能
建议在后端服务器开启压缩功能,而非在HAProxy上开启压缩
配置参数
compression 选项
选项:
algo 算法 启用http协议中的压缩机制、使用算法
identify debug调试时使用的压缩方式
gzip 常用的压缩算法,各浏览器兼容
deflate 常用,但有些浏览器不支持
raw-deflate 新出的压缩方式
type 类型 哪些文件需要压缩
text/html
text/css
text/plain
例:
listen web
compression algo gzip deflate
compression type text/html text/css text/plain
web服务器状态监测:
3种检测方式:
- 基于四层的传输端口做状态监测,此为默认方式
- 基于指定URI做状态监测,需要访问整个页面资源,占用更多带宽
- 基于指定URI的request请求头部内容做状态监测,占用较少带宽,建议使用此方式
配置参数:
option httpchk [method] uri [version]
例:
option httpchk HEAD /health.html HTTP/1.0
option httpchk HEAD /health.html HTTP/1.1\r\nHost:\ www.hj.com http1.1协议必须添加Hots头,否则服务启动失败
http-check expect [!] <match> <pattern> 检查时返回的响应码,匹配为健康,否则为失败。支持正则表达式
例:
http-check expect ! rstatus ^5
http-check expect status 200
http协议的检测:
注意:
- 此方式会导致在后端服务器生成很多的HAProxy发起的访问日志建议在后端server设置一个专门检测的页面,并关闭专门页面的访问日志记录
例: 通过访问指定uri,返回状态码
vim haproxy.cfg
listen web
option httpchk HEAD /health.html HTTP/1.0
http-check expect status 200
server web1 1.1.1.10:80 check inter 3000 fall 2 rise 5
server web2 1.1.1.20:80 check inter 3000 fall 2 rise 5
vim nginx.conf #nginx关闭日志记录
server {
location /health.html {
log_not_found off;
access_log off;
}
}
echo ok > /opt/web/health.html