haproxy的七层代理

发布于:2025-07-25 ⋅ 阅读:(14) ⋅ 点赞:(0)

一、实验环境

IP设置:

主机名 IP地址 网关 网络适配器 角色
client 172.25.254.111/24 172.25.254.2 NAT模式 客户机
haproxy 172.25.254.100/24 172.25.254.2 NAT模式 负载均衡器
RS1 172.25.254.10/24 172.25.254.2 NAT模式 后端服务器1
RS2 172.25.254.20/24 172.25.254.2 NAT模式 后端服务器2

负载均衡器设置:

在负载均衡器上安装 haproxy 软件

查看 haproxy 的版本

后端服务器设置:

在两台后端服务器上安装 nginx 服务器

然后往nginx的默认发布目录中写入内容

防火墙设置:

将两台后端服务器的防火墙关闭

测试网络连通性:

在每台主机上都互相进行ping测试,如果能互通就行。

并且在负载均衡器上访问两台后端服务器中默认发布文件的内容看是否能访问的到,能就行。

二、HAProxy的基本配置信息

1、haproxy软件基本信息

软件安装包: haproxy-2.4.22-3.el9_3.x86_64.rpm

启动文件: /lib/systemd/system/haproxy.service

主配置目录: /etc/haproxy/

主配置文件: /etc/haproxy/haproxy.cfg

子配置目录: /etc/haproxy/conf.d

!!!注意:每次修改完配置文件都要重新启动haproxy服务!!!

HAProxy 的配置文件haproxy.cfg由两大部分组成,分别是:

global:全局配置段

  • 进程及安全配置相关的参数

  • 性能调整相关参数

  • Debug参数

proxies:代理配置段

  • defaults:为frontend, backend, listen提供默认配置

  • frontend:前端,相当于nginx中的server {}

  • backend:后端,相当于nginx中的upstream {}

  • listen:同时拥有前端和后端配置,配置简单,生产推荐使用

2、global 配置

下图为global配置中各种参数的说明:

在 HAProxy 配置中,stats socket 指令用于创建一个 Unix 域套接字(Unix Socket),供管理员通过命令行工具(如 socat 或 haproxyctl)与 HAProxy 进程交互(如查看状态、动态调整配置等)。

指定套接字文件中各参数的含义如下:

1. /var/lib/haproxy/haproxy.sock2

  • 套接字文件的路径和名称。

  • 当 HAProxy 启动后,会在该路径下创建一个名为 haproxy.sock2 的文件,作为与进程通信的接口。

  • 若配置了多个进程(通过 nbproc 指定),通常会为每个进程分配一个独立的套接字文件(如 sock1sock2),避免混淆。

2. mode 600

  • 设置套接字文件的权限(Unix 文件权限格式)。

  • 600 表示:仅文件所有者(root 或启动 HAProxy 的用户)拥有读写权限,其他用户无任何权限。

  • 作用:限制对套接字的访问,防止未授权用户通过套接字操作 HAProxy(如修改配置、查看敏感信息)。

3. level admin

  • 指定通过该套接字可执行的操作权限级别。

  • level admin 表示管理员权限,允许执行所有支持的命令(如 show stats 查看状态、set weight 调整服务器权重、disable server 下线服务器等)。

  • 其他可选级别:level user(仅允许查看状态,无修改权限),但实际中常用 admin 以满足管理需求。

4. process 2

  • 指定该套接字绑定到 HAProxy 的第几个进程(进程编号从 0 或 1 开始,取决于版本,通常从 1 开始)。

  • 仅在多进程模式nbproc > 1)下有效。例如,若 nbproc 4 启动了 4 个进程,process 2 表示该套接字仅与第 2 个进程通信。

  • 作用:在多进程场景中,通过不同套接字文件分别管理每个进程(如单独查看某个进程的连接数、调整其负载均衡策略)。

2.1 多进程

上图 global 配置中已经启用了多进程,下图我们直接重启查看多进程信息就行了。

命令:[root@haproxy 桌面]# pstree -p | grep haproxy

2.2 多线程

命令:[root@haproxy 桌面]# cat /proc/xxxx(haproxy子进程id)/status

利用查看完多线程信息的haproxy子进程的pid来查看对应的haproxy子进程的线程状态。 

可以看到 Threads:1 这个代表该haproxy子进程仅包含 1 个线程(即主线程)的信息。

下图为启用多线程功能。

然后查看haproxy的进程状态,可以发现 Threads:2 这个信息。

3、proxies 配置

整个HAProxy的完整配置示例(包含默认配置、前后端配置和listen块配置,即有下面3.1 proxies 参数说明中的参数的示例配置)

# 全局配置
global
    log /dev/log local0  # 日志配置
    log /dev/log local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
    stats timeout 30s
    user haproxy
    group haproxy
    daemon

# 默认可用配置
defaults
    log global
    mode http  # 默认模式为HTTP
    option httplog
    option dontlognull
    timeout connect 5000ms  # 连接超时
    timeout client 50000ms  # 客户端超时
    timeout server 50000ms  # 服务器超时

# 前端配置:处理HTTP/HTTPS请求
frontend http_frontend
    bind *:80  # 监听80端口(HTTP)
    bind *:443 ssl crt /etc/haproxy/certs.pem  # 监听443端口(HTTPS)
    
    # 访问控制:允许特定IP段,拒绝其他
    acl allowed_ips src 192.168.1.0/24 10.0.0.0/16
    http-request deny unless allowed_ips
    
    # 基于域名的路由规则
    acl is_api hdr(host) -i api.example.com  # 匹配API域名
    acl is_web hdr(host) -i www.example.com  # 匹配网站域名
    
    # 基于路径的路由规则
    acl is_static path_beg /static /images  # 匹配静态资源路径
    acl is_health path_beg /health  # 匹配健康检查路径
    
    # 转发规则:根据条件选择后端
    use_backend api_servers if is_api
    use_backend static_servers if is_static
    use_backend health_check if is_health
    default_backend web_servers  # 默认后端

# 后端配置:API服务器集群
backend api_servers
    mode http
    balance leastconn  # 最少连接数算法(适合长连接服务)
    option httpchk GET /api/health  # HTTP健康检查路径
    
    # 会话保持:基于客户端IP哈希
    stick-table type ip size 10k expire 30m
    stick on src
    
    # 后端服务器列表
    server api1 192.168.1.10:8080 check inter 2s rise 2 fall 3
    server api2 192.168.1.11:8080 check inter 2s rise 2 fall 3
    server api3 192.168.1.12:8080 check inter 2s rise 2 fall 3 backup

# 后端配置:静态资源服务器集群
backend static_servers
    mode http
    balance roundrobin  # 轮询算法(适合无状态服务)
    option httpchk HEAD /static/index.html  # HTTP健康检查
    
    # 服务器权重配置(server2性能更强,权重更高)
    server static1 192.168.1.20:80 check weight 1
    server static2 192.168.1.21:80 check weight 2

# 后端配置:网站服务器集群
backend web_servers
    mode http
    balance uri  # URI哈希算法(相同URI请求到同一服务器,利于缓存)
    
    # 启用HTTP压缩
    compression algo gzip
    compression type text/html text/css application/javascript
    
    # 服务器列表
    server web1 192.168.1.30:80 check
    server web2 192.168.1.31:80 check

# 后端配置:健康检查专用
backend health_check
    mode http
    server health 127.0.0.1:8081 check  # 本地健康检查服务

# listen 块配置:HAProxy 统计页面
listen stats
    bind *:8080  # 监听8080端口
    mode http
    stats enable
    stats uri /haproxy_stats  # 统计页面URL
    stats auth admin:password  # 认证信息(用户名:密码)
    stats refresh 30s  # 自动刷新时间

# listen 块配置:数据库负载均衡(示例)
listen db_cluster
    bind *:3306  # 监听MySQL端口
    mode tcp
    balance leastconn  # 最少连接数算法
    option mysql-check user haproxy_check  # MySQL健康检查用户
    server db1 192.168.1.40:3306 check inter 2s rise 2 fall 3
    server db2 192.168.1.41:3306 check inter 2s rise 2 fall 3 backup

3.1 proxies 参数说明

参数
类型 作用
defaults
proxies
默认配置项,针对以下的 frontend backend listen 生效,可以多个
name 也可以没有 name
frontend
proxies
前端 servername ,类似于 Nginx 的一个虚拟主机 server LVS 服务集
群。
backend
proxies
后端服务器组,等于 nginx upstream LVS 中的 RS 服务器
listen
proxies
frontend backend 合并在一起配置,相对于 frontend backend
配置更简洁,生产常用

补充:name字段只能使用大小写字母,数字,‘-’(dash),'_‘(underscore),'.' (dot)和 ':'(colon),并且严格区分大小写。

下图为做实验时的配置,值得注意的时frontend/backend组合和listen块都在监听80端口,因为同一个端口不能被重复监听,所以会导致配置文件出错,这时侯就需要我们注释掉或者删除掉其中一个组合。

