土法炼钢兴趣小组的算法知识备份

【网络工程】HAProxy 工程:高级配置、ACL 与运维

文章导航

分类入口
network
标签入口
#haproxy#reverse-proxy#load-balancing#acl#high-availability

目录

HAProxy(High Availability Proxy)是一个专注于负载均衡和代理的开源软件。与 Nginx 的”Web 服务器 + 反向代理”定位不同,HAProxy 从第一天就为代理和负载均衡而设计——它不能提供静态文件服务,但在代理场景中提供了 Nginx 不具备的高级功能:Runtime API 动态管理、更细粒度的健康检查、更强大的 ACL 规则引擎。

这篇文章从 HAProxy 的配置模型开始,深入到 ACL 规则、运行时管理和性能调优——帮助你理解什么场景该选 HAProxy 而非 Nginx,以及如何在生产环境中正确运维它。

一、配置模型

1.1 四大配置段

HAProxy 的配置分为四个段(Section),每个段有明确的职责:

┌──────────────────────────────────────────┐
│ global                                   │
│   进程级配置:日志、最大连接数、SSL 引擎  │
└──────────────────────────────────────────┘
┌──────────────────────────────────────────┐
│ defaults                                 │
│   默认参数:超时、重试、日志格式          │
└──────────────────────────────────────────┘
┌──────────────┐     ┌──────────────┐
│ frontend     │     │ backend      │
│ 监听入口     │────▶│ 后端服务器池  │
│ 绑定端口     │     │ 负载均衡策略  │
│ ACL 规则     │     │ 健康检查     │
└──────────────┘     └──────────────┘
┌──────────────────────────────────────────┐
│ listen (= frontend + backend 合体)       │
│   简单场景的快捷配置                      │
└──────────────────────────────────────────┘
# /etc/haproxy/haproxy.cfg — 完整配置示例

global
    log /dev/log local0
    log /dev/log local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin
    stats timeout 30s
    user haproxy
    group haproxy
    daemon
    maxconn 100000
    # SSL 引擎
    ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
    ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
    tune.ssl.default-dh-param 2048

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    option  forwardfor
    option  http-server-close
    timeout connect 5s
    timeout client  30s
    timeout server  30s
    timeout http-keep-alive 10s
    timeout http-request 10s
    retries 3
    errorfile 400 /etc/haproxy/errors/400.http
    errorfile 403 /etc/haproxy/errors/403.http
    errorfile 502 /etc/haproxy/errors/502.http
    errorfile 503 /etc/haproxy/errors/503.http

frontend http_front
    bind *:80
    bind *:443 ssl crt /etc/haproxy/certs/app.pem alpn h2,http/1.1

    # HTTP → HTTPS 重定向
    http-request redirect scheme https unless { ssl_fc }

    # ACL 规则
    acl is_api path_beg /api/
    acl is_static path_end .css .js .png .jpg .gif
    acl is_websocket hdr(Upgrade) -i websocket

    # 路由
    use_backend api_servers if is_api
    use_backend static_servers if is_static
    use_backend ws_servers if is_websocket
    default_backend web_servers

backend web_servers
    balance roundrobin
    option httpchk GET /health
    http-check expect status 200
    server web1 10.0.1.1:8080 check inter 5s fall 3 rise 2
    server web2 10.0.1.2:8080 check inter 5s fall 3 rise 2
    server web3 10.0.1.3:8080 check inter 5s fall 3 rise 2

backend api_servers
    balance leastconn
    option httpchk GET /api/health
    http-check expect status 200
    cookie SERVERID insert indirect nocache httponly secure
    server api1 10.0.2.1:8080 check cookie s1
    server api2 10.0.2.2:8080 check cookie s2

backend static_servers
    balance uri
    server static1 10.0.3.1:8080 check
    server static2 10.0.3.2:8080 check

backend ws_servers
    balance source
    timeout tunnel 3600s       # WebSocket 长连接超时
    server ws1 10.0.4.1:8080 check
    server ws2 10.0.4.2:8080 check

1.2 Frontend vs Listen

# frontend + backend 分离(灵活,适合复杂路由)
frontend http_front
    bind *:80
    use_backend app if { path_beg /app }
    default_backend default

backend app
    server s1 10.0.1.1:8080

# listen(简洁,适合简单场景)
listen mysql_cluster
    bind *:3306
    mode tcp
    balance roundrobin
    option mysql-check user haproxy
    server db1 10.0.5.1:3306 check
    server db2 10.0.5.2:3306 check

