HAProxy ACL规则实战:动态路由与流量分发

 互联网   2026-02-26 11:04   39 人阅读  0 条评论
HAProxy ACL规则实战:动态路由与流量分发  第1张


HAProxy ACL规则实战:动态路由与流量分发

一、概述

1.1 背景介绍

ACL(Access Control List)是HAProxy最强大的功能之一,不仅仅是访问控制,更是实现复杂流量调度的核心武器。在微服务架构和多租户场景下,我们经常需要根据请求的各种特征(域名、路径、Header、Cookie、IP等)把流量路由到不同的后端。

我接触HAProxy ACL是在2018年,当时需要做一个API网关,要实现:不同域名走不同后端、同一域名不同路径走不同服务、还要支持灰度发布。当时觉得用Nginx的location和if语句太费劲,朋友推荐了HAProxy的ACL,用了之后就再也离不开了。

HAProxy ACL的表达能力非常强,正则匹配、IP段匹配、请求头匹配、Cookie匹配都支持,而且可以组合使用。配合use_backend指令,可以实现非常灵活的路由策略。


1.2 技术特点

HAProxy ACL的几个核心特点:

声明式规则:ACL是声明式的,先定义条件,再使用条件。代码可读性比if-else好得多。

丰富的匹配方式:支持字符串精确匹配、前缀匹配、后缀匹配、正则匹配、IP段匹配等。

灵活的取值方法:可以从请求的任何部分取值——URL、Header、Cookie、Query参数、POST数据等。

条件组合:支持AND、OR、NOT组合多个ACL条件。

运行时更新:通过Runtime API可以动态更新ACL规则,不需要reload配置。

1.3 适用场景

场景
说明
ACL条件示例
多域名路由
不同域名路由到不同后端
hdr(host) -i api.company.com
路径路由
不同URL路径路由到不同服务
path_beg /api/v1/users
灰度发布
按比例或按特征分流
hdr(X-Gray) -i true
A/B测试
按用户特征分流
cook(user_group) -i group_a
蓝绿部署
新旧版本切换
hdr(X-Version) -i v2
IP白名单
限制访问来源
src 192.168.0.0/16
请求限流
按条件限流
src_http_req_rate() gt 100
维护模式
特定条件展示维护页
nbsrv(backend) lt 1

1.4 环境要求

组件
版本
说明
HAProxy
3.0.5+
推荐使用最新稳定版
操作系统
Rocky Linux 9.4 / Ubuntu 24.04 LTS

socat
1.7.4+
用于Runtime API通信

二、详细步骤

2.1 准备工作

2.1.1 ACL基础语法

HAProxy ACL的基本语法:

acl <名称> <条件> [标志] [匹配值]

条件(Fetch):从请求中提取数据标志(Flag):修改匹配行为匹配值(Pattern):要匹配的值

常用条件(Fetch):

# 请求相关
path           # URL路径(不含查询参数)
path_beg       # 路径前缀
path_end       # 路径后缀
path_sub       # 路径包含
path_reg       # 路径正则
url            # 完整URL
url_param      # URL参数

# Header相关
hdr(name)      # 指定请求头
hdr_beg(name)  # 请求头前缀
hdr_end(name)  # 请求头后缀
hdr_sub(name)  # 请求头包含
hdr_reg(name)  # 请求头正则

# Cookie相关
cook(name)     # 指定Cookie值
cook_sub(name) # Cookie包含

# 来源相关
src            # 客户端IP
src_port       # 客户端端口

# 后端相关
nbsrv(backend) # 后端可用服务器数量

# SSL相关
ssl_fc         # 是否SSL连接
ssl_fc_sni     # SNI主机名

# 方法相关
method         # HTTP方法(GET/POST等)

# 其他
always_true    # 永真
always_false   # 永假

常用标志(Flag):

-i    # 忽略大小写
-f    # 从文件读取匹配值
-m    # 指定匹配方法
      # -m str  字符串匹配
      # -m beg  前缀匹配
      # -m end  后缀匹配
      # -m sub  包含匹配
      # -m reg  正则匹配
      # -m found  存在即匹配
      # -m len  长度匹配

2.1.2 ACL使用方式

定义好ACL后,可以在以下指令中使用:

# 路由选择
use_backend <backend> if <acl>
use_backend <backend> unless <acl>
default_backend <backend>

# 请求处理
http-request deny if <acl>
http-request allow if <acl>
http-request redirect location <url> if <acl>
http-request set-header <name> <value> if <acl>
http-request add-header <name> <value> if <acl>
http-request del-header <name> if <acl>
http-request replace-path <regex> <replacement> if <acl>

# 响应处理
http-response set-header <name> <value> if <acl>

# 连接处理
tcp-request connection reject if <acl>
tcp-request content reject if <acl>

2.2 核心配置

2.2.1 多域名路由

这是最常见的场景——不同域名路由到不同后端:

# /etc/haproxy/haproxy.cfg
# 多域名路由配置

global
    log /dev/log local0
    user haproxy
    group haproxy
    daemon
    maxconn 50000
    stats socket /run/haproxy/admin.sock mode 660 level admin

defaults
    mode http
    log global
    timeout connect 5s
    timeout client 30s
    timeout server 30s
    option httplog
    option forwardfor

# 前端:统一接收所有请求
frontend http_front
    bind *:80
    bind *:443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1

    # 定义域名ACL
    acl host_api hdr(host) -i api.company.com
    acl host_web hdr(host) -i www.company.com
    acl host_admin hdr(host) -i admin.company.com
    acl host_static hdr(host) -i static.company.com cdn.company.com

    # 支持带端口的Host头
    acl host_api_port hdr_beg(host) -i api.company.com:
    acl host_web_port hdr_beg(host) -i www.company.com:

    # 路由规则
    use_backend api_servers if host_api or host_api_port
    use_backend web_servers if host_web or host_web_port
    use_backend admin_servers if host_admin
    use_backend static_servers if host_static

    # 默认后端
    default_backend web_servers

# API后端
backend api_servers
    balance roundrobin
    option httpchk GET /health
    http-check expect status 200
    server api1 192.168.1.11:8080 check
    server api2 192.168.1.12:8080 check

# Web后端
backend web_servers
    balance roundrobin
    option httpchk GET /health
    server web1 192.168.1.21:8080 check
    server web2 192.168.1.22:8080 check

# Admin后端
backend admin_servers
    balance roundrobin
    # Admin只允许内网访问
    acl internal_network src 192.168.0.0/16 10.0.0.0/8
    http-request deny unless internal_network
    server admin1 192.168.1.31:8080 check