3.2 Proxies配置-defaults

常用 defaults 配置项(代理相关)

以下是 defaults 中与代理功能密切相关的核心配置项:

1. 模式(代理类型)
  • mode { tcp | http | health }
    定义默认的代理模式,决定 HAProxy 如何处理流量:

    • tcp:四层(TCP)代理,基于端口转发,不解析应用层协议(如 HTTP),适用于 SSH、数据库等非 HTTP 服务。

    • http:七层(HTTP/HTTPS)代理,可解析 HTTP 协议,支持 URL 路由、Header 改写、Cookie 会话保持等高级功能。

    • health:健康检查专用模式,较少直接使用。

    示例:

    defaults
      mode http  # 默认使用 HTTP 代理模式
    
2. 超时设置(关键!避免连接挂死)
  • timeout connect <时间>
    客户端请求转发到后端服务器的连接超时时间(从 HAProxy 发起连接到后端服务器响应的最长等待时间)。
    示例:timeout connect 5s(5 秒内未连接成功则视为后端不可用)。

  • timeout client <时间>
    客户端与 HAProxy 之间的空闲超时时间(若客户端超过此时长未发送数据,HAProxy 断开连接)。
    示例:timeout client 30s(客户端 30 秒无活动则断开)。

  • timeout server <时间>
    HAProxy 与后端服务器之间的空闲超时时间(若后端服务器超过此时长未响应,HAProxy 断开连接)。
    示例:timeout server 30s(后端 30 秒无活动则断开)。

  • timeout http-request <时间>
    仅 http 模式有效,等待客户端发送完整 HTTP 请求的超时时间(防止恶意客户端缓慢发送请求)。
    示例:timeout http-request 10s

  • timeout http-keep-alive <时间>
    仅 http 模式有效,HTTP 长连接(Keep-Alive)的超时时间。
    示例:timeout http-keep-alive 15s

3. 负载均衡与调度
  • balance { roundrobin | leastconn | source | uri | url_param ... }
    定义默认的负载均衡算法(适用于 backend 或 listen 中的后端服务器组):

    • roundrobin:轮询(默认),按顺序分发请求到后端服务器。

    • leastconn:最少连接数,优先转发到当前连接数最少的服务器(适合长连接服务,如数据库)。

    • source:基于客户端 IP 哈希,同一客户端请求始终转发到同一后端服务器(会话保持)。

    • uri:基于请求的 URI 哈希(如 /path),适合静态资源缓存场景。

    示例:

    defaults
      balance leastconn  # 默认使用最少连接数算法
    
4. 日志与监控
  • log <address> <facility> [level]
    定义默认的日志输出配置,global 中需先配置日志服务器(如 log 127.0.0.1 local0),此处继承或补充。
    示例:log global(继承 global 中的日志配置)。

  • option httplog
    仅 http 模式有效,启用 HTTP 日志记录,包含请求方法、URL、状态码、Header 等详细信息(默认仅记录基本 TCP 日志)。

  • option dontlognull
    不记录空连接(如客户端连接后立即断开的无效请求),减少日志冗余。

5. 健康检查
  • option httpchk <method> <uri> <version>
    仅 http 模式有效,定义 HTTP 健康检查规则(后端服务器需响应指定请求才视为 “健康”)。
    示例:option httpchk GET /health HTTP/1.1\r\nHost: localhost(检查后端 /health 路径的响应)。

  • default-server [参数]
    定义后端服务器的默认属性,如健康检查间隔、最大失败次数等,简化 backend 中 server 指令的配置。
    示例:

    defaults
      default-server inter 3s fall 3 rise 2  # 每 3 秒检查一次,连续 3 次失败标记为下线,2 次成功恢复上线
    
6. 错误处理
  • errorfile <状态码> <文件路径>
    自定义 HTTP 错误页面(如 404、503 等),需提前准备静态 HTML 文件。
    示例:

    defaults
      errorfile 503 /etc/haproxy/errors/503.html  # 503 错误时返回自定义页面
    
  • retries <次数>
    当后端服务器连接失败时,重试的次数(避免临时网络波动导致的失败)。
    示例:retries 3(最多重试 3 次)。

7. 其他常用选项
  • option forwardfor [except <ip>]
    仅 http 模式有效,向后端服务器添加 X-Forwarded-For Header,记录真实客户端 IP(否则后端看到的是 HAProxy 的 IP)。
    示例:option forwardfor

  • maxconn <数量>
    定义默认的最大并发连接数(全局或单个前端 / 后端的限制),防止过载。
    示例:maxconn 10000(默认最大并发 10000 连接)。

完整 defaults 示例(代理场景)

  • defaults 段的继承​​:若在 defaults 全局默认配置中定义了 balance 算法,而 frontend 未显式覆盖此配置,则 frontend 会继承 defaults 中的算法设置。

defaults
    mode http  # 默认 HTTP 模式
    log global  # 继承 global 中的日志配置
    option httplog  # 记录详细 HTTP 日志
    option dontlognull  # 不记录空连接
    option forwardfor  # 传递客户端真实 IP 到后端
    timeout connect 5s  # 连接后端超时 5 秒
    timeout client 30s  # 客户端空闲超时 30 秒
    timeout server 30s  # 后端服务器空闲超时 30 秒
    timeout http-request 10s  # 等待 HTTP 请求超时 10 秒
    balance leastconn  # 默认最少连接数负载均衡
    retries 3  # 连接失败重试 3 次
    default-server inter 3s fall 3 rise 2  # 后端服务器健康检查配置

3.3 Proxies配置-frontend

frontend 的核心配置项及其用法:

基本语法
frontend <名称>
    bind <IP:端口> [参数]  # 监听地址和端口
    mode { tcp | http | health }  # 代理模式
    [其他配置...]
    use_backend <后端名称> [如果条件]  # 请求转发规则
核心配置项
1. 监听地址与端口
  • bind <IP:端口> [参数]
    指定监听的 IP 地址和端口,可配置多个 bind。支持的参数包括:

    • ssl crt <证书路径>:启用 HTTPS(需指定证书文件)。

    • accept-proxy:接收 PROXY 协议(用于传递客户端真实 IP)。

    • maxconn <数量>:限制此监听的最大并发连接数。

    示例

    bind *:80  # 监听所有 IP 的 80 端口(HTTP)
    bind *:443 ssl crt /etc/haproxy/certs.pem  # 监听 443 端口(HTTPS)
    
2. 代理模式
  • mode { tcp | http | health }
    定义处理请求的模式:

    • tcp:四层代理,直接转发 TCP 流量(如 SSH、数据库)。

    • http:七层代理,解析 HTTP 协议,支持 URL 路由、Header 处理等(最常用)。

    • health:健康检查专用模式。

    示例

    mode http  # 处理 HTTP 请求
    
3. 访问控制
  • 使用 ACL(访问控制列表)
    通过 acl 定义匹配规则,结合 http-request 实现请求过滤:

    acl allowed_ips src 192.168.1.0/24  # 允许的 IP 段
    http-request deny unless allowed_ips  # 拒绝未授权的 IP
    
    acl is_admin path_beg /admin  # 匹配 /admin 开头的路径
    http-request deny if is_admin !allowed_ips  # 禁止非授权 IP 访问 /admin
    
4. 请求转发规则
  • use_backend <后端名称> [如果条件]
    根据条件将请求转发到不同的后端服务器组:

    # 基于域名路由
    acl is_api hdr(host) -i api.example.com
    use_backend api_servers if is_api
    
    # 基于 URL 路径路由
    acl is_static path_beg /static
    use_backend static_servers if is_static
    
    # 默认后端(无匹配规则时使用)
    default_backend web_servers
    
5. HTTP 处理(仅 mode http 有效)
  • 请求 Header 处理

    http-request add-header X-Forwarded-Proto https if { ssl_fc }  # 添加协议头
    http-request set-header Host api.example.com if is_api  # 重写 Host 头
    
  • 请求速率限制

    acl rapid_req rate-limit(1) gt 100  # 1 秒内超过 100 次请求
    http-request deny if rapid_req  # 拒绝超速请求
    
6. 超时设置
  • timeout client <时间>
    客户端与 HAProxy 之间的空闲超时时间。
    示例

    timeout client 30s  # 30 秒无活动则断开连接
    
完整示例

以下是一个处理 HTTP/HTTPS 请求的 frontend 配置示例:

  • frontend 的隐式作用​​:当 frontend 直接通过 use_backend 指向某个已定义算法的 backend 时,frontend 中的 balance 实际无效(被 backend 覆盖)。但若未显式指定 backend 的算法,则 frontend 的 balance 可能被作为默认值传递(依赖 HAProxy 版本)。