listen stats
    bind *:8404
    stats enable
    stats uri /stats
    stats refresh 10s
    stats admin if LOCALHOST

1.3 mode tcp vs mode http

mode tcp (L4):
  - 不解析应用层协议
  - 支持任何 TCP 协议(MySQL、Redis、SMTP...)
  - 性能更高(不需要 HTTP 解析)
  - 无法基于 HTTP 头路由

mode http (L7):
  - 解析 HTTP 协议
  - 支持 URL/Header/Cookie 路由
  - 支持 HTTP 健康检查
  - 支持请求/响应修改
# TCP 模式代理 MySQL
listen mysql
    bind *:3306
    mode tcp
    option mysql-check user haproxy
    balance roundrobin
    server db1 10.0.5.1:3306 check
    server db2 10.0.5.2:3306 check backup

# TCP 模式代理 Redis
listen redis
    bind *:6379
    mode tcp
    option tcp-check
    tcp-check send "PING\r\n"
    tcp-check expect string +PONG
    balance roundrobin
    server redis1 10.0.6.1:6379 check
    server redis2 10.0.6.2:6379 check

二、ACL 规则引擎

2.1 ACL 基础

ACL(Access Control List)是 HAProxy 最强大的功能之一——通过定义条件表达式,实现精细的流量路由和控制:

# ACL 语法
acl <名称> <判断条件> [标志] <值>

# 路径匹配
acl is_api     path_beg /api/          # 路径前缀
acl is_login   path     /login         # 精确路径
acl is_image   path_end .png .jpg .gif # 路径后缀
acl is_assets  path_reg ^/assets/.*\.  # 路径正则

# Header 匹配
acl is_mobile  hdr_sub(User-Agent) -i mobile android iphone
acl is_bot     hdr_sub(User-Agent) -i bot spider crawler
acl is_json    hdr(Content-Type) -i application/json
acl has_auth   hdr(Authorization) -m found

# 源 IP 匹配
acl is_internal src 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
acl is_office   src 203.0.113.0/24
acl is_blocked  src -f /etc/haproxy/blocked_ips.lst

# 方法匹配
acl is_post    method POST
acl is_options method OPTIONS

# SSL/TLS
acl is_ssl     ssl_fc                   # 是否 SSL 连接
acl is_h2      ssl_fc_alpn -i h2        # 是否 HTTP/2

# Cookie 匹配
acl is_beta    cook(canary_group) beta
acl has_session cook(SESSIONID) -m found

# 时间匹配
acl is_peak_hour  date_hour 9 10 11 12 13 14 15 16 17
acl is_weekend    date_wday 0 6

2.2 ACL 组合与路由

frontend http_front
    bind *:80

    # 定义 ACL
    acl is_api        path_beg /api/
    acl is_internal   src 10.0.0.0/8
    acl is_post       method POST
    acl is_admin      path_beg /admin/
    acl is_blocked    src -f /etc/haproxy/blocked.lst
    acl is_beta       cook(canary) beta
    acl rate_exceeded sc0_gpc0_rate() gt 100

    # 安全规则(优先级最高)
    http-request deny if is_blocked
    http-request deny if is_admin !is_internal
    http-request deny if rate_exceeded

    # 路由规则
    use_backend api_canary if is_api is_beta        # API + Beta 用户 → 灰度
    use_backend api_servers if is_api                # API 请求 → API 后端
    use_backend admin_servers if is_admin is_internal # 管理后台 → 仅内网
    default_backend web_servers                      # 默认 → Web 后端

2.3 ACL 与请求改写

frontend http_front
    bind *:80

    # 添加/修改请求头
    http-request set-header X-Forwarded-Proto https if { ssl_fc }
    http-request set-header X-Real-IP %[src]
    http-request set-header X-Request-ID %[unique-id]

    # 根据条件修改请求
    http-request set-path /api/v2%[path] if { path_beg /api/v1 }

    # 添加响应头
    http-response set-header X-Frame-Options SAMEORIGIN
    http-response set-header X-Content-Type-Options nosniff
    http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains"

    # 删除敏感响应头
    http-response del-header Server
    http-response del-header X-Powered-By

    # CORS 处理
    acl is_preflight method OPTIONS
    http-request return status 204 \
        hdr Access-Control-Allow-Origin "*" \
        hdr Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" \
        hdr Access-Control-Allow-Headers "Content-Type, Authorization" \
        hdr Access-Control-Max-Age "86400" \
        if is_preflight

