HAProxy(High Availability Proxy)是一款开源的高性能 TCP/HTTP 负载均衡器和代理服务器,它将网络流量分发到多台后端服务器,以最大化性能、可靠性和服务器承载能力。它同时工作在 OSI 模型的第 4 层(TCP)和第 7 层(HTTP),为应用和服务提供精细的流量管理、高可用性和高效的资源利用。
HAProxy 以速度快、稳定性强以及能够处理超高流量而著称。它通常部署在 Web 服务器、应用服务器和数据库集群之前,用于确保客户端请求的均匀分发、防止服务器过载并简化维护操作。
使用 HAProxy 进行负载均衡
负载均衡是指将网络流量分发到一组后端服务器(称为服务器集群或 server farm)的过程。HAProxy 采用多种算法来决定下一个请求由哪台服务器处理,目标是优化资源使用、最大化吞吐量、最小化响应时间并避免单台服务器过载。
HAProxy 负载均衡的关键要素包括:
- 算法选择: HAProxy 提供多种算法以适应不同的应用需求。
- 服务器健康检查: 持续监控后端服务器的可用性和响应能力。
- 服务器权重: 让特定服务器优先承担更多流量。
负载均衡算法
HAProxy 在 backend 段中提供了一系列可配置的算法:
roundrobin:将请求依次分发给后端组中的每台服务器。默认算法。leastconn:将新连接分配给活动连接数最少的服务器。适合长连接场景。source:使用源 IP 地址的哈希值确定服务器。可确保同一客户端始终连接到同一台服务器,适用于没有显式会话保持机制的有状态应用。uri:对 URL 左侧部分(query string 之前)做哈希以选择服务器。适用于缓存代理。hdr(<name>):对指定 HTTP header 的值做哈希。random:随机挑选一台服务器。
backend web_servers
balance roundrobin
server web1 192.168.1.10:80 check
server web2 192.168.1.11:80 check
server web3 192.168.1.12:80 check
使用 HAProxy 进行代理
代理是指由中间服务器代表客户端或服务器执行操作。HAProxy 作为反向代理运行:接受客户端连接并转发到后端服务器,再将服务器的响应返回给客户端。这一抽象层带来了安全性、性能和运维方面的收益。
第 4 层(TCP)代理
在第 4 层,HAProxy 转发原始 TCP 连接,不检查应用层内容。这适用于非 HTTP 服务、数据库,或不需要(或不希望)内容检查的自定义协议。
listen mysql_cluster
bind *:3306
mode tcp
balance leastconn
server db1 192.168.1.20:3306 check
server db2 192.168.1.21:3306 check
第 7 层(HTTP)代理
在第 7 层,HAProxy 可以检查并修改 HTTP 请求和响应头、URL 以及 Cookie。由此可实现基于内容的路由、SSL 终止、URL 重写和会话保持等高级功能。
frontend http_frontend
bind *:80
mode http
default_backend web_servers
HAProxy 配置组成
HAProxy 配置通常位于 /etc/haproxy/haproxy.cfg,并划分为若干段。
global 段
global 段定义进程级参数,例如日志、安全设置和性能上限。这些设置对整个 HAProxy 实例生效。
global
log /dev/log local0 info
maxconn 20000
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
user haproxy
group haproxy
daemon
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
defaults 段
defaults 段为其后的所有 listen、frontend 和 backend 段指定默认参数,从而减少配置冗余。
defaults
mode http
log global
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
option httplog
option dontlognull
option http-server-close
frontend 段
frontend 定义 HAProxy 监听客户端连接的对外入口。它指定 IP 地址、端口、协议(mode),以及使用访问控制列表(ACL)把请求路由到特定 backend 的规则。
frontend http_in
bind *:80
mode http
acl host_app1 hdr(host) -i app1.example.com
acl host_app2 hdr(host) -i app2.example.com
use_backend app1_servers if host_app1
use_backend app2_servers if host_app2
default_backend default_web_servers
backend 段
backend 定义 HAProxy 可以转发请求的一组服务器,包含负载均衡算法、健康检查参数以及各台服务器的定义。
backend app1_servers
balance leastconn
option httpchk GET /healthz
server s1 10.0.0.10:8080 check inter 2000 fall 3 rise 2
server s2 10.0.0.11:8080 check inter 2000 fall 3 rise 2 backup
check:为该服务器启用健康检查。inter 2000:每 2000ms 检查一次。fall 3:连续 3 次检查失败后将服务器标记为下线。rise 2:连续 2 次检查成功后将服务器标记为上线。backup:仅当所有非 backup 服务器都下线时才使用该服务器。
listen 段
listen 段把 frontend 和 backend 的功能合并到一个代码块中。常用于较简单的配置,或用于 HAProxy 统计页面这类服务。
listen stats_page
bind *:8080
mode http
stats enable
stats uri /haproxy?stats
stats realm HAProxy\ Statistics
stats auth admin:securepassword
stats refresh 5s
访问控制列表(ACL)
ACL 是强大的条件规则,用于匹配客户端请求中的特定条件(例如源 IP、host 头、URL 路径、HTTP 方法)。它们支持动态路由、内容切换和拦截。
frontend website_frontend
bind *:443 ssl crt /etc/haproxy/certs/mydomain.pem
# 基于路径的 ACL
acl is_admin_area path_beg /admin
acl is_api_v1 path_beg /api/v1
# 根据 ACL 进行路由
use_backend admin_backend if is_admin_area
use_backend api_v1_backend if is_api_v1
default_backend main_website_backend
健康检查
HAProxy 持续监控后端服务器的健康状况,确保请求只发送到正常运行的实例。如果某台服务器健康检查失败,HAProxy 会暂时将其移出轮换,直到它恢复。
- TCP 检查(
check): 基本的端口连通性。 - HTTP 检查(
option httpchk): 发送 HTTP 请求(例如GET /health)并期待有效的 HTTP 状态码(2xx 或 3xx)。 - SSL Hello 检查(
ssl-hello-chk): 检查能否建立 SSL 握手。
HAProxy 高级功能
SSL 终止与卸载
HAProxy 可以处理 SSL/TLS 加密与解密,把这项 CPU 密集型任务从后端服务器卸载下来。它解密进入的 HTTPS 流量并以明文 HTTP 转发到后端,也可以重新加密以实现端到端 SSL。
frontend https_in
bind *:443 ssl crt /etc/haproxy/certs/mydomain.pem
mode http
default_backend web_servers
粘性会话(会话保持)
粘性会话确保客户端在整个会话期间的请求始终被路由到同一台后端服务器。对于在单台服务器上维护会话状态的应用,这一点至关重要。
- 基于 Cookie 的保持: HAProxy 在客户端浏览器中插入一个 Cookie,后续请求据此识别正确的后端服务器。
- 基于源 IP 的保持: 使用客户端源 IP 地址始终路由到同一台服务器(在 NAT 后面可靠性较低)。
backend web_servers_sticky
balance roundrobin
cookie SERVERID insert indirect nocache
server s1 10.0.0.10:80 check cookie s1
server s2 10.0.0.11:80 check cookie s2
基于内容的路由
基于内容的路由根据客户端请求中的特定属性(例如请求的 URL 路径、HTTP host 头或自定义 HTTP header)把流量导向不同的后端服务器池。这有助于实现微服务架构或多租户应用。
(示例已在 frontend 段中用 acl host_app1 和 use_backend 展示。)
HAProxy 自身的高可用
虽然 HAProxy 是为后端服务的高可用而设计的,但 HAProxy 实例本身也可以借助外部机制实现高可用,例如配合 Keepalived 等工具使用 VRRP(虚拟路由器冗余协议)。这样会创建一个浮动 IP 地址,在发生故障时在主、备 HAProxy 服务器之间自动切换,确保负载均衡服务不中断。
HAProxy 与 Nginx 简要对比
HAProxy 和 Nginx 都可以充当反向代理和负载均衡器,但它们的主要设计目标和典型部署方式不同。
| 特性 | HAProxy | Nginx |
|---|---|---|
| 主要定位 | 专用的高性能负载均衡器与代理 | Web 服务器、反向代理、负载均衡器、缓存 |
| 性能 | 极高(尤其是 L4/TCP) | 高(全能型) |
| 配置 | 专为负载均衡设计,选项丰富 | 更通用、更灵活 |
| 缓存 | 有限(需要外部模块) | 原生、强大的 HTTP 缓存 |
| 静态文件服务 | 并非其主要定位 | 出色,高度优化 |
| 模块化 | 相对单体 | 高度模块化,模块生态丰富 |
| SSL 终止 | 支持 | 支持 |
| WebSockets | 支持 | 支持 |
HAProxy 常用于对纯粹的负载均衡性能和可靠健康检查要求极高的关键高流量环境。当需要在负载均衡之外同时兼顾 Web 服务、缓存和反向代理时,则常选择 Nginx。两者组合部署也很常见:HAProxy 作为主负载均衡器,Nginx 负责特定的应用层代理或静态内容。
