haproxy代理介绍

1.负载均衡对比

┌─────────────────────────────────────────────────────────────────┐
│                    负载均衡类型对比                                │
├──────────────┬──────────────────────┬───────────────────────────┤
│    类型       │      代表产品         │       应用场景             │
├──────────────┼──────────────────────┼───────────────────────────┤
│ 四层(L4)      │ LVS、Nginx(1.9+)     │ MySQL、Redis、RabbitMQ     │
│              │ HAProxy             │ Memcache 等                │
├──────────────┼──────────────────────┼───────────────────────────┤
│ 七层(L7)      │ HAProxy、Nginx       │ Web服务、API、动静分离      │
│              │                     │ PHP、图片、Tomcat           │
├──────────────┼──────────────────────┼───────────────────────────┤
│ 硬件          │ F5、Netscaler       │ 金融/大型企事业单位           │
│              │ Array、深信服        │                            │
└──────────────┴──────────────────────┴───────────────────────────┘

HAProxy 定位:

  • 高并发(10000+)、高性能 TCP/HTTP 负载均衡器
  • 支持 SSL/TLS、基于 Cookie 持久性、自动故障切换
  • 支持正则表达式及 Web 状态统计
  • 当前最新 TLS 版本为 2.4
  • 不支持 UDP 协议,不支持正向代理和缓存代理

2.安装方式

2.1 Ubuntu 安装

1
2
3
4
5
apt-get install software-properties-common
add-apt-repository ppa:vbernat/haproxy-2.0
apt update
apt install haproxy=2.0.*
haproxy -v

2.2 CentOS 7 yum 安装

1
2
3
4
5
6
7
# 系统默认源 - 版本 1.5.18(不推荐生产使用)
yum install haproxy -y

# IUS 第三方源 - 版本 1.8.x
wget https://centos7.iuscommunity.org/ius-release.rpm
rpm -Uvh ius-release*rpm
yum install haproxy18u -y

2.3 编译安装(推荐生产环境)

1
2
3
4
5
6
7
8
9
10
11
12
# 安装依赖
yum -y install gcc openssl-devel pcre-devel systemd-devel

# 编译安装 HAProxy 2.x
make ARCH=x86_64 TARGET=linux-glibc \
USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 \
USE_SYSTEMD=1 USE_LUA=1 \
LUA_INC=/usr/local/src/lua-5.3.5/src/ \
LUA_LIB=/usr/local/src/lua-5.3.5/src/

make install PREFIX=/apps/haproxy
ln -s /apps/haproxy/sbin/haproxy /usr/sbin/

3.基础配置详解

配置文件分为两大部分:
├── global:全局配置(进程、安全、性能、调试)
└── proxies:代理配置
    ├── defaults:为 frontend/backend/listen 提供默认配置
    ├── frontend:前端,类似 Nginx 的 server {}
    ├── backend:后端,类似 Nginx 的 upstream {}
    └── listen:同时拥有前端和后端,配置更简洁(生产常用)

global 核心参数:

maxconn          最大连接数
chroot           锁定运行目录
stats socket     Socket 文件路径(用于 socat 管理)
user/group       运行用户身份
nbproc           Worker 进程数(与 nbthread 互斥)
cpu-map          绑定进程到指定 CPU 核心
log              日志配置(可同时定义本地和远程日志服务器)

defaults 核心参数:

option forwardfor          透传客户端真实IP
option http-keep-alive     开启长连接
timeout connect  300000ms  客户端→HAProxy→后端建连超时
timeout client   300000ms  客户端非活动时间超时
timeout server   300000ms  后端处理超时(设太大防 502)
timeout check    5s        健康检查超时

4.调度算法

4.1 静态算法

static-rr:基于权重的轮询,不支持运行时动态调整权重(只支持 0 和 1)
first    :按列表顺序,第一台满连接后才调度到下一台(使用较少)

4.2 动态算法

roundrobin:基于权重的轮询(默认),支持运行时动态调整权重和慢启动
            每个 backend 最多支持 4095 个 real server