frontend http_frontend
    bind *:80
    bind *:443 ssl crt /etc/haproxy/certs.pem
    mode http
    log global
    balance roundrobin
    option httplog
    
    # 访问控制
    acl allowed_ips src 192.168.1.0/24 127.0.0.1
    http-request deny unless allowed_ips
    
    # 请求路由
    acl is_api hdr(host) -i api.example.com
    acl is_static path_beg /static
    acl is_health path_beg /health
    
    use_backend api_servers if is_api
    use_backend static_servers if is_static
    use_backend health_check if is_health
    default_backend web_servers
    
    # HTTP 处理
    http-request add-header X-Forwarded-Proto https if { ssl_fc }
    http-request set-header X-Real-IP %[src]
    
    # 超时设置
    timeout client 30s

3.4 Proxies配置-backend

backend 的核心配置项及其用法:

基本语法:

backend <名称>
    mode { tcp | http | health }  # 与前端代理模式保持一致
    [其他配置...]
    server <名称> <IP:端口> [参数]  # 后端服务器定义
核心配置项
1. 后端服务器定义

用于指定后端真实服务的地址、端口及状态参数,是 backend 的核心配置。

  • 基础格式:

    server web1 192.168.1.10:80 check  # 定义服务器web1,启用健康检查
    server web2 192.168.1.11:80 check maxconn 100  # 限制最大连接数为100
    server web3 192.168.1.12:80 check backup  # 作为备用服务器(主服务器故障时启用)
    server web4 192.168.1.13:80 check weight 2  # 权重为2(默认权重1,权重越高被分配请求越多)
    
2. 负载均衡算法

默认使用 roundrobin(轮询),可根据需求指定其他算法:

  • roundrobin:按顺序轮询分配请求(默认),适合服务器性能相近的场景。

    backend web_servers
      mode http
      balance roundrobin  # 显式指定轮询算法
      server web1 192.168.1.10:80 check
    
  • leastconn:优先分配请求到连接数最少的服务器,适合长连接场景(如数据库)。

    backend db_servers
      mode tcp
      balance leastconn  # 最少连接数优先
      server db1 192.168.1.20:3306 check
    
  • source:基于客户端 IP 哈希,确保同一客户端始终访问同一服务器(适合会话绑定)。

    backend app_servers
      mode http
      balance source  # 客户端IP哈希
      server app1 192.168.1.30:8080 check
    
3. 健康检查

通过 check 参数启用,可自定义检查方式(仅 mode http 或 mode tcp 有效):

  • 基础 TCP 检查(默认,检查端口是否存活):

    server web1 192.168.1.10:80 check  # 定期尝试连接80端口,失败则标记为不可用
    
  • HTTP 健康检查(针对 mode http,检查特定路径的响应):

    backend web_servers
      mode http
      option httpchk GET /health  # 发送GET /health请求检查健康状态
      server web1 192.168.1.10:80 check inter 5s rise 2 fall 3  # 每5秒检查1次,2次成功标记可用,3次失败标记不可用
    
4. 会话保持

确保客户端多次请求路由到同一服务器(适合需要会话存储的应用):

  • appsession(基于应用层会话 ID,如 Cookie):

    backend web_servers
      mode http
      appsession SESSIONID len 52 timeout 3h  # 基于SESSIONID Cookie保持会话,超时3小时
      server web1 192.168.1.10:80 check
    
  • stick-table(基于客户端 IP 或其他标识的持久化):

    backend web_servers
      mode http
      stick-table type ip size 10000 expire 30m  # 存储客户端IP,保留30分钟
      stick on src  # 基于客户端IP绑定到特定服务器
      server web1 192.168.1.10:80 check
    
5. 超时设置

定义后端服务器的连接、响应等超时时间(需与前端超时配合):

backend web_servers
    mode http
    timeout connect 5s  # 与后端服务器建立连接的超时时间
    timeout server 30s  # 等待后端服务器响应的超时时间
    timeout tunnel 1h   # 隧道连接(如WebSocket)的超时时间
    server web1 192.168.1.10:80 check
6. 错误处理

指定后端无可用服务器时的响应(仅 mode http 有效):

backend web_servers
    mode http
    server web1 192.168.1.10:80 check
    errorfile 503 /etc/haproxy/errors/503.http  # 当所有服务器不可用时,返回自定义503页面
完整示例

以下是一个处理 HTTP 请求的 backend 配置示例,包含负载均衡、健康检查和会话保持:

backend web_servers
    mode http  # 与前端保持一致
    balance leastconn  # 优先分配到连接数最少的服务器
    
    # 健康检查配置
    option httpchk GET /health
    default-server inter 10s rise 2 fall 3  # 所有服务器默认每10秒检查,2次成功/3次失败切换状态
    
    # 后端服务器列表
    server web1 192.168.1.10:80 check weight 2  # 权重2,优先级更高
    server web2 192.168.1.11:80 check weight 1
    server web3 192.168.1.12:80 check backup  # 备用服务器
    
    # 会话保持(基于客户端IP)
    stick-table type ip size 5000 expire 1h
    stick on src
    
    # 超时设置
    timeout connect 5s
    timeout server 60s

3.5 Proxies配置-listen 简化配置

在 HAProxy 中,listen 块是一种简化的配置方式,它将 frontend(监听端口、接收请求)和 backend(负载均衡、服务器管理)的功能合并到一个块中,适合场景简单、无需复杂路由的服务(如单一应用、数据库代理、监控页面等)。

listen 块的核心优势

  • 配置简洁:无需分离 frontend 和 backend,一个块完成所有配置。

  • 专注单一服务:适合仅需 “监听某个端口 + 转发到一组服务器” 的场景。

  • 减少冗余:避免简单服务的配置分散在多个块中。

listen 块的常用核心配置项
1. bind <IP:端口> [参数]

作用:定义 listen 块监听的网络端口,是接收请求的入口。
参数详解

  • <IP:端口>

    • *:80:监听所有网络接口的 80 端口(常用)。

    • 192.168.1.100:443:仅监听指定 IP(192.168.1.100)的 443 端口。

    • :8080:等价于 *:8080,省略 IP 即监听所有接口。

  • 可选参数(针对 HTTPS 或高级场景):

    • ssl:启用 SSL/TLS 加密(用于 HTTPS)。

    • crt <证书路径>:指定 SSL 证书文件(如 crt /etc/haproxy/cert.pem)。

    • alpn h2,http/1.1:支持 HTTP/2 协议(需配合 ssl)。

示例

listen web_ssl
    bind *:443 ssl crt /etc/haproxy/certs.pem alpn h2,http/1.1  # 监听 443 端口,支持 HTTPS 和 HTTP/2
2. mode { tcp | http | health }

作用:指定代理的协议模式,决定 HAProxy 如何解析和处理请求。

  • mode tcp

    • 四层代理(传输层),仅转发 TCP 数据包,不解析应用层协议(如 HTTP、MySQL)。

    • 适用场景:数据库(MySQL、Redis)、SSH 等非 HTTP 服务。

  • mode http

    • 七层代理(应用层),解析 HTTP 协议,支持基于 URL、Host 头的路由和修改。

    • 适用场景:Web 服务器、API 服务等 HTTP 应用。

  • mode health

    • 专用健康检查模式,仅用于内部健康检测,极少直接配置。

示例

listen mysql_proxy
    mode tcp  # 数据库用 TCP 模式,不解析 SQL 内容
    bind *:3306
3. balance <算法>

作用:定义请求在后端服务器之间的分配策略(负载均衡算法)。
常用算法:

  • roundrobin(默认):

    • 轮询:按顺序依次分配请求到服务器,适合性能相近的无状态服务(如静态资源)。

  • leastconn

    • 最少连接:优先分配到当前连接数最少的服务器,适合长连接服务(如数据库、WebSocket)。

  • source

    • 源地址哈希:基于客户端 IP 哈希,确保同一客户端始终访问同一服务器(适合会话绑定)。

  • uri

    • URI 哈希:基于请求路径(如 /api/user)哈希,相同路径的请求分配到同一服务器(适合缓存场景)。

示例

listen api_service
    mode http
    balance leastconn  # API 服务用最少连接算法,避免单台服务器过载
4. server <名称> <IP:端口> [参数]

作用:定义后端服务器列表及属性,是 listen 块的核心配置。

  • <名称>:服务器的别名(如 web1db2),仅用于配置和日志显示。

  • <IP:端口>:服务器的实际地址(如 192.168.1.10:8080)。

  • 关键参数:

    • check:启用健康检查(默认禁用,需显式添加)。

    • inter <时间>:健康检查间隔(如 inter 2s 表示每 2 秒检查一次)。

    • rise <次数>:连续多少次检查成功后,标记服务器为可用(如 rise 2)。

    • fall <次数>:连续多少次检查失败后,标记服务器为不可用(如 fall 3)。

    • weight <权重>:服务器权重(数值越高,分配的请求越多,默认 1)。

    • backup:标记为备用服务器,仅当主服务器全部故障时启用。