# 静态资源后端
backend static_servers
    balance roundrobin
    # 静态资源启用缓存
    http-response set-header Cache-Control "public, max-age=86400"
    server static1 192.168.1.41:80 check
    server static2 192.168.1.42:80 check

2.2.2 路径路由

根据URL路径路由到不同后端,微服务网关必备:

# 路径路由配置
frontend http_front
    bind *:80

    # 路径ACL - 注意优先级:更具体的规则放前面
    acl path_api_users path_beg /api/v1/users
    acl path_api_orders path_beg /api/v1/orders
    acl path_api_products path_beg /api/v1/products
    acl path_api path_beg /api/
    acl path_static path_beg /static/ /assets/ /images/
    acl path_ws path_beg /ws/ /websocket/
    acl path_health path -i /health /healthz /ready

    # 静态文件扩展名
    acl is_static_file path_end .js .css .png .jpg .gif .ico .woff .woff2

    # WebSocket升级
    acl is_websocket hdr(Upgrade) -i websocket

    # 路由规则
    use_backend ws_servers if path_ws or is_websocket
    use_backend user_service if path_api_users
    use_backend order_service if path_api_orders
    use_backend product_service if path_api_products
    use_backend api_gateway if path_api
    use_backend static_servers if path_static or is_static_file

    # 健康检查直接返回
    http-request return status 200 content-type "text/plain" string "OK"if path_health

    default_backend web_servers

# WebSocket后端
backend ws_servers
    balance source# 同一客户端保持连接到同一后端
    option http-server-close
    # WebSocket需要更长的超时
    timeout server 1h
    timeout tunnel 1h
    server ws1 192.168.1.51:8080 check
    server ws2 192.168.1.52:8080 check

# 用户服务
backend user_service
    balance roundrobin
    server user1 192.168.1.61:8080 check
    server user2 192.168.1.62:8080 check

# 订单服务
backend order_service
    balance roundrobin
    server order1 192.168.1.71:8080 check
    server order2 192.168.1.72:8080 check

# 商品服务
backend product_service
    balance roundrobin
    server product1 192.168.1.81:8080 check
    server product2 192.168.1.82:8080 check

2.2.3 Header路由

根据请求头路由,常用于灰度发布、版本控制:

# Header路由配置
frontend http_front
    bind *:80

    # 灰度标记ACL
    acl gray_header hdr(X-Gray-Release) -i true
    acl gray_cookie cook(gray) -i 1
    acl gray_user hdr_sub(X-User-ID) gray_

    # 版本控制ACL
    acl version_v2 hdr(X-API-Version) -i v2 2.0
    acl version_v3 hdr(X-API-Version) -i v3 3.0

    # 客户端类型ACL
    acl is_mobile hdr_sub(User-Agent) -i mobile android iphone
    acl is_bot hdr_sub(User-Agent) -i bot spider crawler

    # 内部请求ACL(来自其他服务)
    acl is_internal hdr(X-Internal-Request) -i true

    # 优先级用户ACL
    acl is_vip hdr(X-User-Level) -i vip premium

    # 路由规则
    # 灰度用户走灰度环境
    use_backend gray_servers if gray_header or gray_cookie or gray_user

    # 不同API版本走不同后端
    use_backend api_v2 if version_v2
    use_backend api_v3 if version_v3

    # 移动端专属后端(可能有特殊优化)
    use_backend mobile_servers if is_mobile

    # VIP用户走高优先级后端
    use_backend vip_servers if is_vip

    # 爬虫限制
    http-request deny if is_bot

    default_backend api_v1

# 灰度后端
backend gray_servers
    balance roundrobin
    server gray1 192.168.10.11:8080 check
    server gray2 192.168.10.12:8080 check

# API V2后端
backend api_v2
    balance roundrobin
    server api_v2_1 192.168.11.11:8080 check
    server api_v2_2 192.168.11.12:8080 check

# API V3后端
backend api_v3
    balance roundrobin
    server api_v3_1 192.168.12.11:8080 check
    server api_v3_2 192.168.12.12:8080 check

# VIP专属后端
backend vip_servers
    balance roundrobin
    # 更多资源,更高权重
    server vip1 192.168.20.11:8080 check weight 100
    server vip2 192.168.20.12:8080 check weight 100

2.2.4 流量分发(灰度/A/B测试)

按比例分发流量,实现灰度发布和A/B测试

# 流量分发配置
frontend http_front
    bind *:80

    # 方法1:使用随机数实现按比例分流
    # rand(100) 生成0-99的随机数
    acl is_canary rand(100) lt 10  # 10%流量

    # 方法2:基于请求头的Hash分流
    # 使用用户ID的hash值确保同一用户始终走同一版本
    acl canary_by_hash req.hdr(X-User-ID),crc32,mod(100) lt 10

    # 方法3:基于Cookie分流(手动设置灰度标记)
    acl canary_by_cookie cook(canary_group) -i true

    # 方法4:基于IP段分流(内部测试)
    acl canary_by_ip src 192.168.100.0/24

    # 组合条件:任一条件满足即走灰度
    use_backend canary_servers if canary_by_cookie
    use_backend canary_servers if canary_by_ip
    use_backend canary_servers if canary_by_hash

    default_backend stable_servers

# 稳定版后端
backend stable_servers
    balance roundrobin
    option httpchk GET /health
    server stable1 192.168.1.11:8080 check
    server stable2 192.168.1.12:8080 check
    server stable3 192.168.1.13:8080 check

# 灰度版后端
backend canary_servers
    balance roundrobin
    option httpchk GET /health
    # 灰度环境资源较少
    server canary1 192.168.2.11:8080 check
    server canary2 192.168.2.12:8080 check

动态调整灰度比例(不需要reload):

#!/bin/bash
# adjust_canary_ratio.sh
# 动态调整灰度比例

SOCKET="/run/haproxy/admin.sock"

# 获取当前配置
get_current_ratio() {
    echo"show acl #0" | socat stdio $SOCKET
}

# 设置灰度比例(需要使用map方式)
# 这种方式需要在配置中使用map文件
set_canary_ratio() {
    local ratio=$1
    echo"set map /etc/haproxy/canary_ratio.map default $ratio" | socat stdio $SOCKET
}

