Akemi

HAProxy代理后端服务器

2025/04/11

HAProxy与Nignx的负载均衡功能类似,但是功能更加强大

专为负载均衡设计:专注于高性能的 TCP/HTTP 负载均衡,尤其擅长四层(传输层)和七层(应用层)流量分发。适合纯负载均衡场景

算法名称 配置关键字 核心原理 适用场景
轮询(Round Robin) roundrobin 按顺序依次分配请求到后端服务器。 后端服务器性能相近,无状态服务。
加权轮询(Weighted RR) roundrobin + weight 基于服务器权重分配请求,权重高的服务器获得更多流量。 后端服务器性能不均(如不同配置的机器)。
最少连接(Least Connections) leastconn 将请求分配给当前连接数最少的服务器。 后端服务器处理请求时间差异较大(如长连接服务)。
源 IP 哈希(Source IP Hash) source 根据客户端源 IP 的哈希值固定分配请求到同一服务器。 需会话保持但无共享 Session 存储的场景(如临时会话)。
URI 哈希(URI Hash) uri 根据请求 URI 的哈希值分配请求,相同 URI 的请求固定到同一服务器。 需缓存特定 URI 对应的资源(如 CDN 节点优化)。
随机(Random) random 随机选择后端服务器,可基于权重调整概率。 高并发下快速分散请求,避免热点问题。
自定义哈希键(Hash Key) hdr/url_param 根据自定义的 HTTP 头或 URL 参数计算哈希值。 需按业务逻辑(如用户 ID、API Key)分配请求。

安装部署

后端部署与配置httpd

1
2
3
4
5
6
7
8
9
10
11
12
13
yum -y --downloadonly --downloaddir=/root/httpd install httpd
scp -r httpd 1.1.1.1:~
scp -r httpd 1.1.1.2:~
scp -r httpd 1.1.1.3:~
ssh 1.1.1.1 "rpm -vih httpd/* && echo 'wangsheng-1' > /var/www/html/index.html && sed -i 's/^Listen.*/Listen 8080/g' /etc/httpd/conf/httpd.conf && systemctl enable httpd --now"
ssh 1.1.1.2 "rpm -vih httpd/* && echo 'wangsheng-2' > /var/www/html/index.html && sed -i 's/^Listen.*/Listen 8080/g' /etc/httpd/conf/httpd.conf && systemctl enable httpd --now"
ssh 1.1.1.3 "rpm -vih httpd/* && echo 'wangsheng-3' > /var/www/html/index.html && sed -i 's/^Listen.*/Listen 8080/g' /etc/httpd/conf/httpd.conf && systemctl enable httpd --now"

ssh 1.1.1.1 "systemctl restart httpd && systemctl disable firewalld --now"
ssh 1.1.1.2 "systemctl restart httpd && systemctl disable firewalld --now"
ssh 1.1.1.3 "systemctl restart httpd && systemctl disable firewalld --now"

为了做标识,网页内容不同,实际生产中应该是一致的

HAProxy配置文件详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
systemctl disable firewalld.service --now

yum -y install haproxy

# 默认配置文件/etc/haproxy/haproxy.cfg

#---------------------------------------------------------------------
# Global settings - 全局配置(影响所有进程)
#---------------------------------------------------------------------
global
log 127.0.0.1 local2 # 日志输出到本地syslog的local2设施
chroot /var/lib/haproxy # 安全隔离到指定目录
pidfile /var/run/haproxy.pid # 记录进程ID的文件位置
maxconn 4000 # 每个进程最大连接数
user haproxy # 以haproxy用户身份运行
group haproxy # 以haproxy用户组身份运行
daemon # 以守护进程模式运行
stats socket /var/lib/haproxy/stats # 开启统计套接字(用于实时获取状态)

# SSL加密策略
ssl-default-bind-ciphers PROFILE=SYSTEM # 绑定端口的默认加密套件
ssl-default-server-ciphers PROFILE=SYSTEM # 后端通信的默认加密套件