示例

listen web_servers
    server web1 192.168.1.10:80 check inter 3s rise 2 fall 3 weight 2  # 权重 2,优先分配
    server web2 192.168.1.11:80 check inter 3s rise 2 fall 3 weight 1  # 权重 1
    server web3 192.168.1.12:80 check backup  # 备用服务器
5. option <功能>

作用:启用特定功能(如日志、健康检查、HTTP 处理等),根据 mode 选择适用选项。

  • option httplog(仅 mode http):
    记录详细的 HTTP 日志(包含请求方法、URL、状态码等),默认仅记录基本信息。

  • option httpchk <请求>(仅 mode http):
    自定义 HTTP 健康检查请求(默认仅检查端口是否存活)。
    示例:option httpchk GET /health HTTP/1.1\r\nHost:example.com(发送带 Host 头的 GET 请求)。

  • option tcp-check(仅 mode tcp):
    启用 TCP 健康检查(如检查端口是否可连接,默认禁用)。

  • option dontlognull
    不记录空请求(如健康检查的心跳包),减少日志冗余。

示例

listen web_service
    mode http
    option httplog  # 记录详细 HTTP 日志
    option httpchk GET /health  # 用 /health 路径检查健康状态
6. timeout <类型> <时间>

作用:定义各类超时时间,避免连接长期占用资源。
常用超时类型:

  • timeout client <时间>:客户端无活动的超时时间(如 30s,超过则断开连接)。

  • timeout server <时间>:后端服务器无响应的超时时间(如 60s,超过则标记请求失败)。

  • timeout connect <时间>:HAProxy 与后端服务器建立连接的超时时间(如 5s)。

  • timeout http-request <时间>:等待客户端发送完整 HTTP 请求的超时时间(如 10s)。

示例

listen api_service
    timeout client 30s    # 客户端 30 秒无活动则断开
    timeout server 60s    # 服务器 60 秒无响应则超时
    timeout connect 5s    # 5 秒内未与服务器建立连接则失败

4、socat 工具的使用

4.1 安装socat 

4.2 修改haproxy的配置文件

下面socat的常用示例我们只使用一个进程来作为示例的实验环境。

开启haproxy多进程之后,可以指定多个套接字文件,然后指定哪一个套接字文件来对接哪个haproxy进程。示例如下图:

4.3 查看帮助

[root@haproxy 桌面]# socat -h
或者
[root@haproxy 桌面]# man socat
或者
[root@haproxy 桌面]# echo "help" | socat stdio /var/lib/haproxy/stats

#这三条命令可以查看socat命令的相关用法

4.4 socat的常用示例

1. 查看haproxy的状态
2. 查看服务器集群的状态 
3. 查看服务器集群中某个服务器的权重
4. 设置服务器的权重

 5. 设置后端服务器的下线和上线

根据服务器权重进行负载均衡的访问情况如下:

将web1下线后,再次进行访问。发现只能访问到web2,说明web1已经下线了。

将web1重新上线,然后进行访问。发现又能根据服务器权重进行负载均衡的访问情况回来了,说明web1重新上线的操作成功。

三、haproxy的算法

了解慢启动

在服务器(尤其是负载均衡场景下的后端服务器)语境中,慢启动(Slow Start) 是一种用于逐步增加服务器负载的机制,目的是避免服务器刚启动或恢复服务时因突然接收大量请求而被压垮,确保其平稳过渡到正常工作状态。

慢启动的核心逻辑

当一台后端服务器满足以下条件时,慢启动机制会被触发:

  • 刚启动完成,准备加入集群提供服务;

  • 从故障状态恢复(如之前因超时而被负载均衡器下线,现在恢复正常);

  • 手动重新启用(如通过负载均衡器的命令将其从 “禁用” 改为 “启用”)。

此时,负载均衡器不会立即将其纳入正常的负载分配队列(即不分配与其他正常服务器同等比例的请求),而是逐步提高其权重(或分配的请求比例),例如从 0 开始,每隔一定时间增加一定权重,直到达到预设的目标权重(与其他服务器一致)。

通过这种 “渐进式加载”,服务器有足够时间预热(如初始化缓存、建立数据库连接、加载必要资源等),避免因瞬间高负载导致新的故障(如内存溢出、响应超时)。

1、静态算法

静态算法:按照事先定义好的规则轮询公平调度,不关心后端服务器的当前负载、连接数和响应速度 等,且无法实时修改权重(只能为01,不支持其它值),只能靠重启HAProxy生效。

静态算法仅按预定义规则分发请求,​​不感知后端负载​​,权重修改需重启生效,适用于配置稳定的环境。

3.1.1 ​static-rr(静态加权轮询)​

  • ​机制​​:按权重比例轮询分发请求,权重高的服务器获得更多流量。

  • ​局限​​:

    • 权重仅支持 0(禁用)或 1(启用),不支持其他值。

    • 不支持慢启动(新服务器上线即承受高负载)。

  • ​场景​​:后端服务器性能均匀且无需动态调整权重的场景。

3.1.2 ​first(首服务器优先)​

  • ​机制​​:按服务器列表顺序分配请求,仅当第一台服务器连接数达上限(需配置 maxconn)才调度至下一台。

  • ​局限​​:

    • 完全忽略权重设置。

    • 服务器故障时可能造成请求堆积。

  • ​场景​​:极少使用,仅适用于特殊需求如最小化活跃服务器数量。

2、动态算法

动态算法
  • 基于后端服务器状态进行调度适当调整
  • 新请求将优先调度至当前负载较低的服务器
  • 权重可以在haproxy运行时动态调整无需重启

动态算法实时感知后端状态(如连接数、负载),​​支持运行时权重调整​​(通过 socat 动态修改),无需重启。

3.2.1 roundrobin(动态加权轮询)​

  • ​机制​​:基于权重轮询,但优先将请求分发给当前负载低的服务器。

  • ​特点​​:

    • 支持慢启动(新服务器逐渐增加流量)。

    • 单后端最多支持 4095 个服务器(static-rr 无此限制)。

  • ​场景​​:​​默认算法​​,适用于 HTTP/TCP 通用场景。

3.2.2 ​leastconn(加权最少连接)​

  • ​机制​​:优先将请求分发给当前​​连接数最少​​的服务器,其次考虑权重。

  • ​特点​​:

    • 尤其适合长连接服务(如数据库、消息队列)。

  • ​场景​​:MySQL、LDAP 等长会话业务。

3.2.3 ​random(随机调度)​

  • ​机制​​:随机选择服务器,权重高的服务器被选中的概率更高。

  • ​场景​​:超大规模集群或频繁扩缩容的环境。

3、其他算法

其它算法默认为静态算法(取模法),但可通过 hash-type consistent 改为动态算法(一致性哈希),实现会话保持。

取模法(Map-based Hashing)和一致性哈希(Consistent Hashing)的解析与对比

核心原理​
​1. 取模法(Hash Modulo)​
  • ​基本原理​​:
    对键(Key)计算哈希值(如 hash(key)),再对节点数量 N 取模(hash(key) % N),结果即为数据存储的节点编号。
    ​示例​​:
    若 N=3,则 hash(key) % 3 的结果为 0、1 或 2,分别对应节点 Node0、Node1、Node2。

  • ​数据分布​​:
    初始分布均匀,但​​完全依赖节点数量 N​​。节点增减时,N 变化导致所有数据的映射关系重新计算,引发大规模数据迁移。

​2. 一致性哈希(Consistent Hashing)​
  • ​基本原理​​:
    将哈希值空间组织成一个环形结构(哈希环,范围通常为 0∼232−1)。节点和数据均映射到环上,数据存储位置由其哈希值顺时针找到的第一个节点决定。

  • ​数据分布​​:
    节点映射到环上后,数据仅存储在​​顺时针方向最近的节点​​。节点增减时,仅影响相邻节点的数据(局部迁移)。

总结:核心差异对比​
​维度​ ​取模法​ ​一致性哈希​
​数据迁移范围​ 全局迁移(节点变更时几乎全部数据受影响) 局部迁移(仅相邻节点数据受影响)
​负载均衡​ 初始均匀,但无法动态调整权重 通过虚拟节点实现动态负载均衡
​复杂度​ 简单,易实现 需维护哈希环和虚拟节点(实现较复杂)
​扩展性​ 差(扩容/缩容成本高) 优(支持动态增减节点)
​故障容忍度​ 低(节点故障引发雪崩) 高(故障仅影响局部数据)

3.3.1 source算法(基于客户端IP哈希)

  • 原理​​:
    对客户端源IP进行哈希计算,映射到固定后端服务器。同一IP的请求始终分配给同一服务器,确保会话连续性。

  • ​动静结合​​:

    • ​静态模式(取模法)​​:balance source,节点增减时全局重新映射(不推荐)。

    • ​动态模式(一致性哈希)​​:hash-type consistent,节点变动时仅影响相邻IP的会话(迁移比例约 q/(N+q))。

  • 配置示例​​:

    backend app_servers
      balance source
      hash-type consistent  # 启用一致性哈希
      server s1 192.168.1.10:80
      server s2 192.168.1.20:80
  • ​适用场景​​:
    TCP长连接(如数据库、游戏服务),或HTTP无Cookie会话保持