# 实际生产中更推荐使用server权重调整
# 通过调整各后端的权重来实现流量比例控制
adjust_by_weight() {
    local canary_percent=$1
    local stable_percent=$((100 - canary_percent))

    echo"设置灰度比例: ${canary_percent}%"

    # 调整稳定版后端权重
    echo"set server stable_servers/stable1 weight $stable_percent" | socat stdio $SOCKET
    echo"set server stable_servers/stable2 weight $stable_percent" | socat stdio $SOCKET

    # 调整灰度版后端权重
    echo"set server canary_servers/canary1 weight $canary_percent" | socat stdio $SOCKET
    echo"set server canary_servers/canary2 weight $canary_percent" | socat stdio $SOCKET
}

# 使用示例
case"$1"in
    get)
        get_current_ratio
        ;;
    set)
        adjust_by_weight $2
        ;;
    *)
        echo"用法: $0 {get|set <percent>}"
        echo"示例: $0 set 20  # 设置20%灰度流量"
        ;;
esac

更灵活的基于map的灰度配置:

# /etc/haproxy/haproxy.cfg
# 基于map文件的灰度配置

frontend http_front
    bind *:80

    # 使用map文件存储灰度配置
    # map文件格式:key value
    # 可以运行时更新

    # 根据用户ID查map决定路由
    # 如果在map中找到用户ID,值为canary则走灰度
    http-request set-var(req.user_id) hdr(X-User-ID)
    http-request set-var(req.canary) var(req.user_id),map(/etc/haproxy/maps/user_canary.map,stable)

    acl is_canary var(req.canary) -m str canary

    use_backend canary_servers if is_canary
    default_backend stable_servers

Map文件:

# /etc/haproxy/maps/user_canary.map
# 格式:用户ID 路由目标
# 可以运行时用 set map 命令更新

user_001 canary
user_002 canary
user_003 canary
# ... 更多灰度用户

运行时更新map:

# 添加灰度用户
echo "add map /etc/haproxy/maps/user_canary.map user_004 canary" | \
    socat stdio /run/haproxy/admin.sock

# 移除灰度用户
echo "del map /etc/haproxy/maps/user_canary.map user_001" | \
    socat stdio /run/haproxy/admin.sock

# 查看map内容
echo "show map /etc/haproxy/maps/user_canary.map" | \
    socat stdio /run/haproxy/admin.sock

2.3 启动和验证

2.3.1 配置验证

#!/bin/bash
# verify_acl_config.sh
# ACL配置验证脚本

CONFIG_FILE="/etc/haproxy/haproxy.cfg"
SOCKET="/run/haproxy/admin.sock"

echo"=== HAProxy ACL配置验证 ==="

# 1. 语法检查
echo"[1] 检查配置语法..."
if haproxy -c -f $CONFIG_FILEthen
    echo"    配置语法正确"
else
    echo"    配置语法错误!"
    exit 1
fi

# 2. 检查ACL定义
echo""
echo"[2] 已定义的ACL:"
grep -E "^\s*acl\s+"$CONFIG_FILE | awk '{print "    " $2 " -> " $3}'

# 3. 检查路由规则
echo""
echo"[3] 路由规则:"
grep -E "^\s*(use_backend|default_backend)"$CONFIG_FILE | \
    sed 's/^[ \t]*/    /'

# 4. 检查运行状态
echo""
echo"[4] 运行时ACL状态:"
if [ -S "$SOCKET" ]; then
    echo"show acl" | socat stdio $SOCKET | head -20
else
    echo"    HAProxy socket不可用,跳过运行时检查"
fi