#---------------------------------------------------------------------
# Default settings - 默认配置(被所有listen/backend继承)
#---------------------------------------------------------------------
defaults
mode http # 默认工作模式为HTTP代理
log global # 继承全局日志配置
option httplog # 记录HTTP详细日志
option dontlognull # 不记录空连接日志
option http-server-close # 完成响应后关闭与后端连接
option forwardfor except 127.0.0.0/8 # 添加X-Forwarded-For头(排除本地流量)
option redispatch # 当服务器不可用时重新分配请求
retries 3 # 连接失败重试次数
timeout http-request 10s # 等待完整HTTP请求的超时时间
timeout queue 1m # 请求在队列中的最大等待时间
timeout connect 10s # 连接后端服务器的超时时间
timeout client 1m # 客户端不活动超时
timeout server 1m # 服务器不响应超时
timeout http-keep-alive 10s # Keep-Alive连接保持时间
timeout check 10s # 健康检查超时时间
maxconn 3000 # 前后端最大连接数

#---------------------------------------------------------------------
# Frontend配置 - 定义客户端访问入口
#---------------------------------------------------------------------
frontend main
bind *:80 # 监听所有IP的80端口
# 定义ACL规则识别静态资源请求:
acl url_static path_beg -i /static /images /javascript /stylesheets # 路径开头匹配
acl url_static path_end -i .jpg .gif .png .css .js # 文件扩展名匹配

use_backend static if url_static # 静态资源走static后端
default_backend app # 其他请求走app后端

#---------------------------------------------------------------------
# Static backend - 静态资源服务器配置
#---------------------------------------------------------------------
backend static
balance roundrobin # 使用轮询负载算法
server static 127.0.0.1:4331 check # 单个静态资源服务器,启用健康检查

#---------------------------------------------------------------------
# Application backend - 应用服务器集群配置
#---------------------------------------------------------------------
backend app
balance roundrobin # 使用普通轮询
# 定义4个应用服务器节点(本地模拟集群)
server web1 1.1.1.1:8080 check # check表示启用健康检查
server web2 1.1.1.2:8080 check
server web3 1.1.1.3:8080 check

systemctl restart haproxy.service
netstat -tunlp | grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 14214/haproxy

负载分担测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@varnish ~]# curl 10.163.2.100
wangsheng-3
[root@varnish ~]# curl 10.163.2.100
wangsheng-1
[root@varnish ~]# curl 10.163.2.100
wangsheng-2
[root@varnish ~]# curl 10.163.2.100
wangsheng-3
[root@varnish ~]# curl 10.163.2.100
wangsheng-1

可见此时已经成功转发了
其他负载分担模式就不测试了反正是和nginx差不多的,总之是那几个关键字

roundrobin
roundrobin + weight
leastconn
source
uri
random
hdr/url_param

TLS配置

haproxy支持pem格式的证书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
mkdir /etc/pki/haproxy
chmod 700 /etc/pki/haproxy
cd /etc/pki/haproxy

# 自签名证书
openssl genrsa 2048 > server.key
openssl req -new -key server.key -out server.csr
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
cat server.crt server.key > server.pem

# 修改HAProxy的TLS配置
frontend main
bind *:443 ssl crt /etc/pki/haproxy/server.pem
bind *:80
redirect scheme https if !{ ssl_fc }
option forwardfor # 源ip转发
http-request add-header X-Forwarded-Proto https

# 定义ACL规则识别静态资源请求:
acl url_static path_beg -i /static /images /javascript /stylesheets # 路径开头匹配
acl url_static path_end -i .jpg .gif .png .css .js # 文件扩展名匹配

use_backend static if url_static # 静态资源走static后端
default_backend app # 其他请求走app后端

systemctl restart haproxy.service
netstat -tunlp | grep haproxy
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 15081/haproxy
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 15081/haproxy

HTTPS终结

HAProxy 的 HTTPS 终结(SSL/TLS Termination) 功能是指由 HAProxy 负责终止客户端的 HTTPS 加密连接,将解密后的 HTTP 流量以明文形式转发给后端服务器。