3.3.2 uri算法

  • ​原理​​:
    对请求URI的路径(如/api/user)进行哈希,相同路径的请求分配到固定服务器。

  • ​动静结合​​:

    • ​静态模式​​:balance uri,权重变化导致URI重新分配。

    • ​动态模式​​:hash-type consistent,URI与节点绑定稳定,适合缓存优化。

  • ​配置示例​​:
    backend static_servers
      balance uri
      hash-type consistent
      server cache1 10.0.0.10:80
      server cache2 10.0.0.20:80
  • ​适用场景​​:
    静态资源(如图片、CSS)缓存服务器,提升重复请求命中率。

3.3.3 url_param算法

  • 原理​​:
    根据URL参数(如?user_id=1001)哈希分配请求,需指定参数名(如user_id)。

  • ​动静结合​​:

    • ​静态模式​​:balance url_param user_id

    • ​动态模式​​:hash-type consistent,用户会话在服务器扩容时保持局部稳定。

  • ​配置示例​​:
    backend user_servers
      balance url_param user_id
      hash-type consistent
      server app1 10.1.1.10:8080
      server app2 10.1.1.20:8080
  • ​适用场景​​:
    电商用户会话跟踪、API路由(如按用户ID分流)。

3.3.4 hdr算法

针对用户每个http头部(header)请求中的指定信息做hash, 此处由 name 指定的http首部将会被取出并做hash计算, 然后由服务器总权重取模以后派发至某挑出的服务器,如果无有效值,则会使用默认的轮询调度。

  • 原理​​:
    根据指定HTTP头部字段(如User-AgentAuthorization)的值进行哈希。

  • ​动静结合​​:

    • ​静态模式​​:balance hdr(User-Agent)

    • ​动态模式​​:hash-type consistent,头部值绑定节点,减少会话中断。

  • ​配置示例​​:
    backend mobile_servers
      balance hdr(User-Agent)
      hash-type consistent
      server mobile1 10.2.1.10:80
      server mobile2 10.2.1.20:80
  • ​适用场景​​:
    区分设备类型(移动端/桌面端)、按授权令牌路由API请求。

curl命令的 -v 和 -A 参数说明:

1. -v 参数(详细模式)

功能

  • 启用详细输出模式,显示 curl 与服务器通信的完整过程,包括:

    • DNS 解析过程

    • TCP 连接建立(包括 SSL/TLS 握手信息)

    • HTTP 请求头和响应头

    • 数据传输进度

    • 连接关闭信息

2. -A 参数(自定义 User-Agent)

功能

  • 覆盖 curl 默认的 User-Agent 请求头,模拟特定客户端类型。

  • 默认情况下,curl 的 User-Agent 格式为 curl/版本号(如 curl/7.81.0)。

测试访问情况如下:

hdr(User-Agent)算法会对请求头中的User-Agent字段计算哈希值,不同User-Agent(如Chrome、Safari、爬虫UA)的哈希值不同,因此可能被分配到不同的后端服务器(RS)。

四、高级功能及配置

介绍 HAProxy 的高级配置及实用案例

1、基于cookie的会话保持

1.1 配置选项

cookie的配置选项:

cookie name [rewrite | insert | prefix] [indirect] [nocache] [postonly] [preserve] [httponly] [secure] [domain] *[maxidle<idle>] [maxlife]

1.2 配置示例

1.3 验证cookie信息

curl命令的 -b 参数:

  • 作用:向 HTTP 请求添加 Cookie 信息。支持两种格式:

    • 键值对:如 -b "NAME=VALUE",直接设置 Cookie。

    • 文件路径:如 -b cookies.txt,从文件读取 Cookie(格式需符合 Netscape Cookie 规范)。

 2、HAProxy状态页

2.1 状态页配置项

HAProxy 的状态页(Statistics Page)是一个强大的监控工具,可实时展示负载均衡器和后端服务器的运行状态。以下是配置状态页的核心参数及其用法:

基本配置语法

listen stats
    mode http               # 使用 HTTP 模式
    bind *:9999             # 监听地址和端口
    stats enable            # 启用状态页
    stats uri /status       # 访问路径
    stats auth user:pass    # 认证信息

核心配置参数

1. 基础设置
参数 作用
stats enable 启用状态页功能。
stats uri <path> 设置访问路径(如 /stats,默认值为/haproxy?stats)。
stats realm <text> 设置认证对话框的提示文本(如 HAProxy Statistics)。
stats auth <user:pass> 设置基本认证(明文密码,不推荐)。
stats auth-file <path> 从文件读取加密认证信息(推荐,使用 htpasswd 生成)。
2. 访问控制
参数 作用
acl <name> src <ip> 定义允许访问的 IP 或网段(如 acl allowed src 192.168.1.0/24)。
http-request deny unless <acl> 拒绝未通过 ACL 检查的请求。
3. 显示选项
参数 作用
stats refresh <sec> 设置自动刷新间隔(如 30s)。
stats hide-version 隐藏 HAProxy 版本信息(增强安全性)。
stats admin if/unless <acl>

允许通过状态页管理服务器(如启用 / 禁用服务器),需配合 ACL。

stats admin if <acl_name>    # 仅当 ACL 条件满足时允许管理访问
stats admin unless <acl_name> # 仅当 ACL 条件不满足时允许管理访问
stats show-node 显示 HAProxy 节点名称。
stats show-legends 显示指标说明(图例)。
4. 日志设置
参数 作用
log global 使用全局日志配置记录状态页访问。
option httplog 启用 HTTP 日志格式。

使用浏览器登录此界面进行测试:

下图即为HAProxy的状态页:

HAProxy 的状态页提供了丰富的监控指标,以下是默认状态页的核心参数及其含义,按功能分类说明:

1、全局统计参数 

  1. ​进程信息​

    • ​pid​​:当前 HAProxy 进程的 PID。

    • ​nbproc/nbthread​​:进程总数和每个进程的线程数。

    • ​uptime​​:HAProxy 服务的运行时长。

  2. ​系统资源限制​

    • ​memmax​​:内存使用上限(通常为 unlimited)。

    • ​ulimit-n​​:进程可打开的最大文件描述符数(影响并发连接能力)。

    • ​maxsock​​:最大 Socket 连接数。

    • ​maxconn​​:单进程最大并发连接数(与 ulimit-n 关联)。

  3. ​实时流量指标​

    • ​conn rate​​:当前每秒新建立的连接数。

    • ​bit rate​​:当前网络吞吐速率(单位:bps)。

    • ​current connections​​:当前活跃连接总数。

2、流量与错误统计(按后端服务器分组)

  1. ​会话速率(Session Rate)​

    • ​cur​​:当前每秒处理的会话数。

    • ​max​​:历史最高每秒会话数。

    • ​limit​​:配置的会话速率上限。

  2. ​错误统计(Errors)​

    • ​Req​​:请求错误数(如无效 HTTP 格式)。

    • ​Conn​​:连接错误数(如超时、拒绝连接)。

    • ​Resp​​:响应错误数(如后端返回 5xx 错误)。

  3. ​重试与重分发(Retries/Warnings)​

    • ​Retr​​:请求重试次数(因后端故障触发)。

    • ​Redis​​:请求重分发次数(因 option redispatch 生效)。

3、后端服务器(Backend Server)状态 

  1. ​服务器健康状态(Status)​

    • ​UP​​:服务器健康,可接收流量。

    • ​DOWN​​:服务器不可用(健康检查失败)。

    • ​MAINT​​:人工维护状态(手动禁用)。

    • ​GOING UP/DOWN​​:状态切换中(如健康检查波动)。

  2. ​服务器指标​

    • ​LBTot​​:服务器被选中的总次数(负载均衡决策)。

    • ​LastChk​​:最后一次健康检查的时间/结果。

    • ​Wght​​:服务器的权重值(影响流量分配比例)。

    • ​Act/Bck​​:活动连接数/备份服务器数量。

  3. ​流量与连接​

    • ​Bytes In/Out​​:流入/流出的总数据量(单位:字节)。

    • ​Dwn​​:服务器持续 DOWN 状态的总时长。

4、会话与队列统计 

  1. ​会话信息(Sessions)​

    • ​cur​​:当前活跃会话数。

    • ​max​​:历史最高并发会话数。

    • ​total​​:累计处理的会话总数。

  2. ​队列状态(Queues)​

    • ​qcur​​:当前等待队列中的请求数。

    • ​qmax​​:队列中等待请求的历史峰值。