# 5. 检查map文件
echo""
echo"[5] Map文件检查:"
for map_file in /etc/haproxy/maps/*.map; do
    if [ -f "$map_file" ]; then
        entries=$(wc -l < "$map_file")
        echo"    $map_file$entries 条记录"
    fi
done

2.3.2 路由测试

#!/bin/bash
# test_acl_routing.sh
# ACL路由规则测试脚本

BASE_URL="http://127.0.0.1"

echo"=== ACL路由测试 ==="

# 测试函数
test_route() {
    local description=$1
    local curl_args=$2
    local expected=$3

    echo -n "测试: $description ... "

    response=$(curl -s -o /dev/null -w "%{http_code}"$curl_args"$BASE_URL/" 2>/dev/null)

    if [ "$response" == "$expected" ]; then
        echo"PASS (HTTP $response)"
    else
        echo"FAIL (期望 $expected, 实际 $response)"
    fi
}

# 测试域名路由
echo""
echo"--- 域名路由测试 ---"
test_route "api.company.com""-H 'Host: api.company.com'""200"
test_route "www.company.com""-H 'Host: www.company.com'""200"
test_route "unknown.company.com""-H 'Host: unknown.company.com'""200"# 走默认后端

# 测试路径路由
echo""
echo"--- 路径路由测试 ---"
test_route "/api/v1/users""-H 'Host: api.company.com' -X GET""200"
test_route "/api/v1/orders""-H 'Host: api.company.com' -X GET""200"
test_route "/static/logo.png""-H 'Host: www.company.com'""200"

# 测试Header路由
echo""
echo"--- Header路由测试 ---"
test_route "灰度标记""-H 'Host: api.company.com' -H 'X-Gray-Release: true'""200"
test_route "API版本V2""-H 'Host: api.company.com' -H 'X-API-Version: v2'""200"
test_route "VIP用户""-H 'Host: api.company.com' -H 'X-User-Level: vip'""200"

# 测试IP限制
echo""
echo"--- IP限制测试 ---"
# 这个测试需要从不同IP发起,这里只是示例
# test_route "内网访问Admin" "-H 'Host: admin.company.com'" "200"

# 详细测试(查看实际路由到哪个后端)
echo""
echo"--- 详细路由信息 ---"
echo"测试请求详情:"
curl -v -s -o /dev/null \
    -H "Host: api.company.com" \
    -H "X-Gray-Release: true" \
    "$BASE_URL/api/v1/users" 2>&1 | grep -E "< |> " | head -20

三、示例代码和配置

3.1 完整配置示例

3.1.1 企业级API网关配置

这是一个完整的企业级API网关配置,包含了常用的ACL场景:

# /etc/haproxy/haproxy.cfg
# 企业级API网关配置 - HAProxy 3.0

#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
    log /dev/log local0 info
    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

    # 性能优化
    maxconn 100000
    nbthread 4

    # SSL优化
    ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
    tune.ssl.default-dh-param 2048

#---------------------------------------------------------------------
# Default settings
#---------------------------------------------------------------------
defaults
    mode http
    log global
    option httplog
    option dontlognull
    option http-server-close
    option forwardfor except 127.0.0.0/8
    option redispatch

    retries 3
    timeout http-request 10s
    timeout queue 30s
    timeout connect 5s
    timeout client 30s
    timeout server 30s
    timeout http-keep-alive 10s
    timeout check 5s

    # 错误页面
    errorfile 400 /etc/haproxy/errors/400.http
    errorfile 403 /etc/haproxy/errors/403.http
    errorfile 408 /etc/haproxy/errors/408.http
    errorfile 500 /etc/haproxy/errors/500.http
    errorfile 502 /etc/haproxy/errors/502.http
    errorfile 503 /etc/haproxy/errors/503.http
    errorfile 504 /etc/haproxy/errors/504.http

#---------------------------------------------------------------------
# Stats frontend
#---------------------------------------------------------------------
frontend stats
    bind *:8404
    mode http
    stats enable
    stats uri /stats
    stats refresh 10s
    stats admin if TRUE
    stats show-legends

#---------------------------------------------------------------------
# Main HTTP/HTTPS frontend
#---------------------------------------------------------------------
frontend http_front
    bind *:80
    bind *:443 ssl crt /etc/haproxy/certs/company.pem alpn h2,http/1.1

    # ===== 通用ACL定义 =====

    # 请求方法
    acl is_get method GET
    acl is_post method POST
    acl is_options method OPTIONS

    # SSL检测
    acl is_https ssl_fc

    # ===== 安全相关ACL =====

    # 内网IP
    acl internal_network src 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16

    # 黑名单IP(从文件读取)
    acl blocked_ips src -f /etc/haproxy/blacklist.ips

    # 恶意User-Agent
    acl bad_bots hdr_sub(User-Agent) -i -f /etc/haproxy/bad_bots.txt

    # SQL注入检测(基础)
    acl sql_injection url_sub -i select union insert drop delete update

    # XSS检测(基础)
    acl xss_attack url_sub -i <script javascript:

    # ===== 域名路由ACL =====

    acl host_api hdr(host) -i api.company.com
    acl host_web hdr(host) -i www.company.com company.com
    acl host_admin hdr(host) -i admin.company.com
    acl host_ws hdr(host) -i ws.company.com
    acl host_static hdr(host) -i static.company.com cdn.company.com

    # ===== 路径路由ACL =====

    # API版本路由
    acl path_api_v1 path_beg /api/v1/
    acl path_api_v2 path_beg /api/v2/
    acl path_api_v3 path_beg /api/v3/

    # 微服务路由
    acl path_user_service path_beg /api/v1/users /api/v2/users
    acl path_order_service path_beg /api/v1/orders /api/v2/orders
    acl path_product_service path_beg /api/v1/products /api/v2/products
    acl path_payment_service path_beg /api/v1/payments
    acl path_notification_service path_beg /api/v1/notifications

    # 特殊路径
    acl path_health path -i /health /healthz /ready /live
    acl path_metrics path -i /metrics /prometheus
    acl path_swagger path_beg /swagger /api-docs

    # 静态资源
    acl path_static path_beg /static/ /assets/ /public/
    acl is_static_file path_end .js .css .png .jpg .jpeg .gif .ico .svg .woff .woff2 .ttf .eot

    # WebSocket
    acl path_websocket path_beg /ws/ /websocket/ /socket.io/
    acl is_websocket hdr(Upgrade) -i websocket

    # ===== 灰度发布ACL =====

    # Header标记
    acl canary_header hdr(X-Canary) -i true
    acl canary_header_v2 hdr(X-API-Version) -i canary beta

    # Cookie标记
    acl canary_cookie cook(canary) -i true 1

    # 用户ID Hash(10%灰度)
    acl canary_by_hash req.hdr(X-User-ID),crc32,mod(100) lt 10

    # 特定用户ID(从map读取)
    http-request set-var(req.user_id) hdr(X-User-ID)
    acl canary_user var(req.user_id),map(/etc/haproxy/maps/canary_users.map,stable) -m str canary

    # ===== 流量控制ACL =====

    # 请求频率限制
    acl rate_limit_exceeded src_http_req_rate(rate_limit_table) gt 100

    # VIP用户(不限速)
    acl is_vip hdr(X-User-Level) -i vip premium enterprise

    # ===== 安全处理 =====

    # 拒绝黑名单IP
    http-request deny deny_status 403 if blocked_ips

    # 拒绝恶意爬虫
    http-request deny deny_status 403 if bad_bots

    # 拒绝SQL注入
    http-request deny deny_status 400 if sql_injection

    # 拒绝XSS攻击
    http-request deny deny_status 400 if xss_attack

    # HTTP重定向到HTTPS(非内网)
    http-request redirect scheme https code 301 unless is_https or internal_network

    # ===== 请求头处理 =====

    # 添加请求ID
    http-request set-header X-Request-ID %[uuid()]

    # 添加真实IP
    http-request set-header X-Real-IP %[src]

    # 删除敏感头
    http-request del-header X-Forwarded-For
    http-request add-header X-Forwarded-For %[src]

    # 添加灰度标记(用于追踪)
    http-request set-header X-Canary-Flag trueif canary_header or canary_cookie or canary_user

    # ===== CORS处理 =====

    # 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, X-Requested-With, X-User-ID" \
        hdr Access-Control-Max-Age "86400" \
        if is_options

    # ===== 路由规则(按优先级排列) =====

    # 健康检查(直接返回)
    http-request return status 200 content-type "application/json" \
        string "{\"status\":\"ok\",\"timestamp\":\"%[date]\"}"if path_health

    # 指标接口(仅内网)
    http-request deny deny_status 403 if path_metrics !internal_network
    use_backend metrics_servers if path_metrics

    # WebSocket
    use_backend ws_servers if is_websocket or path_websocket

    # 静态资源
    use_backend static_servers if host_static or path_static or is_static_file

    # Admin后台(仅内网)
    http-request deny deny_status 403 if host_admin !internal_network
    use_backend admin_servers if host_admin

    # 灰度流量
    use_backend canary_user_service if path_user_service canary_header
    use_backend canary_user_service if path_user_service canary_cookie
    use_backend canary_user_service if path_user_service canary_user

    # 微服务路由(正常流量)
    use_backend user_service if path_user_service
    use_backend order_service if path_order_service
    use_backend product_service if path_product_service
    use_backend payment_service if path_payment_service
    use_backend notification_service if path_notification_service

    # API版本路由
    use_backend api_v3 if path_api_v3
    use_backend api_v2 if path_api_v2
    use_backend api_v1 if path_api_v1

    # 域名路由
    use_backend api_gateway if host_api
    use_backend web_servers if host_web

    # 默认后端
    default_backend web_servers

#---------------------------------------------------------------------
# Backend definitions
#---------------------------------------------------------------------

# 流量限制表
backend rate_limit_table
    stick-table type ip size 100k expire 30s store http_req_rate(10s)

# 用户服务
backend user_service
    balance roundrobin
    option httpchk GET /health HTTP/1.1
    http-check send hdr Host localhost
    http-check expect status 200
    default-server inter 3s fall 3 rise 2
    server user1 192.168.10.11:8080 check
    server user2 192.168.10.12:8080 check
    server user3 192.168.10.13:8080 check

# 用户服务(灰度)
backend canary_user_service
    balance roundrobin
    option httpchk GET /health HTTP/1.1
    http-check send hdr Host localhost
    http-check expect status 200
    default-server inter 3s fall 3 rise 2
    server canary_user1 192.168.20.11:8080 check
    server canary_user2 192.168.20.12:8080 check

# 订单服务
backend order_service
    balance roundrobin
    option httpchk GET /health HTTP/1.1
    default-server inter 3s fall 3 rise 2
    server order1 192.168.10.21:8080 check
    server order2 192.168.10.22:8080 check
    server order3 192.168.10.23:8080 check

# 商品服务
backend product_service
    balance roundrobin
    option httpchk GET /health HTTP/1.1
    default-server inter 3s fall 3 rise 2
    server product1 192.168.10.31:8080 check
    server product2 192.168.10.32:8080 check

# 支付服务(更严格的健康检查)
backend payment_service
    balance roundrobin
    option httpchk GET /health HTTP/1.1
    default-server inter 2s fall 2 rise 3
    server payment1 192.168.10.41:8080 check
    server payment2 192.168.10.42:8080 check

# 通知服务
backend notification_service
    balance roundrobin
    option httpchk GET /health HTTP/1.1
    default-server inter 3s fall 3 rise 2
    server notification1 192.168.10.51:8080 check
    server notification2 192.168.10.52:8080 check

# API网关
backend api_gateway
    balance roundrobin
    option httpchk GET /health HTTP/1.1
    default-server inter 3s fall 3 rise 2
    server gateway1 192.168.10.61:8080 check
    server gateway2 192.168.10.62:8080 check

# API V1
backend api_v1
    balance roundrobin
    server api_v1_1 192.168.11.11:8080 check
    server api_v1_2 192.168.11.12:8080 check

# API V2
backend api_v2
    balance roundrobin
    server api_v2_1 192.168.12.11:8080 check
    server api_v2_2 192.168.12.12:8080 check

# API V3
backend api_v3
    balance roundrobin
    server api_v3_1 192.168.13.11:8080 check
    server api_v3_2 192.168.13.12:8080 check

# WebSocket服务
backend ws_servers
    balance source
    option http-server-close
    timeout server 1h
    timeout tunnel 1h
    server ws1 192.168.10.71:8080 check
    server ws2 192.168.10.72:8080 check

# 静态资源服务
backend static_servers
    balance roundrobin
    http-response set-header Cache-Control "public, max-age=31536000"
    server static1 192.168.10.81:80 check
    server static2 192.168.10.82:80 check

# Web服务
backend web_servers
    balance roundrobin
    option httpchk GET /health HTTP/1.1
    default-server inter 3s fall 3 rise 2
    server web1 192.168.10.91:8080 check
    server web2 192.168.10.92:8080 check
    server web3 192.168.10.93:8080 check

# Admin服务
backend admin_servers
    balance roundrobin
    option httpchk GET /health HTTP/1.1
    server admin1 192.168.10.101:8080 check
    server admin2 192.168.10.102:8080 check

# 监控指标服务
backend metrics_servers
    balance roundrobin
    server metrics1 192.168.10.111:9090 check

3.2 实际应用案例

3.2.1 案例一:多租户SaaS平台路由

某SaaS平台需要支持:

  • 每个租户有独立的子域名
  • 大客户有独立的后端集群
  • 支持租户级别的灰度发布
# /etc/haproxy/haproxy.cfg
# 多租户SaaS平台配置

frontend http_front
    bind *:443 ssl crt /etc/haproxy/certs/

    # 从子域名提取租户ID
    # tenant1.saas.company.com -> tenant1
    http-request set-var(req.tenant_id) hdr(host),regsub(\.saas\.company\.com$,,)

    # 从map查询租户路由信息
    # map文件格式:tenant_id backend_name
    http-request set-var(req.tenant_backend) var(req.tenant_id),map(/etc/haproxy/maps/tenant_routing.map,shared_pool)

    # 租户级别灰度
    http-request set-var(req.tenant_canary) var(req.tenant_id),map(/etc/haproxy/maps/tenant_canary.map,stable)
    acl tenant_is_canary var(req.tenant_canary) -m str canary

    # 大客户专属后端
    acl tenant_enterprise var(req.tenant_backend) -m str enterprise_pool_1 enterprise_pool_2

    # 路由规则
    use_backend enterprise_pool_1 if { var(req.tenant_backend) -m str enterprise_pool_1 }
    use_backend enterprise_pool_2 if { var(req.tenant_backend) -m str enterprise_pool_2 }
    use_backend canary_servers if tenant_is_canary
    default_backend shared_pool

# 共享资源池
backend shared_pool
    balance roundrobin
    server shared1 192.168.1.11:8080 check
    server shared2 192.168.1.12:8080 check
    server shared3 192.168.1.13:8080 check
    server shared4 192.168.1.14:8080 check

# 大客户专属池1
backend enterprise_pool_1
    balance roundrobin
    server ent1_1 192.168.2.11:8080 check
    server ent1_2 192.168.2.12:8080 check

# 大客户专属池2
backend enterprise_pool_2
    balance roundrobin
    server ent2_1 192.168.3.11:8080 check
    server ent2_2 192.168.3.12:8080 check

# 灰度测试池
backend canary_servers
    balance roundrobin
    server canary1 192.168.10.11:8080 check
    server canary2 192.168.10.12:8080 check

租户路由map文件:

# /etc/haproxy/maps/tenant_routing.map
# 租户ID -> 后端池

# 大客户使用专属池
bigcorp enterprise_pool_1
megacorp enterprise_pool_1
hugecompany enterprise_pool_2

# 其他租户使用共享池(默认值已在配置中设定)
# tenant1 shared_pool  # 可以省略

租户灰度map文件:

# /etc/haproxy/maps/tenant_canary.map
# 租户ID -> 灰度状态

# 参与灰度测试的租户
testcorp canary
betacorp canary
democorp canary

动态管理租户路由:

#!/bin/bash
# manage_tenant_routing.sh
# 租户路由管理脚本

SOCKET="/run/haproxy/admin.sock"
ROUTING_MAP="/etc/haproxy/maps/tenant_routing.map"
CANARY_MAP="/etc/haproxy/maps/tenant_canary.map"

# 添加大客户专属后端
add_enterprise_tenant() {
    local tenant_id=$1
    local pool=$2

    echo"add map $ROUTING_MAP $tenant_id $pool" | socat stdio $SOCKET
    echo"已添加租户 $tenant_id 到 $pool"
}

# 设置租户灰度
set_tenant_canary() {
    local tenant_id=$1
    local status=$2# canary 或 stable

    echo"set map $CANARY_MAP $tenant_id $status" | socat stdio $SOCKET
    echo"已设置租户 $tenant_id 灰度状态为 $status"
}

# 查看租户路由
show_tenant_routing() {
    echo"=== 租户路由配置 ==="
    echo"show map $ROUTING_MAP" | socat stdio $SOCKET

    echo""
    echo"=== 租户灰度配置 ==="
    echo"show map $CANARY_MAP" | socat stdio $SOCKET
}

# 使用示例
case"$1"in
    add)
        add_enterprise_tenant "$2""$3"
        ;;
    canary)
        set_tenant_canary "$2""$3"
        ;;
    show)
        show_tenant_routing
        ;;
    *)
        echo"用法:"
        echo"  $0 add <tenant_id> <pool_name>    # 添加大客户"
        echo"  $0 canary <tenant_id> canary|stable  # 设置灰度"
        echo"  $0 show                            # 查看配置"
        ;;
esac

3.2.2 案例二:蓝绿部署自动切换

实现蓝绿部署的自动化切换:

# /etc/haproxy/haproxy.cfg
# 蓝绿部署配置

frontend http_front
    bind *:80

    # 从map读取当前活跃环境
    http-request set-var(req.active_env) str(default),map(/etc/haproxy/maps/active_env.map,blue)

    # 强制指定环境(用于测试)
    acl force_blue hdr(X-Env) -i blue
    acl force_green hdr(X-Env) -i green

    # 路由规则
    use_backend blue_servers if force_blue
    use_backend green_servers if force_green
    use_backend blue_servers if { var(req.active_env) -m str blue }
    use_backend green_servers if { var(req.active_env) -m str green }

    default_backend blue_servers

# 蓝环境
backend blue_servers
    balance roundrobin
    option httpchk GET /health HTTP/1.1
    default-server inter 3s fall 3 rise 2
    server blue1 192.168.1.11:8080 check
    server blue2 192.168.1.12:8080 check
    server blue3 192.168.1.13:8080 check

# 绿环境
backend green_servers
    balance roundrobin
    option httpchk GET /health HTTP/1.1
    default-server inter 3s fall 3 rise 2
    server green1 192.168.2.11:8080 check
    server green2 192.168.2.12:8080 check
    server green3 192.168.2.13:8080 check

蓝绿切换脚本:

#!/bin/bash
# blue_green_switch.sh
# 蓝绿部署切换脚本

SOCKET="/run/haproxy/admin.sock"
ENV_MAP="/etc/haproxy/maps/active_env.map"

get_current_env() {
    # 从map获取当前环境
    current=$(echo"show map $ENV_MAP" | socat stdio $SOCKET | grep "default" | awk '{print $2}')
    if [ -z "$current" ]; then
        current="blue"
    fi
    echo"$current"
}

check_backend_health() {
    local backend=$1
    local healthy_count=$(echo"show stat" | socat stdio $SOCKET | \
        grep "$backend" | grep "UP" | wc -l)
    echo"$healthy_count"
}

switch_env() {
    local target_env=$1

    echo"=== 蓝绿部署切换 ==="
    echo"目标环境: $target_env"

    # 检查目标环境健康状态
    echo"检查 ${target_env}_servers 健康状态..."
    healthy=$(check_backend_health "${target_env}_servers")

    if [ "$healthy" -lt 2 ]; then
        echo"错误:目标环境健康节点不足 ($healthy < 2),取消切换"
        exit 1
    fi

    echo"健康节点: $healthy"

    # 执行切换
    echo"执行切换..."
    echo"set map $ENV_MAP default $target_env" | socat stdio $SOCKET

    # 验证切换结果
    sleep 1
    current=$(get_current_env)

    if [ "$current" == "$target_env" ]; then
        echo"切换成功!当前活跃环境: $current"

        # 发送通知
        curl -X POST "http://alert-api/webhook" \
            -H "Content-Type: application/json" \
            -d "{\"message\":\"蓝绿部署切换完成,当前环境: $target_env\"}" \
            2>/dev/null

        return 0
    else
        echo"切换失败!当前环境: $current"
        return 1
    fi
}

rollback() {
    local current=$(get_current_env)
    local target

    if [ "$current" == "blue" ]; then
        target="green"
    else
        target="blue"
    fi

    echo"回滚到 $target 环境..."
    switch_env "$target"
}

status() {
    echo"=== 蓝绿部署状态 ==="
    echo"当前活跃环境: $(get_current_env)"
    echo""
    echo"蓝环境状态:"
    echo"show stat" | socat stdio $SOCKET | grep "blue_servers" | \
        awk -F',''{printf "  %s: %s\n", $2, $18}'
    echo""
    echo"绿环境状态:"
    echo"show stat" | socat stdio $SOCKET | grep "green_servers" | \
        awk -F',''{printf "  %s: %s\n", $2, $18}'
}

# 主程序
case"$1"in
    switch)
        if [ -z "$2" ]; then
            echo"用法: $0 switch blue|green"
            exit 1
        fi
        switch_env "$2"
        ;;
    rollback)
        rollback
        ;;
    status)
        status
        ;;
    *)
        echo"蓝绿部署管理工具"
        echo""
        echo"用法:"
        echo"  $0 switch blue|green  # 切换到指定环境"
        echo"  $0 rollback           # 回滚到另一个环境"
        echo"  $0 status             # 查看当前状态"
        ;;
esac

四、最佳实践和注意事项

4.1 最佳实践

4.1.1 ACL命名规范

好的命名让配置更易维护:

# 好的命名示例
acl host_api hdr(host) -i api.company.com          # host_ 前缀表示域名
acl path_user_service path_beg /api/v1/users       # path_ 前缀表示路径
acl is_websocket hdr(Upgrade) -i websocket         # is_ 前缀表示布尔判断
acl has_auth_header hdr(Authorization) -m found    # has_ 前缀表示存在性检查
acl rate_exceeded src_http_req_rate() gt 100       # 描述性名称

# 不好的命名示例
acl a1 hdr(host) -i api.company.com                # 太简短,不知道是什么
acl check path_beg /api/                           # 太宽泛
acl my_acl src 192.168.1.0/24                      # my_ 前缀没有意义

4.1.2 ACL顺序优化

ACL匹配是按顺序的,把最常命中的放前面:

# 优化后的顺序
frontend http_front
    bind *:80

    # 1. 最简单的检查放前面(开销小)
    acl is_options method OPTIONS
    http-request return status 204 if is_options

    # 2. 高频路径放前面
    acl path_api path_beg /api/
    acl path_static path_beg /static/

    # 3. 复杂的正则放后面(开销大)
    acl complex_pattern path_reg ^/api/v[0-9]+/users/[0-9]+$

    # 4. 需要读取body的检查放最后(开销最大)
    acl has_json_body req.body -m sub "json"

4.1.3 使用Map文件管理动态数据

大量动态数据不要写在配置文件里,用map文件管理:

# 配置文件中引用map
frontend http_front
    # 黑名单IP - 从文件读取
    acl blocked_ip src -f /etc/haproxy/blacklist.ips

    # 用户路由 - 从map读取
    http-request set-var(req.user_group) hdr(X-User-ID),map(/etc/haproxy/maps/user_groups.map,default)

# 优点:
# 1. 可以运行时更新,无需reload
# 2. 配置文件更简洁
# 3. 便于自动化管理

4.1.4 避免重复计算

相同的值只提取一次:

# 不好的写法 - 多次提取相同的值
acl is_api_v1 hdr(X-API-Version) -i v1
acl is_api_v2 hdr(X-API-Version) -i v2
acl is_api_v3 hdr(X-API-Version) -i v3
use_backend api_v1 if is_api_v1
use_backend api_v2 if is_api_v2
use_backend api_v3 if is_api_v3

# 好的写法 - 提取一次,多次使用
http-request set-var(req.api_version) hdr(X-API-Version)
use_backend api_v1 if { var(req.api_version) -m str v1 }
use_backend api_v2 if { var(req.api_version) -m str v2 }
use_backend api_v3 if { var(req.api_version) -m str v3 }

# 更好的写法 - 使用map
http-request set-var(req.api_version) hdr(X-API-Version)
http-request set-var(req.target_backend) var(req.api_version),map(/etc/haproxy/maps/api_version_routing.map,api_default)
use_backend %[var(req.target_backend)]

4.2 注意事项

问题
表现
原因
解决方案
ACL不生效
请求没有按预期路由
ACL条件写错或顺序问题
用show acl命令调试
性能下降
响应变慢
复杂正则或大量ACL
优化ACL顺序,使用map
配置reload失败
服务无法启动
语法错误
先用haproxy -c检查
Map更新不生效
动态配置没生效
map文件格式错误
检查map文件格式
内存使用高
HAProxy占用大量内存
stick-table或map太大
设置合理的大小限制
灰度比例不准
实际比例与预期不符
Hash函数选择不当
使用crc32或其他均匀分布的hash

4.2.1 常见ACL错误

# 错误1:忘记-i导致大小写敏感
acl host_api hdr(host) api.company.com      # 不匹配 API.company.com
acl host_api hdr(host) -i api.company.com   # 正确:忽略大小写

# 错误2:路径匹配没考虑结尾
acl path_api path_beg /api                  # 会匹配 /api 和 /api123
acl path_api path_beg /api/                 # 正确:匹配 /api/ 开头

# 错误3:正则没转义
acl match_ip path_reg 192.168.1.1           # 错误:. 匹配任意字符
acl match_ip path_reg 192\.168\.1\.1        # 正确:转义.

# 错误4:Header名称大小写
acl has_auth hdr(x-auth-token) -m found     # 可能不匹配 X-Auth-Token
acl has_auth hdr(X-Auth-Token) -m found     # 推荐:使用标准大小写

# 错误5:逻辑组合错误
use_backend api if is_api !is_admin         # 是AND关系
use_backend api if is_api or !is_admin      # OR需要显式写

五、故障排查和监控

5.1 故障排查

5.1.1 ACL调试命令

#!/bin/bash
# debug_acl.sh
# ACL调试工具

SOCKET="/run/haproxy/admin.sock"

# 查看所有ACL定义
show_acls() {
    echo"=== ACL定义列表 ==="
    echo"show acl" | socat stdio $SOCKET
}

# 测试特定ACL
test_acl() {
    local acl_id=$1
    local test_value=$2

    echo"测试ACL #$acl_id 匹配值: $test_value"
    echo"get acl #$acl_id $test_value" | socat stdio $SOCKET
}

# 查看ACL内容
show_acl_content() {
    local acl_id=$1
    echo"show acl #$acl_id" | socat stdio $SOCKET
}

# 实时查看匹配情况
watch_acl_matches() {
    echo"实时监控ACL匹配(查看HAProxy日志)..."
    # 需要在配置中启用详细日志
    # log global
    # option httplog
    tail -f /var/log/haproxy.log | grep -E "acl|backend"
}

case"$1"in
    list)
        show_acls
        ;;
    test)
        test_acl "$2""$3"
        ;;
    show)
        show_acl_content "$2"
        ;;
    watch)
        watch_acl_matches
        ;;
    *)
        echo"ACL调试工具"
        echo"用法:"
        echo"  $0 list              # 列出所有ACL"
        echo"  $0 test <id> <value> # 测试ACL匹配"
        echo"  $0 show <id>         # 查看ACL内容"
        echo"  $0 watch             # 实时监控匹配"
        ;;
esac

5.1.2 请求追踪

在请求中添加调试信息:

# 在frontend中添加调试header
frontend http_front
    bind *:80

    # 调试模式开关
    acl debug_mode hdr(X-Debug) -i true

    # 记录匹配的ACL到响应头(仅调试模式)
    http-response set-header X-Matched-Host %[hdr(host)] if debug_mode
    http-response set-header X-Matched-Path %[path] if debug_mode
    http-response set-header X-Backend-Name %[be_name] if debug_mode
    http-response set-header X-Server-Name %[srv_name] if debug_mode

测试命令:

# 发送带调试标记的请求
curl -v -H "X-Debug: true" -H "Host: api.company.com" http://localhost/api/v1/users

# 查看响应头中的调试信息
# X-Matched-Host: api.company.com
# X-Matched-Path: /api/v1/users
# X-Backend-Name: user_service
# X-Server-Name: user1

5.2 性能监控

5.2.1 ACL相关指标

# prometheus_acl_rules.yaml
# ACL相关的监控指标

groups:
-name:haproxy_acl_metrics
    rules:
      # 后端请求分布
      -record:haproxy:backend_request_rate
        expr:rate(haproxy_backend_http_requests_total[5m])

      # 各后端请求比例
      -record:haproxy:backend_request_ratio
        expr:|
          haproxy_backend_http_requests_total
          / ignoring(backend) group_left
          sum(haproxy_backend_http_requests_total)

      # 灰度流量比例告警
      -alert:CanaryTrafficRatioAbnormal
        expr:|
          sum(rate(haproxy_backend_http_requests_total{backend="canary_servers"}[5m]))
          / sum(rate(haproxy_backend_http_requests_total{backend=~".*_servers"}[5m]))
          > 0.2
        for:5m
        labels:
          severity:warning
        annotations:
          summary:"灰度流量比例异常"
          description:"灰度流量超过20%,当前: {{ $value | humanizePercentage }}"

5.3 备份与恢复

5.3.1 ACL配置备份

#!/bin/bash
# backup_acl_config.sh
# ACL配置备份脚本

BACKUP_DIR="/data/backups/haproxy_acl"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_PATH="$BACKUP_DIR/$DATE"

mkdir -p "$BACKUP_PATH"

# 备份主配置
cp /etc/haproxy/haproxy.cfg "$BACKUP_PATH/"

# 备份所有map文件
cp -r /etc/haproxy/maps "$BACKUP_PATH/"

# 备份黑白名单
cp /etc/haproxy/*.ips "$BACKUP_PATH/" 2>/dev/null
cp /etc/haproxy/*.txt "$BACKUP_PATH/" 2>/dev/null

# 导出运行时ACL状态
SOCKET="/run/haproxy/admin.sock"
if [ -S "$SOCKET" ]; then
    echo"show acl" | socat stdio $SOCKET > "$BACKUP_PATH/runtime_acls.txt"
    for map in /etc/haproxy/maps/*.map; do
        mapname=$(basename "$map")
        echo"show map $map" | socat stdio $SOCKET > "$BACKUP_PATH/runtime_${mapname}.txt"
    done
fi

# 压缩
cd"$BACKUP_DIR"
tar -czf "${DATE}.tar.gz""$DATE"
rm -rf "$DATE"

echo"备份完成: ${BACKUP_DIR}/${DATE}.tar.gz"

# 清理旧备份(保留30天)
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +30 -delete

六、总结

6.1 技术要点回顾

  1. ACL是HAProxy的核心功能:掌握ACL才能充分发挥HAProxy的能力。

  2. 合理使用Fetch和Flag:了解各种取值方法和匹配标志,选择最合适的组合。

  3. 善用Map文件:动态数据用map管理,支持运行时更新。

  4. 注意性能影响:复杂ACL会影响性能,要优化顺序和减少重复计算。

  5. 做好监控和调试:ACL匹配情况要可观测,方便排查问题。

6.2 进阶学习方向

  • Lua扩展:用Lua脚本实现更复杂的路由逻辑
  • SPOE:Stream Processing Offload Engine,把复杂逻辑卸载到外部服务
  • 服务网格集成:HAProxy作为sidecar proxy的ACL配置
  • 自动化配置:结合服务发现自动生成ACL配置

6.3 参考资料

  • HAProxy Configuration Manual
  • HAProxy ACL Documentation
  • HAProxy Runtime API

附录

A. 命令速查表

操作
命令
查看ACL列表
echo "show acl" | socat stdio /run/haproxy/admin.sock
查看ACL内容
echo "show acl #<id>" | socat stdio /run/haproxy/admin.sock
添加ACL条目
echo "add acl #<id> <value>" | socat stdio /run/haproxy/admin.sock
删除ACL条目
echo "del acl #<id> <value>" | socat stdio /run/haproxy/admin.sock
清空ACL
echo "clear acl #<id>" | socat stdio /run/haproxy/admin.sock
查看Map内容
echo "show map <file>" | socat stdio /run/haproxy/admin.sock
添加Map条目
echo "add map <file> <key> <value>" | socat stdio /run/haproxy/admin.sock
修改Map条目
echo "set map <file> <key> <value>" | socat stdio /run/haproxy/admin.sock
删除Map条目
echo "del map <file> <key>" | socat stdio /run/haproxy/admin.sock

B. 配置参数详解

Fetch方法
说明
示例
hdr(name)
获取请求头
hdr(Host)
path
URL路径
path
path_beg
路径前缀
path_beg /api/
path_end
路径后缀
path_end .html
path_reg
路径正则
path_reg ^/api/v[0-9]+/
url_param(name)
URL参数
url_param(id)
cook(name)
Cookie值
cook(session_id)
src
客户端IP
src
method
HTTP方法
method
标志
说明
示例
-i
忽略大小写
hdr(Host) -i example.com
-f
从文件读取
src -f /etc/haproxy/whitelist.ips
-m str
字符串匹配
path -m str /api/health
-m beg
前缀匹配
path -m beg /api/
-m end
后缀匹配
path -m end .json
-m sub
包含匹配
path -m sub admin
-m reg
正则匹配
path -m reg ^/api/v[0-9]+/
-m found
存在检查
hdr(Authorization) -m found

C. 术语表


术语
英文
解释
ACL
Access Control List
访问控制列表,用于定义匹配条件
Fetch
Fetch Method
从请求中提取数据的方法
Map
Map File
键值对映射文件,支持运行时更新
灰度发布
Canary Release
先让一部分用户使用新版本
蓝绿部署
Blue-Green Deployment
维护两套环境,切换流量
A/B测试
A/B Testing
将用户分组测试不同方案
流量分发
Traffic Splitting
按规则将请求分发到不同后端


(版权归原作者所有,侵删)


免责声明:本文内容来源于网络,所载内容仅供参考。转载仅为学习和交流之目的,如无意中侵犯您的合法权益,请及时联系Docker中文社区!


HAProxy ACL规则实战:动态路由与流量分发  第2张
本文地址:https://www.docker.top/?id=454
温馨提示:文章内容系作者个人观点,不代表Docker中文对观点赞同或支持。
版权声明:本文为转载文章,来源于 互联网 ,版权归原作者所有,欢迎分享本文,转载请保留出处!
NEXT:已经是最新一篇了

 发表评论


表情

还没有留言,还不快点抢沙发?