维度 HTTPS 终结(HAProxy 解密) SSL 穿透(后端服务器解密)
性能 ✅ 后端服务器无需处理加解密,性能更高 ❌ 后端需消耗资源处理 SSL/TLS
配置复杂度 ✅ 证书集中管理,维护简单 ❌ 每台后端服务器需独立配置证书
安全性 ⚠️ 内部网络需可信(明文传输) ✅ 端到端加密(外部到后端全程加密)
功能扩展性 ✅ 可基于 HTTP 头/内容实现高级路由和策略 ❌ 仅能基于 TCP/IP 层信息(如端口、IP)
适用场景 多域名托管、复杂路由、需卸载 SSL 压力的场景 严格端到端加密需求(如金融、医疗敏感数据)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
global
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
stats socket /var/lib/haproxy/stats

# --------------- 新增SSL强化配置 ---------------
ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 # 全局禁用不安全协议
ssl-default-bind-ciphers TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384 # 强制使用高安全性加密套件
tune.ssl.default-dh-param 2048 # 增强Diffie-Hellman参数

#---------------------------------------------------------------------
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 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000

#---------------------------------------------------------------------
frontend main
# --------------- 强化HTTPS终结配置 ---------------
bind *:443 ssl crt /etc/pki/haproxy/server.pem alpn h2,http/1.1 # HTTPS 终结在此发生
bind *:80
# 强制所有HTTP流量跳转到HTTPS
redirect scheme https code 301 if !{ ssl_fc }

# 添加安全相关HTTP头(HSTS等)
http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
http-request add-header X-Forwarded-Proto https if { ssl_fc }
http-request set-header X-Real-IP %[src] # 传递真实客户端IP

# 静态资源路由规则
acl url_static path_beg -i /static /images /javascript /stylesheets
acl url_static path_end -i .jpg .gif .png .css .js
use_backend static if url_static
default_backend app

#---------------------------------------------------------------------
backend static
balance roundrobin
# 转发明文HTTP到静态服务器(注意端口为80)
server static 127.0.0.1:4331 check

#---------------------------------------------------------------------
backend app
balance roundrobin
# 转发明文HTTP到应用服务器集群(端口应为80,此处8080需确认是否为HTTP服务)
server web1 1.1.1.1:8080 check
server web2 1.1.1.2:8080 check
server web3 1.1.1.3:8080 check

systemctl restart haproxy.service

调整后,客户端通过 HTTPS 访问,HAProxy 完成 SSL 解密,后端 Apache 将收到明文 HTTP 请求并记录为 HTTP 访问(但客户端实际使用 HTTPS)。

HAProxy监控管理(admin mode)

  1. 手动管理后端服务器状态
    • 强制将特定后端服务器标记为“管理状态”,HAProxy 将立即停止向其转发新流量。
    • 适用于以下场景:
      • 服务器维护(如升级、打补丁)。
      • 调试问题(临时隔离问题节点)。
      • 避免因健康检查延迟导致的流量误分发。
  2. 覆盖健康检查结果
    • 即使服务器健康检查正常,Admin Mode 仍会阻止流量进入该服务器。
    • 即使健康检查异常,Admin Mode 也可强制流量继续分发(需结合其他参数)。
  3. 平滑流量迁移
    • 允许现有连接完成(类似 drain 模式),避免强制中断用户会话。

添加配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
front stat-page
bind *:8080
stats enable
stats uri /wsstat
stats auth ws:ws123
stats admin if TRUE # 开启admin模式

systemctl restart haproxy.service

ss -tunlp | grep 8080
tcp LISTEN 0 3000 0.0.0.0:8080 0.0.0.0:* users:(("haproxy",pid=2003,fd=8))

ls /var/lib/haproxy/stats
/var/lib/haproxy/stats
同时会创建出一个socket文件

访问网页8080/wsstat
输入账号密码

后端服务器默认带了admin参数,表示被admin mode所管理
server server1 192.168.1.10:80 check init-addr none state admin

CATALOG
  1. 1. 安装部署
    1. 1.1. 后端部署与配置httpd
  2. 2. HAProxy配置文件详解
  3. 3. 负载分担测试
  4. 4. TLS配置
  5. 5. HTTPS终结
  6. 6. HAProxy监控管理(admin mode)