欢迎光临
我们一直在努力

架构之HAProxy

架构之HAProxy

目录

  • 简介
  • 架构概览
  • 核心组件
  • 请求处理流程
  • 负载均衡算法
  • 配置结构
  • 性能特征
  • 健康检查机制
  • 会话持久化
  • SSL/TLS 终止
  • 高可用部署
  • 最佳实践
  • 使用场景

  • 简介

    HAProxy(High Availability Proxy)是一个免费、开源、高性能的负载均衡器和代理服务器,适用于基于 TCP 和 HTTP 的应用程序。它将传入流量分发到多个后端服务器,确保高可用性、可靠性和最佳资源利用率。

    核心特性

    • 四层和七层负载均衡:支持 TCP(四层)和 HTTP(七层)负载均衡
    • 高性能:能够以最少的资源使用处理数万个并发连接
    • 零拷贝架构:采用事件驱动的单进程模型以实现最大效率
    • 高级健康检查:支持多种健康检查机制以检测服务器故障
    • 会话持久化:多种保持客户端会话的方法
    • SSL/TLS 终止:将 SSL/TLS 处理从后端服务器卸载
    • 可观测性:全面的指标、日志和统计信息

    历史背景

    HAProxy 由 Willy Tarreau 于 2000 年创建,旨在解决现有负载均衡解决方案的局限性。它已发展成为最广泛使用的负载均衡器之一,为包括 GitHub、Instagram、Stack Overflow 和 Reddit 在内的主要互联网服务提供支持。


    架构概览

    设计理念

    HAProxy 采用单线程、事件驱动架构,通过避免上下文切换和内存复制开销来最大化性能。这种设计选择使其在处理高并发工作负载时效率极高。

    架构图

    ┌─────────────────────────────────────────────────────────────────┐
    │ HAProxy 进程 │
    │ │
    │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
    │ │ 监听器 │ │ 监听器 │ │ 监听器 │ │
    │ │ (前端) │ │ (前端) │ │ (前端) │ │
    │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
    │ │ │ │ │
    │ └─────────────────┼─────────────────┘ │
    │ ▼ │
    │ ┌───────────────┐ │
    │ │ 处理引擎 │ │
    │ │ (事件循环) │ │
    │ └───────┬───────┘ │
    │ │ │
    │ ┌─────────────────┼─────────────────┐ │
    │ ▼ ▼ ▼ │
    │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
    │ │ 后端 │ │ 后端 │ │ 后端 │ │
    │ │ (服务器) │ │ (服务器) │ │ (服务器) │ │
    │ └──────────────┘ └──────────────┘ └──────────────┘ │
    └─────────────────────────────────────────────────────────────────┘

    线程模型

    HAProxy 提供两种线程模型:

    单线程模式(默认)
    • 单个进程处理所有连接
    • 最大性能,最小开销
    • 适用于大多数用例
    • 无需锁定或同步
    多线程模式
    • 多个工作线程共享工作负载
    • 可配置的线程数(nbproc、nbthread)
    • 每个线程有自己的事件循环
    • 无锁数据结构用于线程间通信
    • 跨多个 CPU 核心扩展

    核心组件

    1. 前端(Frontends)

    前端定义 HAProxy 如何监听传入连接并处理请求。

    关键属性:

    • bind:监听的 IP 地址和端口
    • mode:操作模式(tcp、http、health)
    • default_backend:流量路由的默认后端
    • acl:用于条件路由的访问控制列表
    • use_backend:条件后端选择

    示例:

    frontend web_frontend
    bind *:80
    bind *:443 ssl crt /etc/haproxy/certs/
    mode http
    default_backend web_servers

    2. 后端(Backends)

    后端定义处理转发请求的服务器组。

    关键属性:

    • mode:操作模式(tcp、http)
    • balance:负载均衡算法
    • server:后端服务器定义
    • check:健康检查配置
    • cookie:会话持久化设置

    示例:

    backend web_servers
    mode http
    balance roundrobin
    cookie SERVERID insert indirect nocache
    server web1 10.0.0.1:80 check cookie web1
    server web2 10.0.0.2:80 check cookie web2

    3. 服务器(Servers)

    带有健康检查和权重配置的单个后端服务器定义。

    参数:

    • address:port:服务器地址
    • check:启用健康检查
    • weight:服务器权重(默认 1-256)
    • maxconn:最大并发连接数
    • backup:标记为备份服务器
    • rise/fall:健康检查阈值

    4. 监听器(Listeners)

    监听器是 HAProxy 接受连接的实际套接字端点。它们使用 bind 指令在前端中定义。

    5. ACL(访问控制列表)

    ACL 为请求路由和操作提供强大的条件逻辑。

    语法:

    acl <名称> <条件> [标志] <操作符> <值>

    常用条件:

    • path:URL 路径
    • hdr:HTTP 头
    • src:源 IP 地址
    • method:HTTP 方法
    • url_param:URL 参数

    示例:

    acl is_api path_beg /api
    acl is_static path_beg /static
    use_backend api_servers if is_api
    use_backend static_servers if is_static


    请求处理流程

    HTTP 模式处理

    客户端请求


    ┌──────────────┐
    │ 接受 TCP │
    │ 连接 │
    └──────┬───────┘


    ┌──────────────┐
    │ 解析 HTTP │
    │ 请求 │
    └──────┬───────┘


    ┌──────────────┐
    │ 应用 ACL │
    │ 和路由 │
    └──────┬───────┘


    ┌──────────────┐
    │ 选择 │
    │ 后端 │
    └──────┬───────┘


    ┌──────────────┐
    │ 选择 │
    │ 服务器 │
    │ (算法) │
    └──────┬───────┘


    ┌──────────────┐
    │ 转发到 │
    │ 服务器 │
    └──────┬───────┘


    ┌──────────────┐
    │ 接收 │
    │ 响应 │
    └──────┬───────┘


    ┌──────────────┐
    │ 应用 │
    │ 头部 │
    └──────┬───────┘


    客户端响应

    TCP 模式处理

    TCP 模式在四层运行,提供连接级负载均衡,不检查应用数据。

    客户端连接


    ┌──────────────┐
    │ 接受 TCP │
    │ 连接 │
    └──────┬───────┘


    ┌──────────────┐
    │ 应用 ACL │
    │ (IP/端口) │
    └──────┬───────┘


    ┌──────────────┐
    │ 选择 │
    │ 后端 │
    └──────┬───────┘


    ┌──────────────┐
    │ 选择 │
    │ 服务器 │
    └──────┬───────┘


    ┌──────────────┐
    │ 建立 │
    │ TCP 隧道 │
    └──────┬───────┘


    双向数据流


    负载均衡算法

    轮询(roundrobin)

    按顺序将请求分发到服务器。每个服务器获得平等的机会。

    特征:

    • 均匀分布
    • 无连接跟踪
    • 适用于相似的服务器能力

    配置:

    backend servers
    balance roundrobin

    最少连接(leastconn)

    将新连接路由到活动连接最少的服务器。

    特征:

    • 考虑当前负载
    • 适用于不同的请求持续时间
    • 理想用于长连接

    配置:

    backend servers
    balance leastconn

    源 IP 哈希(source)

    哈希客户端的源 IP 以确定服务器。

    特征:

    • 按 IP 进行会话持久化
    • 同一客户端的一致路由
    • 可能导致分布不均

    配置:

    backend servers
    balance source
    hash-type consistent

    URI 哈希(uri)

    哈希请求 URI 以确定服务器。

    特征:

    • 相同 URI 路由到同一服务器
    • 适用于缓存场景
    • 可能导致分布不均

    配置:

    backend servers
    balance uri
    hash-type consistent

    随机(random)

    从可用服务器中随机选择服务器。

    特征:

    • 简单快速
    • 随时间统计分布
    • 无连接跟踪

    配置:

    backend servers
    balance random

    首选(first)

    始终使用第一个可用的服务器。

    特征:

    • 最大缓存命中率
    • 负载分布不均
    • 适用于特定场景

    配置:

    backend servers
    balance first

    算法比较

    算法会话持久化均匀分布使用场景
    轮询 通用
    最少连接 不同的请求持续时间
    源 IP 哈希 需要粘性会话
    URI 哈希 是(每个 URI) 缓存场景
    随机 简单分发
    首选 缓存优化

    配置结构

    全局配置段

    适用于整个 HAProxy 进程的全局设置。

    global
    # 进程设置
    user haproxy
    group haproxy
    daemon
    maxconn 50000

    # 性能调优
    nbproc 1
    nbthread 4
    cpu-map 1:1-4

    # 日志记录
    log /dev/log local0
    log /dev/log local1 notice
    chroot /var/lib/haproxy

    # SSL
    tune.ssl.default-dh-param 2048

    # 统计套接字
    stats socket /run/haproxy/admin.sock mode 660 level admin

    默认配置段

    所有前端和后端继承的默认设置,除非被覆盖。

    defaults
    mode http
    log global
    option httplog
    option dontlognull
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms
    errorfile 400 /etc/haproxy/errors/400.http
    errorfile 503 /etc/haproxy/errors/503.http

    前端配置段

    定义监听端点和请求路由规则。

    frontend http_in
    bind *:80
    bind *:443 ssl crt /etc/haproxy/certs/
    mode http

    # 日志记录
    option httplog

    # 超时设置
    timeout client 30s

    # ACL
    acl is_api path_beg /api
    acl is_websocket hdr(Upgrade) -i websocket

    # 路由
    use_backend api_servers if is_api
    use_backend websocket_servers if is_websocket
    default_backend web_servers

    # HTTP 头部
    http-request set-header X-Forwarded-Proto https if { ssl_fc }
    http-request set-header X-Forwarded-Port %[dst_port]

    后端配置段

    定义服务器组和负载均衡规则。

    backend web_servers
    mode http
    balance roundrobin

    # 健康检查
    option httpchk GET /health
    http-check expect status 200

    # 超时设置
    timeout server 30s

    # 会话持久化
    cookie SRV insert indirect nocache

    # 服务器
    server web1 10.0.1.10:80 check cookie web1 rise 2 fall 3
    server web2 10.0.1.11:80 check cookie web2 rise 2 fall 3
    server web3 10.0.1.12:80 check cookie web3 backup

    监听配置段

    在一个配置段中组合前端和后端(更简单的配置)。

    listen stats
    bind *:8404
    mode http
    stats enable
    stats uri /stats
    stats refresh 10s
    stats auth admin:password


    性能特征

    连接处理

    HAProxy 使用基于 epoll(Linux)、kqueue(BSD/macOS)或 /dev/poll(Solaris)系统调用的事件驱动、非阻塞 I/O 模型。这使其能够以最少的 CPU 使用处理数万个并发连接。

    内存效率

    • 零拷贝架构:数据在网络缓冲区之间传递而无需复制
    • 固定大小缓冲区:预分配缓冲区防止内存碎片
    • 连接池:高效重用连接

    基准性能

    现代硬件上的典型性能:

    指标值
    并发连接数 100,000+
    每秒请求数 1,000,000+ (HTTP)
    CPU 使用率 50k 连接时 < 10%
    内存使用 50k 连接时约 100MB
    延迟 < 1ms(代理开销)

    性能调优参数

    global
    # 最大并发连接数
    maxconn 100000

    # 缓冲区大小
    tune.bufsize 32768
    tune.maxrewrite 1024

    # 连接限制
    tune.maxaccept 64

    # SSL 性能
    tune.ssl.cachesize 200000

    # 多线程
    nbproc 1
    nbthread 4


    健康检查机制

    TCP 健康检查

    四层的基本连接检查。

    backend tcp_servers
    mode tcp
    option tcplog
    server s1 10.0.1.10:3306 check

    HTTP 健康检查

    应用级健康检查,使用 HTTP 请求。

    backend http_servers
    mode http
    option httpchk GET /health HTTP/1.1\\r\\nHost:\\ example.com
    http-check expect status 200
    server s1 10.0.1.10:80 check

    高级 HTTP 检查

    多个条件和响应验证。

    backend api_servers
    mode http
    option httpchk GET /api/health
    http-check expect rstring {"status":"ok"}
    http-check expect status 200
    server s1 10.0.1.10:80 check inter 5s rise 2 fall 3

    SSL 健康检查

    验证 SSL 证书和连接。

    backend ssl_servers
    mode tcp
    option ssl-hello-chk
    server s1 10.0.1.10:443 check ssl verify none

    SMTP 健康检查

    用于 SMTP 服务器监控。

    backend smtp_servers
    mode tcp
    option smtpchk HELO localhost
    server s1 10.0.1.10:25 check

    健康检查参数

    参数描述默认值
    check 启用健康检查 禁用
    inter 检查间隔 2000ms
    rise 成功阈值 2
    fall 失败阈值 3
    timeout check 检查超时 根据模式变化
    port 替代检查端口 服务器端口

    代理检查

    用于自定义健康检查的外部代理。

    backend custom_servers
    server s1 10.0.1.10:80 agent-check agent-port 6300 inter 1s


    会话持久化

    基于 Cookie 的持久化

    插入或修改 HTTP Cookie 以跟踪会话。

    backend web_servers
    balance roundrobin
    cookie SERVERID insert indirect nocache
    server web1 10.0.1.10:80 cookie web1
    server web2 10.0.1.11:80 cookie web2

    Cookie 模式:

    • insert:HAProxy 插入新 cookie
    • prefix:HAProxy 前缀现有 cookie
    • rewrite:HAProxy 重写现有 cookie

    源 IP 持久化

    哈希客户端 IP 以进行一致路由。

    backend web_servers
    balance source
    hash-type consistent

    URL 参数持久化

    使用 URL 参数进行会话跟踪。

    backend web_servers
    balance url_param JSESSIONID
    hash-type consistent

    基于头部的持久化

    使用 HTTP 头部值进行路由。

    backend web_servers
    balance hdr(User-Agent)
    hash-type consistent

    RDP Cookie 持久化

    用于远程桌面协议连接。

    backend rdp_servers
    mode tcp
    balance rdp-cookie


    SSL/TLS 终止

    SSL 终止配置

    从后端服务器卸载 SSL 处理。

    frontend https_in
    bind *:443 ssl crt /etc/haproxy/certs/example.pem
    mode http

    # SSL 选项
    no sslv3
    no tls-tickets

    # 转发协议信息
    http-request set-header X-Forwarded-Proto https

    default_backend web_servers

    多证书(SNI)

    使用 SNI 支持多个域。

    frontend https_in
    bind *:443 ssl crt /etc/haproxy/certs/example.pem crt /etc/haproxy/certs/api.pem
    mode http
    default_backend web_servers

    SSL 卸载到后端

    将加密流量转发到后端。

    frontend https_passthrough
    bind *:443
    mode tcp
    default_backend ssl_servers

    backend ssl_servers
    mode tcp
    server s1 10.0.1.10:443 check ssl verify none

    SSL 证书链

    包含中间证书。

    frontend https_in
    bind *:443 ssl crt /etc/haproxy/certs/fullchain.pem

    SSL 性能调优

    global
    # SSL 会话缓存
    tune.ssl.cachesize 200000

    # 默认 DH 参数
    tune.ssl.default-dh-param 2048

    # SSL 生命周期
    tune.ssl.lifetime 300

    frontend https_in
    # 启用会话重用
    option http-use-htx

    # 优先服务器密码套件
    ssl-default-server-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256


    高可用部署

    使用 Keepalived 的主备模式

    使用 VRRP 实现 HAProxy 故障转移。

    主节点配置:

    vrrp_script chk_haproxy {
    script "killall -0 haproxy"
    interval 2
    weight 2
    }

    vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 101
    authentication {
    auth_type PASS
    auth_pass secret
    }
    virtual_ipaddress {
    10.0.0.100/24
    }
    track_script {
    chk_haproxy
    }
    }

    备节点配置:

    vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 100
    authentication {
    auth_type PASS
    auth_pass secret
    }
    virtual_ipaddress {
    10.0.0.100/24
    }
    track_script {
    chk_haproxy
    }
    }

    基于 DNS 的负载均衡

    DNS 轮询后的多个 HAProxy 实例。

    ; DNS 配置
    lb1.example.com. IN A 10.0.0.10
    lb2.example.com. IN A 10.0.0.11
    lb3.example.com. IN A 10.0.0.12

    ; 应用 DNS
    app.example.com. IN A 10.0.0.10
    app.example.com. IN A 10.0.0.11
    app.example.com. IN A 10.0.0.12

    多层高可用

    ┌─────────────┐
    │ 客户端 │
    └──────┬──────┘

    ┌──────▼──────┐
    │ DNS 轮询 │
    └──────┬──────┘

    ┌────────────────┼────────────────┐
    │ │ │
    ┌────▼────┐ ┌────▼────┐ ┌────▼────┐
    │ HAProxy │ │ HAProxy │ │ HAProxy │
    │ LB1 │ │ LB2 │ │ LB3 │
    └────┬────┘ └────┬────┘ └────┬────┘
    │ │ │
    └────────────────┼────────────────┘

    ┌──────▼──────┐
    │ HAProxy │
    │ (内部) │
    └──────┬──────┘

    ┌────────────────┼─────────────────┐
    │ │ │
    ┌────▼────┐ ┌────▼────┐ ┌────▼────┐
    │ 应用 │ │ 应用 │ │ 应用 │
    │ Server1 │ │ Server2 │ │ Server3 │
    └─────────┘ └─────────┘ └─────────┘


    最佳实践

    1. 配置组织

    使用 include 进行模块化配置:

    global
    # 全局设置

    defaults
    # 默认设置

    # 包含单独的文件
    haproxy.cfg.d/frontend/*.cfg
    haproxy.cfg.d/backend/*.cfg

    2. 日志记录和监控

    配置全面的日志记录:

    global
    log 127.0.0.1 local0 info
    log 127.0.0.1 local1 notice

    defaults
    log global
    option httplog
    option logasap
    capture request header Host len 64
    capture request header User-Agent len 128

    3. 超时配置

    设置适当的超时:

    defaults
    # 连接超时
    timeout connect 5s

    # 客户端超时
    timeout client 30s

    # 服务器超时
    timeout server 30s

    # 隧道超时(WebSocket 等)
    timeout tunnel 1h

    # HTTP keep-alive 超时
    timeout http-keep-alive 10s

    4. 速率限制

    实施速率限制:

    frontend http_in
    # 按 IP 跟踪客户端
    stick-table type ip size 100k expire 30s store http_req_rate(10s)

    # 速率限制 ACL
    http-request deny if { src_http_req_rate(10s) gt 100 }

    5. 安全头部

    添加安全头部:

    backend web_servers
    http-response set-header X-Frame-Options "SAMEORIGIN"
    http-response set-header X-Content-Type-Options "nosniff"
    http-response set-header X-XSS-Protection "1; mode=block"
    http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains"

    6. 连接限制

    防止过载:

    backend api_servers
    # 每个服务器的最大连接数
    server s1 10.0.1.10:80 maxconn 1000
    server s2 10.0.1.11:80 maxconn 1000

    # 队列超时
    timeout queue 5s

    7. 优雅关闭

    优雅处理关闭:

    global
    # 优雅关闭超时
    grace-timeout 30s

    8. 统计信息访问

    保护统计信息端点:

    listen stats
    bind 127.0.0.1:8404
    mode http
    stats enable
    stats uri /stats
    stats refresh 10s
    stats auth admin:strongpassword
    stats admin if TRUE

    9. HTTP/2 支持

    启用 HTTP/2:

    frontend https_in
    bind *:443 ssl crt /certs/example.pem alpn h2,http/1.1
    mode http
    default_backend web_servers

    10. 连接重用

    启用 HTTP keep-alive:

    defaults
    option http-keep-alive
    option http-server-close


    使用场景

    1. Web 应用程序负载均衡

    frontend web_app
    bind *:80
    bind *:443 ssl crt /certs/
    mode http
    default_backend web_servers

    backend web_servers
    mode http
    balance roundrobin
    option httpchk GET /health
    server web1 10.0.1.10:80 check
    server web2 10.0.1.11:80 check
    server web3 10.0.1.12:80 check

    2. API 网关

    frontend api_gateway
    bind *:8080
    mode http

    # 速率限制
    stick-table type ip size 100k expire 10s store http_req_rate(1s)
    http-request deny if { src_http_req_rate(1s) gt 100 }

    # 版本路由
    acl is_v1 path_beg /api/v1
    acl is_v2 path_beg /api/v2

    use_backend api_v1 if is_v1
    use_backend api_v2 if is_v2

    3. 数据库负载均衡

    frontend db_proxy
    bind *:3306
    mode tcp
    default_backend mysql_servers

    backend mysql_servers
    mode tcp
    balance leastconn
    option mysql-check user haproxy_check
    server db1 10.0.2.10:3306 check
    server db2 10.0.2.11:3306 check

    4. WebSocket 代理

    frontend websocket
    bind *:80
    mode http

    acl is_websocket hdr(Upgrade) -i websocket
    use_backend websocket_servers if is_websocket

    backend websocket_servers
    mode http
    balance leastconn
    option httpchk GET /health
    server ws1 10.0.1.20:80 check
    server ws2 10.0.1.21:80 check

    5. 微服务入口

    frontend microservices
    bind *:80
    mode http

    # 服务路由
    acl is_user path_beg /user
    acl is_order path_beg /order
    acl is_payment path_beg /payment

    use_backend user_service if is_user
    use_backend order_service if is_order
    use_backend payment_service if is_payment

    backend user_service
    mode http
    balance roundrobin
    server user1 10.0.3.10:8001 check
    server user2 10.0.3.11:8001 check

    6. 内容分发网络

    frontend cdn_edge
    bind *:80
    bind *:443 ssl crt /certs/
    mode http

    # 缓存控制
    http-response set-header Cache-Control "public, max-age=3600" if { path_end .css .js .png .jpg }

    # 静态内容路由
    acl is_static path_end .css .js .png .jpg .gif .ico
    use_backend static_servers if is_static
    default_backend app_servers

    backend static_servers
    mode http
    balance uri
    hash-type consistent
    server static1 10.0.4.10:80 check
    server static2 10.0.4.11:80 check

    7. 蓝绿部署

    frontend production
    bind *:80
    mode http

    # 流量分割
    acl is_test src 10.0.0.0/8
    use_backend green if is_test
    default_backend blue

    backend blue
    mode http
    balance roundrobin
    server blue1 10.0.5.10:80 check

    backend green
    mode http
    balance roundrobin
    server green1 10.0.5.20:80 check

    8. 熔断器模式

    backend api_servers
    mode http
    balance roundrobin

    # 熔断器设置
    option httpchk GET /health
    http-check expect status 200

    # 失败阈值
    server api1 10.0.1.10:80 check inter 2s rise 3 fall 3 on-marked-down shutdown-sessions
    server api2 10.0.1.11:80 check inter 2s rise 3 fall 3 on-marked-down shutdown-sessions


    结论

    HAProxy 是一个功能强大、高性能的负载均衡器,在以最少的资源消耗处理高并发工作负载方面表现出色。其事件驱动架构、全面的功能集和灵活性使其适用于从简单的 Web 应用程序到复杂的微服务架构的广泛部署场景。

    关键要点:

  • 性能:事件驱动的单线程模型提供卓越的性能
  • 灵活性:支持四层和七层负载均衡
  • 可靠性:高级健康检查和故障转移机制
  • 可观测性:全面的指标和日志记录功能
  • 安全性:SSL/TLS 终止、ACL 和速率限制
  • 在使用 HAProxy 设计负载均衡架构时,请考虑您的性能、会话持久化、健康检查和高可用性特定要求,以针对您的用例优化配置 HAProxy。


    参考资料

    • 官方文档:https://www.haproxy.org/documentation/
    • HAProxy GitHub:https://github.com/haproxy/haproxy
    • 社区邮件列表:https://www.haproxy.org/#community
    • 配置指南:https://docs.haproxy.org
    赞(0)
    未经允许不得转载:171主机测评 » 架构之HAProxy
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址