前言
前面章节我们完成了 HAProxy 基础安装、socat 热运维、负载均衡调度算法配置,本章聚焦生产环境高频必备三大高级功能:
- Cookie 基于 Cookie 精准会话保持:粒度优于源 IP 哈希,解决会话粘滞需求
- Web 状态监控页面:可视化查看集群运行、节点健康、流量连接统计
- 四层 / 七层真实客户端 IP 透传:后端 Web 服务器获取真实访客 IP,用于日志统计、安全风控、访问分析
实验环境沿用前文架构
- HAProxy 调度器:eth0
172.25.254.100,eth1192.168.0.100- RS1:
192.168.0.10,RS2:192.168.0.20- 客户端测试机:
172.25.254.99
一、基于 Cookie 的会话保持(七层 HTTP 专用)
1.1 原理说明
cookie会话黏性是 HAProxy 七层模式专属会话保持方案,粒度比source源IP哈希更精准: HAProxy 给不同后端服务器分配唯一 Cookie 标识,首次访问插入 Set-Cookie;后续客户端携带 Cookie 访问时,直接固定调度至对应后端节点。
- 限制:仅支持
mode http七层模式,TCP 四层模式无法使用 - 对比:源 IP 哈希会存在局域网多用户同 IP 绑定同一节点弊端,Cookie 基于浏览器标识,用户粒度隔离更精细
- 现状:大规模集群更多采用后端
Session共享替代会话保持,但小集群、老旧业务仍广泛使用 Cookie 黏滞
1.2 cookie 完整配置参数解析
cookie name [ rewrite | insert | prefix ][ indirect ] [ nocache ][ postonly ] [ preserve ][ httponly ] [ secure ][ domain ]* [ maxidle <idle> ][ maxlife ]| 参数 | 作用解释 |
|---|---|
| name | Cookie 键名,自定义名称,用于识别会话 |
| insert | 客户端首次访问时,自动向响应头插入 Set-Cookie 写入节点标识 |
| indirect | 客户端已有 Cookie 时,HAProxy 不再重复下发 Set-Cookie,减少头部冗余 |
| nocache | 防止 CDN、反向代理缓存 Cookie,避免大量客户端被固定分发同一后端 |
| rewrite/prefix | 重写 Cookie / 前缀式 Cookie(两种进阶模式,insert 最常用) |
| httponly/secure | 安全属性,防止 JS 窃取 Cookie、仅 HTTPS 传输 |
1.3 完整配置示例
修改 HAProxy 配置/etc/haproxy/haproxy.cfg,新增 cookie 会话保持:
listen webserver-cluster-80 bind 172.25.254.100:80 balance roundrobin mode http option forwardfor # 定义Cookie配置:键名WEBCOOKIE,插入模式、防缓存、已有cookie不再重复下发 cookie WEBCOOKIE insert nocache indirect # 给两台后端分别设置唯一cookie标识 web1 / web2 server webserver1 192.168.0.10:80 cookie web1 check inter 3s fall 3 rise 5 weight 1 server webserver2 192.168.0.20:80 cookie web2 check inter 3s fall 3 rise 5 weight 1校验配置语法并重启生效:
haproxy -c -f /etc/haproxy/haproxy.cfg systemctl restart haproxy1.4 效果验证
1. 首次访问自动下发 Set-Cookie
[root@client ~]# curl -i 172.25.254.100 HTTP/1.1 200 OK date: Mon, 16 Mar 2026 11:15:37 GMT server: Apache/2.4.57 (Red Hat Enterprise Linux) last-modified: Thu, 29 Jan 2026 03:27:51 GMT etag: "18-6497e710faf2b" accept-ranges: bytes content-length: 24 content-type: text/html; charset=UTF-8 set-cookie: WEBCOOKIE=web1; path=/ cache-control: private webserver1-192.168.0.10响应头自动携带Set-Cookie: WEBCOOKIE=web1,代表本次绑定 webserver1 节点。
2. 携带 Cookie 固定访问对应后端
# 携带web2标识,永远访问RS2 [root@client ~]# curl -b WEBCOOKIE=web2 172.25.254.100 Webserver2-192.168.0.20 [root@client ~]# curl -b WEBCOOKIE=web2 172.25.254.100 Webserver2-192.168.0.20 # 携带web1标识,永远访问RS1 [root@client ~]# curl -b WEBCOOKIE=web1 172.25.254.100 webserver1-192.168.0.10 [root@client ~]# curl -b WEBCOOKIE=web1 172.25.254.100 webserver1-192.168.0.10会话黏滞生效,同一个 Cookie 请求始终调度至绑定服务器。
二、HAProxy Web 状态监控页面(运维可视化必备)
2.1 功能介绍
HAProxy 内置 Web 可视化状态页,无需额外部署监控组件,浏览器即可访问查看:
- 进程运行时长、CPU / 连接上限、当前并发连接、吞吐速率
- 后端节点健康状态(UP/DOWN/ 维护下线 / 故障检测中)
- 总会话量、每秒会话速率、流量进出、错误统计、拒绝请求统计
- 支持账号密码登录鉴权,支持在线手动上下线后端节点(管理权限)
2.2 状态页核心配置参数
| 配置指令 | 功能说明 |
|---|---|
| stats enable | 开启状态页面总开关 |
| stats uri /status | 自定义访问路径,默认访问地址/haproxy?stats |
| stats hide-version | 隐藏 HAProxy 版本号,规避安全扫描漏洞暴露 |
| stats refresh 5s | 页面自动刷新间隔 5 秒,默认关闭自动刷新 |
| stats auth user:pass | 登录账号密码,可多行配置多组管理员账号 |
| stats admin if TRUE | 开启页面管理权限,支持页面上下线后端服务器 |
2.3 独立状态页配置(推荐配置)
在配置文件末尾新增独立listen段,单独监听 8888 端口做监控入口,不与业务端口混杂:
listen stats mode http bind 0.0.0.0:8888 stats enable log global stats uri /status stats hide-version stats refresh 5s stats auth dragon:dragon stats admin if TRUE重载配置并放行防火墙端口:
haproxy -c -f /etc/haproxy/haproxy.cfg systemctl restart haproxy # 放行8888端口 firewall-cmd --add-port=8888/tcp --permanent firewall-cmd --reload2.4 浏览器访问方式
访问地址:http://172.25.254.100:8888/status弹窗输入账号:dragon,密码:dragon即可进入监控面板。
2.5 页面关键字段释义
全局运行信息
pid = 27134 (process #1, nbproc = 1, nbthread = 1) uptime = 0d 0h00m04s system limits: memmax = unlimited; ulimit-n = 200029 maxsock = 200029; maxconn = 100000; maxpipes = 0 current conns = 2; conn rate = 2/sec- pid:进程 ID、进程 / 线程数量
- uptime:服务运行时长
- current conns:当前活跃总连接数
后端节点状态分类
| 状态标识 | 含义 |
|---|---|
| active UP | 节点健康在线,正常承接流量 |
| active DOWN, going up | 故障节点检测恢复中 |
| active or backup DOWN | 节点健康检查失败,已下线 |
| MAINT | 管理员手动维护下线 |
| SOFT STOPPED | 权重置 0 软下线,不再接收新连接 |
流量与会话统计
sessions cur/max/total:当前会话、峰值会话、总请求量In/Out Bytes:入站、出站总流量Errors Req/Conn/Resp:请求错误、连接错误、响应错误统计
三、四层 TCP & 七层 HTTP 真实客户端 IP 透传
业务背景
HAProxy 作为反向代理,后端 Web 服务器默认只能获取 HAProxy 内网 IP,无法拿到真实访客 IP;无法完成访问日志统计、IP 黑名单拦截、地域分析、风控限流等业务。 HAProxy 提供两套方案实现 IP 透传:
- 七层 HTTP 模式:X-Forwarded-For 请求头透传(最常用)
- 四层 TCP 模式:Proxy Protocol 代理协议透传
3.1 四层 TCP 模式:Proxy Protocol(send-proxy)IP 透传
1、HAProxy 四层配置
mode tcp场景,后端服务器开启proxy_protocol协议接收原始客户端 IP:
listen webserver-cluster-80 bind 172.25.254.100:80 balance roundrobin mode tcp # send-proxy 开启代理协议,向前端传递原始五元组信息 server webserver1 192.168.0.10:80 send-proxy check inter 3s fall 3 rise 5 weight 1 server webserver2 192.168.0.20:80 send-proxy check inter 3s fall 3 rise 5 weight 1校验重启服务:
haproxy -c -f /etc/haproxy/haproxy.cfg systemctl restart haproxy2、后端 Nginx 配置接收 Proxy Protocol
RS2(192.168.0.20)开启代理协议监听,日志打印真实 IP
http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '"$proxy_protocol_addr"' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; server { listen 80 proxy_protocol; listen [::]:80 proxy_protocol; server_name _; root /usr/share/nginx/html; } }重载 Nginx:systemctl reload nginx
RS1(192.168.0.10)不开启 Proxy Protocol 作为对比
默认日志只能看到 HAProxy 内网地址:
http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; }3、访问测试 & 日志对比
客户端批量访问:
[root@client ~]# for i in {1..10};do curl 172.25.254.100;done- RS1 日志(未开启 Proxy Protocol)
192.168.0.100 - - [16/Mar/2026:20:51:08 +0800] "GET / HTTP/1.1" 200 18 "-" "curl/7.76.1" "-"只能看到 HAProxy 内网 IP192.168.0.100
- RS2 日志(开启 Proxy Protocol 成功获取真实 IP)
192.168.0.100 - - [16/Mar/2026:20:51:08 +0800] "GET / HTTP/1.1" "172.25.254.99"200 18 "-" "curl/7.76.1" "-"成功打印客户端真实源 IP172.25.254.99
3.2 七层 HTTP 模式:X-Forwarded-For 头部透传(生产主流)
原理
option forwardfor指令让 HAProxy 在转发 HTTP 请求时,自动新增X-Forwarded-For请求头,填入客户端真实 IP;后端 Apache/Nginx 修改日志格式读取该头部,记录真实访客地址。
1、HAProxy 全局配置 forwardfor
推荐在defaults段全局开启,所有后端代理自动生效:
defaults mode http log global option httplog option dontlognull option http-server-close # 排除本地回环网段,不对自身IP插入头部 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 listen webserver-cluster-80 bind 172.25.254.100:80 balance roundrobin mode http option forwardfor server webserver1 192.168.0.10:80 check inter 3s fall 3 rise 5 weight 1 server webserver2 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1重启 HAProxy 生效。
2、后端 Apache httpd 日志配置读取 X-Forwarded-For
RS1(开启读取 XFF 头部)
编辑/etc/httpd/conf/httpd.conf,修改日志格式行:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{X-Forwarded-For}i\" \"%{Referer}i\" \"%{User-Agent}i\"" combined重启 httpd:systemctl restart httpd
RS2(默认原生日志,不读取 XFF)
保持默认日志格式:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined3、后端 Nginx 日志配置读取 X-Forwarded-For
http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; }4、访问日志验证
客户端循环访问后查看:
- RS1 httpd 日志(成功获取真实 IP)
192.168.0.100 - - [16/Mar/2026:21:21:17 +0800] "GET / HTTP/1.1" 200 24 "172.25.254.99" "-" "curl/7.76.1"- RS2 httpd 日志(仅看到代理 IP)
192.168.0.100 - - [16/Mar/2026:21:23:38 +0800] "GET / HTTP/1.1" 200 24 "-" "curl/7.76.1"3.3 两种透传方案选型总结
| 方案 | 适用模式 | 优点 | 缺点 |
|---|---|---|---|
| X-Forwarded-For | 仅七层 HTTP | 配置简单、兼容性极强,主流方案 | 四层 TCP 无法使用 |
| Proxy Protocol(send-proxy) | 四层 TCP / 七层 HTTP 通用 | 四层场景唯一透传方案,协议标准化 | 前后端必须成对开启配置,配置繁琐 |