2.4 速率限制

HAProxy 的速率限制通过 Stick Table 实现,比 Nginx 的 limit_req 更灵活:

frontend http_front
    bind *:80

    # 定义 Stick Table(跟踪表)
    stick-table type ip size 100k expire 30s store http_req_rate(10s),conn_cur,gpc0

    # 跟踪源 IP
    http-request track-sc0 src

    # 速率限制规则
    # 10 秒内超过 100 次请求 → 拒绝
    acl rate_abuse sc0_http_req_rate() gt 100
    http-request deny deny_status 429 if rate_abuse

    # 当前并发连接超过 20 → 拒绝
    acl conn_abuse sc0_conn_cur gt 20
    http-request deny deny_status 429 if conn_abuse
# 多维度速率限制
frontend http_front
    bind *:80

    # 表 1: 按源 IP 限制
    stick-table type ip size 100k expire 60s \
        store http_req_rate(10s),conn_cur

    # 表 2: 按 URI 限制
    stick-table type string len 128 size 10k expire 60s \
        store http_req_rate(10s) peers mypeers

    # 跟踪
    http-request track-sc0 src table http_front
    http-request track-sc1 path table http_front_uri

    # 判断
    acl ip_rate_high  sc0_http_req_rate() gt 100
    acl uri_rate_high sc1_http_req_rate() gt 50

    # 限制
    http-request deny deny_status 429 if ip_rate_high
    http-request deny deny_status 429 if uri_rate_high

backend rate_limit_uri
    stick-table type string len 128 size 10k expire 60s store http_req_rate(10s)

三、健康检查

3.1 TCP 健康检查

backend db_servers
    mode tcp
    option tcp-check

    # 简单 TCP 连接检查
    server db1 10.0.5.1:3306 check inter 3s fall 3 rise 2

    # 自定义 TCP 检查序列
    tcp-check connect
    tcp-check send "PING\r\n"
    tcp-check expect string "+PONG"

3.2 HTTP 健康检查

backend api_servers
    mode http

    # 基础 HTTP 检查
    option httpchk GET /health
    http-check expect status 200

    # 高级 HTTP 检查(HAProxy 2.2+)
    option httpchk
    http-check connect
    http-check send meth GET uri /health ver HTTP/1.1 hdr Host app.example.com
    http-check expect status 200
    http-check expect body "\"status\":\"ok\""  # 检查响应体

    server s1 10.0.1.1:8080 check inter 5s fall 3 rise 2
    server s2 10.0.1.2:8080 check inter 5s fall 3 rise 2

3.3 Agent 健康检查

Agent Check 让后端应用主动报告自己的状态——比 HTTP 检查更灵活:

backend app_servers
    server s1 10.0.1.1:8080 check agent-check agent-inter 5s agent-port 8081

    # 后端需要在 8081 端口启动一个 agent
    # agent 返回以下格式之一:
    # "ready"          → 服务正常
    # "drain"          → 排空模式,不接受新连接
    # "maint"          → 维护模式,标记为 DOWN
    # "up"             → 标记为 UP
    # "down"           → 标记为 DOWN
    # "75%"            → 设置权重为最大权重的 75%
    # "maxconn:50"     → 设置最大连接数为 50
#!/usr/bin/env python3
"""HAProxy Agent Check 服务端示例"""

import socket
import os
import psutil

def get_health_status():
    """根据系统状态返回健康信息"""
    cpu_percent = psutil.cpu_percent(interval=0.1)
    memory = psutil.virtual_memory()

    # CPU 过高:降低权重
    if cpu_percent > 90:
        return "drain\n"
    elif cpu_percent > 80:
        return "50%\n"
    elif cpu_percent > 60:
        return "75%\n"

    # 内存不足:进入维护
    if memory.percent > 95:
        return "maint\n"

    # 应用级检查
    if not os.path.exists("/tmp/app_ready"):
        return "drain\n"

    return "ready 100%\n"

def main():
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server.bind(('0.0.0.0', 8081))
    server.listen(5)

    while True:
        conn, addr = server.accept()
        status = get_health_status()
        conn.sendall(status.encode())
        conn.close()

if __name__ == '__main__':
    main()

四、Runtime API

4.1 Socket 管理接口