leastconn:加权最少连接,适合长连接场景(如 MySQL)
random   :基于随机数,适合大型服务器场或频繁增删服务器的场景

4.3 其他算法(可静态可动态)

source    :基于源地址 hash(会话保持,不适用 cookie 的场景)
            hash-type map-based  → 取模法(静态)
            hash-type consistent → 一致性 hash(动态,支持 socat 调整)

uri       :基于 URI hash(适用于后端是缓存服务器的场景,仅 HTTP 模式)

url_param :基于 URL 参数 hash(如 userid,可实现 session 保持)

hdr       :基于请求头 hash(如 User-Agent、Host)

rdp-cookie:基于 RDP cookie(Windows 远程桌面专用)

4.4 算法选择速查表

┌────────────────┬─────────────────────────────────────┐
│     算法        │           适用场景                   │
├────────────────┼─────────────────────────────────────┤
│ roundrobin     │ 通用场景(默认首选)                   │
│ leastconn      │ 数据库连接、长连接场景                  │
│ source         │ 基于客户端 IP 的会话保持               │
│ uri            │ CDN、缓存服务器                       │
│ url_param      │ 需要基于用户 ID 保持会话               │
│ hdr            │ 基于 User-Agent/Host 路由            │
│ rdp-cookie     │ Windows RDP 负载                     │
└────────────────┴─────────────────────────────────────┘

5.高级功能

1
2
3
4
5
listen web_port bind 10.0.0.7:80 mode http balance roundrobin
cookie WEBSRV insert nocache indirect
server web1 10.0.0.17:80 cookie web1 check inter 3000 fall 2 rise 5
server web2 10.0.0.27:80 cookie web2 check inter 3000 fall 2 rise 5
# 注意:仅支持 HTTP 模式,不支持 TCP

5.2 状态页(Stats Page)

1
2
3
4
5
6
7
8
9
listen stats
bind :9999
stats enable
stats uri /haproxy-status
stats auth haadmin:123456
stats refresh 30s
# 浏览器访问 http://<IP>:9999/haproxy-status
# 支持通过 curl 做健康检查:
curl -I -u haadmin:123456 http://10.0.0.7:9999/haproxy-status

状态页关键字段:

session rate    → 每秒连接会话(cur/max/limit)
sessions        → 当前/最大/总共会话量
Errors          → 错误请求/连接/响应数
Warnings        → 重试/重发次数
Server          → 状态(UP/DOWN)、权重、活动/备份连接数、检查状态
Bytes           → 输入/输出流量

5.3 IP 透传

四层透传(Proxy Protocol):

1
2
3
4
5
6
7
8
# HAProxy 端
listen web_http_nodes bind 172.16.0.100:80 mode tcp
balance roundrobin
server web1 www.wangxiaochun.com:80 send-proxy check inter 3000 fall 3 rise 5

# Nginx 后端
listen 80 proxy_protocol;
log_format main '$proxy_protocol_addr - $remote_user...';

七层透传:

1
2
3
4
5
6
7
# HAProxy 端
option forwardfor # 默认添加 X-Forwarded-For 头
option forwardfor except 127.0.0.0/8 # 排除内网
option forwardfor header X-client # 自定义头部名称

# Nginx 后端日志格式
log_format main '"$proxy_add_x_forwarded_for" - $remote_user...';

5.4 报文修改

1
2
3
4
5
6
7
8
# 请求报文添加/删除头部
http-request add-header X-Haproxy-Current-Date %T
http-request del-header Server

# 响应报文添加/删除头部
http-response add-header X-Via: HAproxy-1
http-response del-header Server # 隐藏后端信息
http-response del-header X-Powered-By # 隐藏 PHP 版本

5.5 自定义日志格式

1
2
3
4
5
log global
option httplog
capture request header Host len 256
capture request header User-Agent len 512
capture request header X-Forwarded-For len 15

5.6 压缩功能

1
2
3
compression algo gzip deflate
compression type text/html text/css text/plain text/xml text/javascript
# 注意:建议在后端服务器开启压缩,而非 HAProxy

5.7 健康检查