5、拒绝与限制(Denied/Throttle) 

  • ​Denied Req/Resp​​:因 ACL 规则或安全策略拒绝的请求/响应数。

  • ​Throttle​​:因速率限制(如 maxconn)被限制的请求数。

HAProxy状态页总结:

HAProxy 状态页是运维核心工具,通过上述参数可实时监控:

  1. ​系统负载​​:连接速率(conn rate)、并发数(current)反映实时压力。

  2. ​后端健康​​:UP/DOWN 状态和 LastChk 揭示服务器可用性。

  3. ​错误定位​​:Req/Conn/Resp 错误数帮助快速排查故障。

  4. ​性能瓶颈​​:队列长度(qcur)和会话峰值(max sessions)指示扩容需求。

3、IP透传

3.1 未开启透传的tcp四层代理

在Real Server中正常的nginx配置

未开启IP透传的四层代理的访问测试:

可以看到Nginx 服务器的访问日志里是看不到访问服务器的客户端的IP的。

3.2 开启四层透传 

注意:每次修改完配置文件都要重启对应的服务来让新的配置生效!!!

在负载均衡器上的haproxy配置文件中添加send-proxy指令。

两台RS中的nginx服务器配置都要进行修改,添加下图中新添加的配置。

开启了IP透传的tcp四层代理的访问测试:

可以看到能获取到客户端的IP地址了。

3.3 开启七层IP透传

可以看到RS1开启了send-proxy选项,并且RS1的nginx服务器启用了PROXY协议解析但是没有添加内置变量用于获取PROXY协议传递的IP地址,而RS2中什么都没有添加。

在 Nginx 配置中,$proxy_protocol_addr 是一个内置变量,用于获取通过 PROXY 协议传递的客户端真实 IP 地址。

经过测试发现开启了七层IP透传后,RS1的nginx服务器无论添不添加$proxy_protocol_addr 这个变量都能获取到客户端的真实IP地址,说明RS1用的也是七层IP透传。

最后测试:

发现无论是RS1还是RS2的日志中都能获取到客户端的真实IP地址,说明七层IP透传成功。