HAProxy 的 Runtime API 是其最强大的运维功能——通过 Unix Socket 实时查看和修改配置,无需 reload

# 配置 stats socket
# global
#     stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
#     stats socket ipv4@127.0.0.1:9999 level admin

# 使用 socat 连接
echo "show info" | socat stdio /run/haproxy/admin.sock

# 或使用 hatop(交互式终端)
hatop -s /run/haproxy/admin.sock

4.2 服务器管理

# 查看后端状态
echo "show servers state" | socat stdio /run/haproxy/admin.sock

# 将服务器设置为维护模式(不接受新连接,等待现有连接完成)
echo "set server api_servers/s1 state maint" | \
    socat stdio /run/haproxy/admin.sock

# 恢复服务器
echo "set server api_servers/s1 state ready" | \
    socat stdio /run/haproxy/admin.sock

# 排空服务器(优雅下线)
echo "set server api_servers/s1 state drain" | \
    socat stdio /run/haproxy/admin.sock

# 修改服务器权重(不需要 reload)
echo "set server api_servers/s1 weight 50%" | \
    socat stdio /run/haproxy/admin.sock

# 修改服务器地址(动态后端)
echo "set server api_servers/s1 addr 10.0.1.100 port 8080" | \
    socat stdio /run/haproxy/admin.sock

# 修改最大连接数
echo "set server api_servers/s1 maxconn 200" | \
    socat stdio /run/haproxy/admin.sock

4.3 流量管理

# 查看前端流量统计
echo "show stat" | socat stdio /run/haproxy/admin.sock | \
    awk -F',' 'NR==1 || /^http_front/{print $1,$2,$8,$9,$10,$34,$35}'

# 禁用/启用前端
echo "disable frontend http_front" | socat stdio /run/haproxy/admin.sock
echo "enable frontend http_front" | socat stdio /run/haproxy/admin.sock

# 查看当前连接数
echo "show sess" | socat stdio /run/haproxy/admin.sock | head -20

# 查看 Stick Table 内容(限流状态)
echo "show table http_front" | socat stdio /run/haproxy/admin.sock
# table: http_front, type: ip, size: 100000, used: 523
# 0x55a1234: key=10.0.1.55 use=1 exp=25s http_req_rate(10000)=45

# 清除特定 IP 的限流计数
echo "clear table http_front key 10.0.1.55" | \
    socat stdio /run/haproxy/admin.sock

4.4 动态服务器管理

HAProxy 2.4+ 支持通过 Runtime API 动态添加和删除服务器:

# 动态添加服务器
echo "add server api_servers/s4 10.0.2.4:8080 check inter 5s" | \
    socat stdio /run/haproxy/admin.sock

# 启用新服务器
echo "set server api_servers/s4 state ready" | \
    socat stdio /run/haproxy/admin.sock

# 删除服务器(必须先设为 maint 并等待连接排空)
echo "set server api_servers/s4 state maint" | \
    socat stdio /run/haproxy/admin.sock
sleep 30  # 等待现有连接完成
echo "del server api_servers/s4" | \
    socat stdio /run/haproxy/admin.sock
#!/bin/bash
# haproxy_graceful_drain.sh — 优雅下线后端服务器
# 用法: ./haproxy_graceful_drain.sh <backend>/<server> [timeout]

SOCKET="/run/haproxy/admin.sock"
TARGET=$1
TIMEOUT=${2:-60}

echo "=== 开始优雅下线: $TARGET ==="

# Step 1: 进入 drain 模式(停止接受新连接)
echo "set server $TARGET state drain" | socat stdio $SOCKET
echo "$(date): 进入 drain 模式"

# Step 2: 等待现有连接完成
ELAPSED=0
while [ $ELAPSED -lt $TIMEOUT ]; do
    CONN=$(echo "show servers conn $TARGET" | socat stdio $SOCKET 2>/dev/null \
        | awk -F',' '{print $5}' | tail -1)
    echo "$(date): 剩余连接: ${CONN:-0}"

    if [ "${CONN:-0}" = "0" ]; then
        echo "所有连接已完成"
        break
    fi

    sleep 5
    ELAPSED=$((ELAPSED + 5))
done

# Step 3: 进入维护模式
echo "set server $TARGET state maint" | socat stdio $SOCKET
echo "$(date): 已进入维护模式"
echo "=== 下线完成 ==="

五、多线程模型

5.1 HAProxy 的线程演进