1
2
3
4
5
6
7
8
9
10
11
12
13
# 四种检查方式:
# 1. 四层 TCP 端口检查(默认)
server web1 10.0.0.17:80 check inter 3000 fall 3 rise 5

# 2. 基于 URI 的 HTTP 检查(完整页面,占用带宽)
option httpchk GET /monitor/check.html

# 3. 基于 URI 的 HEAD 检查(推荐,占用带宽少)
option httpchk HEAD /monitor/check.html HTTP/1.1\r\nHost:\ 10.0.0.7

# 4. 检查期望响应码
http-check expect status 200
http-check expect ! rstatus ^5

5.8 ACL 访问控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 语法:acl <name> <criterion> [flags] [operator] [<value>]
# 常见匹配规范:
acl pc_domain hdr_dom(host) -i www.magedu.org # 域名匹配
acl mobile_domain hdr_dom(host) -i mobile.magedu.org
acl ip_range src 172.18.0.0/16 10.0.0.6 # 源 IP/子网
acl static_file path_end -i .jpg .png .css .js # 文件后缀
acl api_path path_beg -i /api # 路径前缀
acl bad_agent hdr_sub(User-Agent) -i curl wget # 浏览器匹配
acl invalid_method method TRACE # HTTP 方法

# 组合调用(与/或/非):
use_backend static_host if static_file
use_backend app_host if !static_file
http-request deny if bad_agent

预定义 ACL:

FALSE           → never match
TRUE            → always match
HTTP            → 协议为 HTTP
HTTP_1.0/1.1    → HTTP 版本
LOCALHOST       → 源地址 127.0.0.1/8
METH_GET/POST/PUT/DELETE/TRACE → HTTP 方法
RDP_COOKIE      → 存在 RDP cookie

5.9 自定义错误页面

1
2
3
4
5
6
7
# 方式一:本地错误文件
errorfile 400 /etc/haproxy/errorfiles/400.http
errorfile 502 /etc/haproxy/errorfiles/502.http
errorfile 503 /etc/haproxy/errorfiles/503.http

# 方式二:重定向到远程 URL
errorloc 503 http://www.magedu.com/error_pages/503.html

5.10 四层负载均衡

1
2
3
4
5
6
7
8
9
# Redis 示例
listen redis-port bind 10.0.0.7:6379 mode tcp balance leastconn
server server1 10.0.0.17:6379 check
server server2 10.0.0.27:6379 check backup

# MySQL 示例
listen magedu_mysql bind 10.0.0.7:3306 mode tcp balance leastconn
server mysql1 10.0.0.17:3306 check
server mysql2 10.0.0.27:3306 check

5.11 HTTPS 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
# 证书制作(PEM 格式:私钥 + 证书合并)
openssl genrsa -out haproxy.key 2048
openssl req -new -x509 -key haproxy.key -out haproxy.crt -subj "/CN=www.magedu.org"
cat haproxy.key haproxy.crt > haproxy.pem

# HAProxy 配置
frontend https_port
bind 10.0.0.7:443 ssl crt /etc/haproxy/certs/haproxy.pem
bind 10.0.0.7:80
redirect scheme https if !{ ssl_fc } # HTTP 强制跳转 HTTPS
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
default_backend web_servers

6.动态管理(socat)

1
2
3
4
5
6
7
8
9
10
11
12
# 连接 Socket 进行运行时管理
echo "show info" | socat stdio /var/lib/haproxy/haproxy.sock
echo "show stat" | socat stdio /var/lib/haproxy/haproxy.sock
echo "show servers state" | socat stdio /var/lib/haproxy/haproxy.sock

# 动态调整权重
echo "get weight web_host/web1" | socat stdio /var/lib/haproxy/haproxy.sock
echo "set weight web_host/web1 3" | socat stdio /var/lib/haproxy/haproxy.sock

# 上下线服务器
echo "disable server web_host/web1" | socat stdio /var/lib/haproxy/haproxy.sock
echo "enable server web_host/web1" | socat stdio /var/lib/haproxy/haproxy.sock