option forward 与 send-proxy 的区别
特性 option forwardfor send-proxy
适用模式 仅七层(mode http 四层(mode tcp)和七层(mode http)均可
传递方式 通过 HTTP 头(X-Forwarded-For 通过 PROXY 协议(独立于 HTTP 协议)
安全性 头字段可被客户端伪造(需后端验证) 协议层面传递,伪造难度高(需后端支持)
后端要求 应用需解析 HTTP 头(兼容性好,几乎所有 Web 应用支持) 后端需支持 PROXY 协议(如 Nginx、HAProxy)
web服务器日志格式配置:后端服务器如何使用 X-Forwarded-For

后端服务器(如 Nginx、Apache、应用程序)需要解析 X-Forwarded-For 头以获取客户端真实 IP,以下是常见场景的配置:

1. Nginx 配置

在 Nginx 中,通过 $http_x_forwarded_for 变量获取客户端真实 IP,并应用到日志或业务逻辑:

server {
    listen 80;
    server_name example.com;
    
    # 日志中记录客户端真实 IP
    log_format main '$http_x_forwarded_for - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent"';
    access_log /var/log/nginx/access.log main;
    
    # 向后端应用传递真实 IP(如 PHP、Java 应用)
    location / {
        proxy_pass http://app_server;
        proxy_set_header X-Real-IP $http_x_forwarded_for;  # 传递给应用
    }
}
2. Apache 配置

在 Apache 中,通过 mod_remoteip 模块解析 X-Forwarded-For

LoadModule remoteip_module modules/mod_remoteip.so
RemoteIPHeader X-Forwarded-For  # 指定头字段
RemoteIPTrustedProxy 10.0.0.1   # 信任 HAProxy 的 IP(避免伪造)

# 日志格式中使用真实 IP
LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

4、ACL访问控制

访问控制列表ACLAccess Control Lists)。

是一种基于包过滤的访问控制技术。

它可以根据设定的条件对经过服务器传输的数据包进行过滤(条件匹配)即对接收到的报文进行匹配和过 滤,基于请求报文头部中的源地址、源端口、目标地址、目标端口、请求方法、URL、文件后缀等信息内 容进行匹配并执行进一步操作,比如允许其通过或丢弃。

4.1 ACL配置选项

#用acl来定义或声明一个acl

acl         <aclname>         <criterion>         [flags]         [operator]         [<value>]
acl             名称                 匹配规范        匹配模式      具体操作符     操作对象类型
4.1.1 ACL-Name 名称

acl示例:acl         test         path_end         -m         sub         /a

#ACL名称,可以使用大字母A-Z、小写字母a-z、数字0-9、冒号:、点.、中横线和下划线,并且严格区分大 小写,比如:my_aclMy_Acl就是两个完全不同的acl
4.1.2 ACL-criterion 匹配规范

定义ACL匹配规范,即:判断条件

1、HTTP首部匹配规范

用于提取并匹配HTTP请求/响应报文的首部信息。

​匹配方法​ ​语法​ ​功能说明​ ​应用场景示例​ ​配置示例​
​hdr​ hdr(<name>[,<occ>]) 精确匹配首部字段值 验证特定头内容 acl auth hdr(Authorization) -i Bearer
​hdr_beg​ hdr_beg(<name>[,<occ>]) 匹配首部字段值的​​开头​ 识别子域名或服务类型 acl static hdr_beg(Host) -i img. video.
​hdr_end​ hdr_end(<name>[,<occ>]) 匹配首部字段值的​​结尾​ 按域名后缀路由 acl cn_dom hdr_end(Host) -i .cn
​hdr_dom​ hdr_dom(<name>[,<occ>]) 匹配Host的​​主域名​ 按域名分流请求 acl site1 hdr_dom(Host) -i shop.com
​hdr_sub​ hdr_sub(<name>[,<occ>]) ​子串匹配​​首部字段值 过滤恶意User-Agent acl bad_agent hdr_sub(User-Agent) -i curl wget
​hdr_reg​ hdr_reg(<name>[,<occ>]) ​正则表达式匹配​ 复杂域名或路径规则 acl bbs hdr_reg(Host) -i (bbs|forum).com
​hdr_len​ hdr_len(<name>[,<occ>]) 匹配首部字段值的​​长度​ 防御超长头部攻击 acl long_hdr hdr_len(User-Agent) gt 500

关键参数说明:

  • <occ>​:指定多值首部中的第几个值(如多个Cookie值)。

  • -i​:忽略大小写(常用)。

  • -m​:指定匹配模式(如-m beg前缀匹配)。


2、URL路径匹配规范

path 用于提取并匹配URL中的路径部分(不包含主机名和查询参数)。

​匹配方法​ ​语法​ ​功能说明​ ​应用场景示例​ ​配置示例​
​path​ path 精确匹配完整路径 特定页面路由 acl home path /index.html
​path_beg​ path_beg 匹配路径​​开头​ 静态资源目录分离 acl static path_beg -i /static/ /img/
​path_end​ path_end 匹配路径​​结尾​ 按文件类型分流 acl image path_end -i .jpg .png
​path_sub​ path_sub 路径中​​包含子串​ 拦截危险路径 acl unsafe path_sub -i /admin/
​path_reg​ path_reg ​正则匹配​​路径 复杂路径规则 acl dynamic path_reg -i ^/app/.*\.php$
​path_dir​ path_dir 匹配路径中的​​目录名​ 按目录分类请求 acl uploads path_dir -i /uploads/

base 用于提取请求中的 Host 头 + URL 路径(不含查询参数),格式为 Host/Path。适用于虚拟主机路由场景,例如根据域名和路径组合路由请求。

​匹配类型​ ​语法​ ​功能说明​ ​应用场景示例​ ​配置示例​
​base​ base <value> 精确匹配整个 Host/Path 特定虚拟主机的固定路径 acl shop base "shop.com/cart"
​base_beg​ base_beg <prefix> 匹配 Host/Path 的开头 识别子域名下的统一前缀路径 acl static base_beg "cdn.com/static"
​base_dir​ base_dir <subdir> 匹配路径中的子目录 按目录分类请求(如资源文件夹) acl uploads base_dir -i "/uploads"
​base_dom​ base_dom <domain> 匹配主域名(忽略子域名) 泛域名路由(如所有子域名到同一后端) acl main_site base_dom "example.com"
​base_end​ base_end <suffix> 匹配 Host/Path 的结尾 按文件类型或固定后缀路由 acl api base_end -i "/v1/endpoint"
​base_reg​ base_reg <regex> 正则表达式匹配 复杂路由规则(如动态路径) acl dynamic base_reg -i "^bbs\.com/thread/\d+"
​base_sub​ base_sub <substring> 子串匹配(模糊匹配) 路径中包含关键词的请求 acl search base_sub -i "/search"
​base_len​ base_len <length> 匹配 Host/Path 的长度 防御超长路径攻击 acl long_req base_len gt 200

url 用于提取完整 URL(含协议、域名、路径、查询参数及锚点),格式为 <scheme>://<host>:<port>/<path>?<query>#<frag>。适用于精确重定向或完整路径匹配。

​匹配类型​ ​语法​ ​功能说明​ ​应用场景示例​ ​配置示例​
​url​ url <value> 精确匹配完整 URL 特定页面的重定向 acl redirect url "http://old.com/pricing"
​url_beg​ url_beg <prefix> 匹配 URL 的开头 按协议或固定前缀路由 acl https_url url_beg "https://secure."
​url_dir​ url_dir <subdir> 匹配路径中的子目录 分类带参数的目录请求 acl v2_api url_dir -i "/api/v2"
​url_dom​ url_dom <domain> 匹配主域名 泛域名重定向 acl old_domain url_dom "old-site.com"
​url_end​ url_end <suffix> 匹配 URL 的结尾 按文件类型或固定后缀重定向 acl legacy_url url_end -i ".asp"
​url_reg​ url_reg <regex> 正则表达式匹配 复杂重定向规则(含动态参数) acl dynamic_redirect url_reg -i "^http://old\.com/user/\d+/profile"
​url_sub​ url_sub <substring> 子串匹配(模糊匹配) URL 中包含关键词的请求 acl promo url_sub -i "campaign_id="
​url_len​ url_len <length> 匹配 URL 的长度 防御超长 URL 攻击 acl long_url url_len gt 500

以上三种 HAProxy 的路径匹配方法对比表

​对比维度​ path base url
​提取范围​ 请求的URL路径(从首个/开始,到?前结束,​​不包含域名和协议​​) Host头 + URL路径(​​不含查询参数​​),格式如 example.com/path ​完整URL​​(含协议、域名、路径、查询参数及锚点),如 http://example.com/path?id=1
​匹配目标​ 纯路径(如 /api/user 域名+路径组合(如 shop.com/cart 完整请求地址(如 https://shop.com/cart?item=123
​典型语法​ path_beg /static
path_end .jpg
base_beg "cdn.com/static"
base_dom "example.com"
url_reg "^http://old\.com/.*"
url_sub "campaign_id="
​适用场景​ ✅ 静态资源分离(.css/.js
✅ 按目录路由(/admin/
✅ 虚拟主机路由(不同域名+路径到不同后端)
✅ 子域名分类(img.domain.com
✅ 带参数重定向(保留 ?id=1
✅ 完整URL正则匹配(复杂路由)
​性能影响​ ⚡ ​​最低​​(仅解析路径) ⚡ ​​中​​(需拼接域名+路径) ⚡ ​​高​​(需解析完整URL,正则开销大)
​注意事项​ ❗ 无法区分同名路径的不同域名请求 ❗ 自动忽略查询参数(?后内容) ❗ 避免贪婪正则(如 .*),易引发CPU飙升

总结:

  • ​首选 path​:纯路径匹配场景(如按文件类型、目录路由)。

  • ​次选 base​:需​​域名+路径​​组合时(如 blog.com/api),性能优于 url

  • ​慎用 url​:仅需处理​​完整URL​​(如带查询参数的重定向)时使用,避免复杂正则。


3、网络层匹配规范

基于IP、端口等网络层信息过滤。

​匹配方法​ ​语法​ ​功能说明​ ​应用场景示例​ ​配置示例​
​src​ src 匹配​​源IP​ 黑名单/IP白名单 acl block src 10.0.0.7 192.168.1.0/24
​src_port​ src_port 匹配​​源端口​ 限制特权端口访问 acl invalid_port src_port 0:1023
​dst​ dst 匹配​​目标IP​ 多IP主机分流 acl vip dst 192.168.10.100
​dst_port​ dst_port 匹配​​目标端口​ 按端口转发服务 acl http dst_port 80
 4、响应状态码匹配(status)​

功能​​:
基于HTTP响应报文中的状态码(如200、404、500等)执行策略,常用于故障转移或监控告警。

语法​​:

acl <acl_name> status <operator> <status_code>
  • 常用操作符​​:
    eq(等于)、ge(大于等于)、lt(小于)等。

  • ​示例配置​​:

    acl server_error status ge 500 # 匹配5xx服务器错误 
    use_backend fallback_backend if server_error # 触发故障转移

场景​​:

  • 自动将5xx错误请求转移到备用后端

  • 结合监控系统实时告警(如Prometheus + Grafana)

5、​​HTTP方法限制(ACL + http-request deny

功能​​:
仅允许特定HTTP方法(如GET、HEAD),拒绝其他危险方法(如PUT、DELETE)。

​语法​​:

acl <acl_name> method <method> # 定义允许的方法 
http-request deny if !<acl_name> # 拒绝不匹配的请求

​示例配置​​:

acl valid_method method GET HEAD # 仅允许GET和HEAD 
http-request deny if !valid_method # 拒绝其他方法(返回403)

​关键点​​:

  1. ​拒绝响应​​:默认返回403 Forbidden,可通过errorfile自定义错误页面:

    errorfile 403 /etc/haproxy/errors/403.http

  2. ​安全加固​​:有效防御非法请求(如恶意上传、删除操作)

  3. ​HEAD方法处理​​:需确保后端服务正确处理HEAD请求(不返回响应体)

4.1.3 ACL-flags 匹配模式

匹配模式用于修改匹配行为,常见选项包括:

  • -i :不区分大小写(如 hdr(host) -i example.com)。

  • -m <类型> :使用指定的正则表达式匹配方法,如:

    • -m str:字符串精确匹配。

    • -m sub:子串匹配。

    • -m reg:正则表达式匹配。

    • -m dom:域名匹配(如 .example.com 匹配所有子域名)。

  • -n :不做DNS解析

  • -u :禁止 ACL 重名,否则多个同名 ACL 匹配会自动合并为或关系,可能导致意外匹配。

4.1.4 ACL-operator 具体操作符

HAProxy的ACL操作符(ACL-operator)用于定义匹配条件的具体比较方式,主要分为​​整数比较​​和​​字符/模式匹配​​两大类。以下是具体操作符及其功能详解:

1、整数比较操作符​

适用于数值型数据(如端口号、响应状态码、会话速率等):

​操作符​ ​含义​ ​示例​ ​适用场景​
eq 等于 acl port_eq dst_port eq 80 匹配目标端口为80的请求
ge 大于等于 acl high_rate be_sess_rate ge 100 后端会话速率≥100/s时触发动作
gt 大于 acl attack fe_sess_rate gt 500 前端会话速率>500/s时判定为攻击
le 小于等于 acl safe_conn conn le 10 连接数≤10时视为安全
lt 小于 acl low_status status lt 200 响应状态码<200(如1xx信息类)

​注​​:常用于匹配端口范围(dst_port 0:1023)、状态码(status 404)或速率阈值(be_sess_rate)。

2、字符/模式匹配操作符​

通过 -m 标志指定匹配模式类型,适用于字符串类数据(如URL路径、Host头部、User-Agent等):

​操作符​ ​匹配模式​ ​语法示例​ ​典型应用场景​
-m str (或默认) ​精确匹配​ acl exact_path path -m str /login 严格匹配URL路径为/login
-m sub ​子串匹配​ acl bad_agent hdr(User-Agent) -m sub curl 过滤User-Agent含curl的请求
-m beg ​前缀匹配​ acl static_host hdr_beg(host) -m beg img. 匹配Host以img.开头的域名
-m end ​后缀匹配​ acl image_file path_end -m end .jpg .png 匹配.jpg.png结尾的资源
-m dir ​路径匹配​ acl wp_dir path_dir -m dir /wp-content 匹配路径中包含/wp-content
-m dom ​域名匹配​ acl cdn_dom hdr_dom(host) -m dom cdn.com 匹配域名包含cdn.com的请求
-m reg ​正则匹配​ acl script_tag path_reg -m reg \.php$ 用正则匹配.php结尾的URL

​关键说明​​:

  1. ​大小写控制​​:通过 -i 标志忽略大小写(如 -i -m beg www.)。
  2. ​多值匹配​​:同一ACL可指定多个值(如 path_end .js .css),满足任一即触发。
  3. ​正则灵活性​​:-m reg 支持复杂匹配(如 ^/api/v[1-3]/.*)。
3、操作符组合与逻辑控制​

ACL支持通过逻辑运算符组合多个条件:

​逻辑符​ ​作用​ ​示例​ ​效果​
​隐式与​ 同时满足 if valid_ip valid_port 需源IP和端口均合法才放行
` or` 满足其一
! 逻辑非 if ! whitelist 非白名单IP全部拒绝

​案例​​:

acl valid_method method GET POST # 精确匹配GET/POST方法

acl admin_path path_beg /admin # 路径前缀匹配

http-request deny if ! valid_method admin_path # 非GET/POST访问/admin时拒绝

该案例组合了精确匹配(method)、前缀匹配(path_beg)和逻辑非(!

4.1.5 ACL-value 操作对象

在 HAProxy 中,ACL(Access Control List,访问控制列表)的核心是通过对不同类型的 value(值)进行匹配,实现请求的过滤、路由或访问控制。value 的类型决定了 ACL 能匹配的对象和规则,以下是对各类 value 类型的详细说明及使用场景:

1. Boolean(布尔值)
  • 作用:用于判断条件是否 “真” 或 “假”,通常结合其他指令(如 exists)检查某个元素是否存在。

  • 示例

    # 检查请求中是否存在 "User-Agent" 头
    acl has_user_agent hdr(User-Agent) -m exists
    
    • 若请求头包含 User-Agent,则 has_user_agent 为 true;否则为 false

2. Integer 或 Integer Range(整数或整数范围)
  • 作用:匹配整数或连续的整数范围,常用于端口、状态码等数值类对象。

  • 匹配方式

    • 单个整数(如 80);

    • 范围(如 80-8080,表示 80 到 8080 之间的所有整数)。

  • 示例

    # 匹配请求的源端口在 1024-65535 之间(非特权端口)
    acl non_priv_port src_port 1024-65535
    
    # 匹配 HTTP 响应状态码为 200 或 301-302
    acl valid_status status 200 301-302
    
3. IP Address / Network(IP 地址或网络段)
  • 作用:匹配 IPv4 或 IPv6 地址,或指定网段(CIDR 格式),常用于限制客户端来源或路由到特定后端。

  • 格式

    • 单个 IP:如 192.168.1.100

    • 网段(CIDR):如 10.0.0.0/8(匹配 10 开头的所有 IP)、192.168.1.0/24(匹配 192.168.1.x 网段)。

  • 示例

    # 允许内部网段 192.168.1.0/24 访问
    acl internal_ip src 192.168.1.0/24
    
    # 拒绝特定 IP(如黑名单)
    acl blocked_ip src 203.0.113.5
    
4. String(字符串)

字符串是最常用的 value 类型,支持多种匹配方式,适用于域名、路径、请求头、Cookie 等文本类对象。根据匹配规则不同,可细分为以下子类型:

匹配方式

作用说明

示例

exact

精确匹配(完全相等),区分大小写(默认)。

acl is_google hdr(host) -i -m exact google.com-i 忽略大小写)

substring

子串匹配(只要字符串中包含目标子串即生效)。

acl has_php path_sub .php(匹配路径中包含 .php 的请求)

suffix

后缀匹配(字符串以目标后缀结尾)。

acl is_jpg url_end .jpg(匹配 URL 以 .jpg 结尾的静态资源)

prefix

前缀匹配(字符串以目标前缀开头)。

acl is_api path_beg /api/(匹配路径以 /api/ 开头的请求)

subdir

路径子目录匹配(针对 URL 路径,如 /static/js 匹配 /static 子目录)。

acl in_static_dir path_dir /static(匹配 /static 下的所有子路径)

domain

域名匹配(支持主域名或子域名,自动忽略端口)。

acl is_example hdr(host) -m domain example.com(匹配 example.com 及所有子域名,如 www.example.com

5. Regular Expression(正则表达式)
  • 作用:通过正则表达式实现复杂的字符串匹配,灵活性极高,适用于不规则或动态的匹配场景。

  • 语法:使用 -m reg 或 -m regex 标记,支持贪婪 / 非贪婪匹配(需结合正则语法)。

  • 示例

    # 匹配 URL 中包含数字的请求(如 /item/123、/page/456)
    acl has_digits url_reg ^/.*\d+.*$
    
    # 匹配邮箱格式的请求参数(如 ?email=user@example.com)
    acl valid_email url_param(email) -m reg ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
    
6. Hex Block(十六进制块)
  • 作用:匹配二进制数据的十六进制表示,常用于处理非文本协议(如 TCP 二进制协议)或特定字节序列。

  • 语法:直接使用十六进制字符串,无需前缀(如 48545450 对应 ASCII 中的 HTTP)。

  • 示例

    # 匹配 TCP 数据包中包含 "HTTP" 十六进制序列(48545450)的请求
    acl has_http_hex req.payload(0,4) 48545450
    
    • 上述示例中,req.payload(0,4) 表示取请求 payload 的前 4 个字节,与十六进制 48545450(即 ASCII 中的 HTTP)匹配。

ACL的value类型总结

ACL 的 value 类型覆盖了从简单布尔判断到复杂正则匹配的场景,核心是根据实际需求选择合适的类型:

  • 限制 IP 用 IP 地址 / 网段

  • 匹配域名 / 路径用 字符串(前缀、后缀等);

  • 复杂格式验证用 正则表达式

  • 二进制协议处理用 十六进制块

4.1.6 ACL配置示例:

5、自定义 HAProxy 错误页面

在 HAProxy 中自定义错误界面主要是为了提升用户体验、增强系统专业性和安全性,同时便于问题排查。

使用errorfileerrorloc指令的两种方法,可以实现自定义各种错误页面。

# 下图是haproxy默认使用的错误页面

首先,暂停所有后端服务器的nginx服务器服务,让后端服务器全部宕机。

下图为当后端服务器全部宕机后客户端访问172.25.254.100访问到的默认错误页面。

5.1 基于自定义的错误页面文件

# 自定义错误页
语法:errorfile        <code>        <file>
<code>        #HTTP status code,支持 200,400,403,405,408,425,429,500,502 503,504
<file>          #包含完整 HTTP 响应头的错误页文件的绝对路径。建议后缀 ".http" ,以和一般的 html 文件相区分
#示例: errorfile        503        /haproxy/errorpages/503page.http

注意要编写完自定义错误页面才能重启haproxy服务,不然会因为文件不存在而报错!!!

然后用浏览器访问172.25.254.100就会访问到我们自定义的错误页面。

5.2 基于http重定向错误页面 

# 错误页面重定向
语法:errorloc        <code>        <url>
#相当于errorloc        302        <code>        <url>,利用302重定向至指 URL
#示例: errorloc        503        https://www.baidu.com

重启haproxy服务后,然后访问172.25.254.100,就会被重定向到百度中。

6、HAProxy 的四层负载

HAProxy的四层负载主要针对除了HTTP以外的TCP协议应用服务访问的应用场景。

例如:

        1、MySQL
        2、Redis
        3、Memcache
        4、RabbitMQ

四层负载示例:

对 MySQL服务实现四层负载 

首先,在后端服务器上安装和配置mariadb服务。

然后再修改MariaDB数据库的核心配置文件 /etc/my.cnf.d/mariadb-server.cnf 。

修改完文件后要重启服务。

haproxy中要进行以下配置:

设置完要重启服务以此让设置生效。

如果不使用下图的listen mysql_port块,也可以使用frontend和backend实现,将listen mysql_port块的内容改为下面的内容即可。

frontend mysql_port
    bind    *:3306
    mode    tcp
    use_backend    mysql_rs

backend mysql_rs
    mode    tcp
    balance roundrobin
    server mysql1 172.25.254.10:3306 check inter 3 fall 3 rise 5
    server mysql2 172.25.254.20:3306 check inter 3 fall 3 rise 5

下图的命令是用于创建一个名为 lee 的用户,并授予该用户对所有数据库和表的完全权限(ALL PRIVILEGES)。

实验测试:

客户端也要安装mariadb,不然客户端没有mysql这个命令,无法使用。

下图中可以看到完成了对mysql的负载均衡。

7、HAProxy https 实现

haproxy可以实现https的证书安全,从用户到haproxyhttps,haproxy到后端服务器用http通信。

但基于性能考虑,生产中证书都是在后端服务器比如nginx上实现。

#配置HAProxy支持https协议,支持ssl会话;

语法:        bind        *:443        ssl        crt        /PATH/TO/SOME_PEM_FILE

#指令crt后证书文件为PEM格式,需要同时包含证书和所有私钥

语法:        cat        demo.key        demo.crt > demo.pem

#80端口的请求重定向到443端口,443是https的默认端口

语法:        bind        *:80

                   redirect        scheme        https        if         !{ ssl_fc }

7.1 证书制作

7.2 https配置示例

执行的操作:
cat timinglee.org.key timinglee.org.crt > timinglee.pem

解释:

  1. 在HAProxy配置中,绑定443端口时使用了SSL证书,指定了证书文件路径为/etc/haproxy/certs/timinglee.pem

  2. HAProxy要求SSL证书文件必须是PEM格式,并且通常需要将私钥(.key)和证书(.crt)合并到同一个文件中。

  3. 执行的操作是将私钥文件timinglee.org.key和证书文件timinglee.org.crt合并为一个文件timinglee.pem

下图为haproxy负载均衡器的配置

最后进行访问测试:

能成功就说明配置生效了。


网站公告

今日签到

点亮在社区的每一天
去签到