HAProxy 早期是纯单进程单线程的——所有连接在一个线程中处理。从 1.8 版本开始支持多线程,2.x 版本多线程逐渐成熟:

HAProxy 1.x:
  单进程 + 单线程 + 事件循环
  性能上限: 单核 CPU

HAProxy 2.x:
  单进程 + 多线程 + 每线程独立事件循环
  性能: 线性扩展到多核

对比 Nginx:
  单 Master + 多 Worker 进程
  进程间通过共享内存通信

HAProxy 的多线程优势:
  - 线程间共享内存空间(Stick Table、Stats 天然共享)
  - 无需进程间通信机制
  - 动态配置更新更简单
# 多线程配置
global
    nbthread 4            # 使用 4 个线程
    cpu-map auto:1/1-4 0-3  # 线程绑定到 CPU 0-3

    # 线程组(HAProxy 2.7+)
    # thread-groups 2
    # thread-group 1 threads 1-2
    # thread-group 2 threads 3-4
# 验证多线程
echo "show threads" | socat stdio /run/haproxy/admin.sock
# Thread 1: id=1, pth_id=..., tid_bit=0x1, ...
# Thread 2: id=2, pth_id=..., tid_bit=0x2, ...
# Thread 3: id=3, pth_id=..., tid_bit=0x4, ...
# Thread 4: id=4, pth_id=..., tid_bit=0x8, ...

# 查看各线程的负载
echo "show activity" | socat stdio /run/haproxy/admin.sock

5.2 Seamless Reload

HAProxy 的 reload 机制与 Nginx 不同。Nginx reload 创建新 Worker 进程、旧 Worker 优雅退出。HAProxy 的 seamless reload 使用 expose-fd listeners 技术:

# 配置 expose-fd listeners
# global
#     stats socket /run/haproxy/admin.sock expose-fd listeners

# Reload 命令
haproxy -f /etc/haproxy/haproxy.cfg -sf $(cat /run/haproxy.pid)
# -sf: 发送 SIGUSR1 给旧进程

# 或使用 systemd
systemctl reload haproxy
Seamless Reload 过程:
1. 新进程启动
2. 新进程通过 Unix Socket 从旧进程接收 listen fd
3. 新进程开始接受新连接
4. 旧进程停止接受新连接
5. 旧进程等待现有连接完成后退出
6. 整个过程不丢失任何连接

六、SSL/TLS 工程

6.1 SSL Termination

# SSL 终止配置
frontend https_front
    bind *:443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1

    # 多证书(SNI 自动选择)
    # 将证书按域名命名放在 /etc/haproxy/certs/ 目录下
    # app.example.com.pem, api.example.com.pem 等
    # HAProxy 自动匹配 SNI

    # SSL 重定向
    http-request redirect scheme https unless { ssl_fc }

    # HSTS
    http-response set-header Strict-Transport-Security \
        "max-age=31536000; includeSubDomains; preload"
# 生成 HAProxy 格式的 PEM 文件(证书 + 私钥合并)
cat server.crt intermediate.crt > /etc/haproxy/certs/app.pem
cat server.key >> /etc/haproxy/certs/app.pem

# 验证 SSL 配置
openssl s_client -connect localhost:443 -servername app.example.com < /dev/null 2>/dev/null \
    | openssl x509 -noout -subject -dates

# 查看 SSL 会话统计
echo "show ssl sess" | socat stdio /run/haproxy/admin.sock

6.2 SSL 性能优化

global
    # OpenSSL 引擎(硬件加速)
    ssl-engine rdrand
    ssl-mode-async

    # SSL 缓存
    tune.ssl.default-dh-param 2048
    tune.ssl.cachesize 100000       # SSL 会话缓存数量
    tune.ssl.lifetime 300           # SSL 会话缓存有效期

    # SSL 内存
    tune.ssl.maxrecord 16384        # SSL 记录大小

frontend https_front
    bind *:443 ssl crt /etc/haproxy/certs/ \
        alpn h2,http/1.1 \
        no-sslv3 no-tlsv10 no-tlsv11

七、监控与故障排查

7.1 Stats 页面

# 内置 Stats 页面
listen stats
    bind *:8404
    stats enable
    stats uri /haproxy?stats
    stats refresh 5s
    stats show-legends
    stats show-node
    stats admin if TRUE              # 允许管理操作
    stats auth admin:password        # 基本认证

7.2 Prometheus 指标导出

# HAProxy 2.0+ 内置 Prometheus Exporter
frontend stats
    bind *:8405
    http-request use-service prometheus-exporter if { path /metrics }
    stats enable
    stats uri /stats
# prometheus.yml
scrape_configs:
  - job_name: 'haproxy'
    scrape_interval: 15s
    static_configs:
      - targets: ['haproxy:8405']
    metrics_path: /metrics
# 常用 Prometheus 告警规则
groups:
  - name: haproxy
    rules:
      - alert: HAProxyBackendDown
        expr: haproxy_backend_active_servers == 0
        for: 30s
        annotations:
          summary: "后端 {{ $labels.proxy }} 无可用服务器"

      - alert: HAProxyHighErrorRate
        expr: |
          rate(haproxy_backend_http_responses_total{code="5xx"}[5m])
          / rate(haproxy_backend_http_responses_total[5m]) > 0.05
        for: 2m
        annotations:
          summary: "后端 {{ $labels.proxy }} 5xx 错误率 > 5%"

      - alert: HAProxyHighLatency
        expr: |
          haproxy_backend_response_time_average_seconds > 2
        for: 5m
        annotations:
          summary: "后端 {{ $labels.proxy }} 平均延迟 > 2s"

      - alert: HAProxyConnectionLimit
        expr: |
          haproxy_process_current_connections
          / haproxy_process_max_connections > 0.8
        for: 5m
        annotations:
          summary: "HAProxy 连接数超过 80%"

7.3 日志分析

# 日志格式配置
defaults
    log global
    option httplog
    # 自定义日志格式
    log-format "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"
# 日志字段含义:
# %ci    客户端 IP
# %cp    客户端端口
# %tr    请求接收时间
# %ft    Frontend 名称
# %b/%s  Backend/Server 名称
# %TR    请求头接收时间
# %Tw    等待队列时间
# %Tc    TCP 连接到后端时间
# %Tr    后端响应时间
# %Ta    总活跃时间
# %ST    HTTP 状态码
# %B     响应字节数
# %tsc   终止状态码

# 常用日志分析命令
# 找出响应最慢的请求
grep -oP '\d+/\d+/\d+/\d+/\d+' /var/log/haproxy.log | \
    awk -F'/' '{print $4}' | sort -n | tail -20

# 统计各后端的请求分布
awk '{print $6}' /var/log/haproxy.log | sort | uniq -c | sort -rn

# 统计状态码分布
awk '{print $10}' /var/log/haproxy.log | sort | uniq -c | sort -rn

# 找出被限流的请求
grep "429" /var/log/haproxy.log | wc -l

7.4 终止状态码

HAProxy 的日志中包含一个两字符的终止状态码(Termination State),是排查连接问题的关键:

状态码 含义 常见原因
-- 正常完成 请求正常处理
CD 客户端主动关闭 客户端超时或取消
SC 服务端关闭 后端关闭连接
sQ 服务端排队超时 后端连接已满
sH 服务端返回错误响应头 后端返回格式错误
PR 代理读取错误 网络问题
PT 代理超时 后端响应太慢

八、总结

  1. HAProxy 的定位是纯代理,Nginx 的定位是 Web 服务器 + 代理。如果你只需要负载均衡和代理,HAProxy 在功能深度上超过 Nginx——更强的 ACL、更灵活的健康检查、更强大的 Runtime API。

  2. Runtime API 是 HAProxy 的杀手级功能。不需要 reload 就能动态调整权重、上下线服务器、清除限流状态。在大规模部署中,这意味着零停机运维。

  3. Stick Table 让限流更精确更灵活。可以基于 IP、URL、Cookie 等多维度做限流,支持自定义计数器。相比 Nginx 的 limit_req,Stick Table 提供了更多的控制能力。

  4. 多线程模型简化了状态共享。HAProxy 的多线程共享内存空间,Stick Table、统计数据等天然在线程间共享,不需要 Nginx 那样的共享内存区域配置。

  5. SSL 终止和 HTTP/2 是现代 HAProxy 的标配。2.x 版本的 SSL 性能和 HTTP/2 支持已经成熟,不再需要在前面放一层 Nginx 做 SSL 终止。


参考文献


上一篇:Nginx 架构深度剖析:事件模型、Worker 与 Upstream

下一篇:Envoy 架构剖析:xDS、Filter Chain 与热重启

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。


By .