> For AI agents: the complete documentation index is available at https://www.tteam.icu/llms.txt, the full documentation bundle is available at https://www.tteam.icu/llms-full.txt.

# haproxy

## 基本介绍

### HAProxy 特点

相比 LVS 和 Nginx，LVS 性能最好但搭建相对复杂。Nginx 的 upstream 模块支持集群功能，但对集群节点的健康检查功能不强，性能不如 HAProxy。

### 主要特性

- 可靠性和稳定性非常好，可以与硬件级的 F5 负载均衡设备相媲美
- 最高可以同时维护 40000-50000 个并发连接，单位时间内处理的最大请求数为 20000 个，最大处理能力可达 10Git/s
- 支持多达八种负载均衡算法，也支持会话保持
- 基于流量的健康评估机制，基于 HTTP 认证
- 基于命令行的管理接口，有日志分析器，可以对日志进行分析
- 有强大的 ACL 支持，用于访问控制(黑白名单)
- 支持虚拟主机的功能，从而实现 Web 负载均衡更加灵活

### LVS、Nginx、HAProxy 区别

1. LVS 基于 Linux 操作系统内核实现软负载均衡，而 HAProxy 和 Nginx 是基于第三方应用实现的软负载均衡
2. LVS 是可实现 4 层的 IP 负载均衡技术，无法实现基于目录、URL 的转发，而 HAProxy 和 Nginx 都可以实现 4 层和 7 层技术，HAProxy 可以提供 TCP 和 HTTP 应用的负载均衡综合解决方案
3. LVS 因为工作在 ISO 模型的第四层，其状态检测功能单一，而 HAProxy 在状态检测方面功能更丰富、强大，可支持端口、URL、脚本等多种状态检测方式
4. HAProxy 功能强大，但整体性能低于 4 层模式的 LVS 负载均衡
5. Nginx 主要用于 Web 服务器或者缓存服务器，Nginx 的 upstream 模块虽然也支持集群功能，但对集群节点健康检查功能不强，性能没有 HAProxy 强

### 总体来说

反向代理、前端部署等 HTTP 服务，都使用 Nginx。

如果需要用到 TCP 转发，就需要用到 HAProxy(HAProxy 和 FRP 从 TCP 转发角度来说，HAProxy 的性能更高，所以生产环境的 TCP 转发需要使用 HAProxy)。

## 部署

```tree
.
├── config
│   └── haproxy.cfg
├── reload.sh
└── setup.sh
```

### 启动脚本

```sh file="./haproxy/setup.sh" title="setup.sh"
#!/bin/bash
docker stop haproxy
docker rm haproxy
docker run -d --network host --name haproxy \
--restart=always \
-v /etc/timezone:/etc/timezone:ro \
-v /etc/localtime:/etc/localtime:ro \
-v $(pwd)/config/:/usr/local/etc/haproxy/:ro \
haproxy:2.8.1-alpine
```

### 重载脚本

```sh file="./haproxy/reload.sh" title="reload.sh"
#!/bin/bash

if [ `docker run -i --rm --name haproxy-syntax-check -v $(pwd)/config/:/usr/local/etc/haproxy/:ro haproxy:2.8.1-alpine haproxy -c -f /usr/local/etc/haproxy/haproxy.cfg|grep -E -c "Configuration file is valid"` = 1 ];then
	docker kill -s HUP haproxy && echo "reload haproxy"
else
	echo "配置文件无效"
fi
```

## HAProxy 基本配置

### global 配置

全局配置部分，一般设置进程级别的配置。

示例:

```bash
global
    log         127.0.0.1 local3  # 表示使用本地 127.0.0.1 上的 rsyslog 服务器中的 local3 设备记录
#    chroot      /var/lib/haproxy
#    pidfile     /var/run/haproxy.pid
    maxconn     100000     # 整个 HAProxy 实例的最大连接数限制为 100000
#    user        haproxy
#    group       haproxy
    daemon    # HAProxy 将在后台以守护进程的形式运行
```

### defaults 配置

定义默认配置，所有的 frontend、backend 和 listen 都从该区段继承默认配置。如果在这些区段中重新声明指令配置项，则会覆盖 defaults 中的配置。

示例:

```bash
defaults
    mode        tcp
    log         global
    option      tcplog
    # log-format {"client_ip":"%ci","client_port":"%cp","date_time":"%t","frontend_name_transport":"%ft","backend":"%b","server_name":"%s","time":"%Tq/%Tw/%Tc/%Tr/%Tt","bytes_read":"%B","connection":"%ac/%fc/%bc/%sc/%rc","queue":"%sq/%bq","backend_source_ip":"%bi","backend_source_port":"%bp","status_code":"%ST","http_request":%r,"request_headers":"%hrl","response_headers":"%hsl"}
    #option      forwardfor
    option      redispatch
    timeout connect 600s # 连接建立的超时时间为 600 秒
    timeout client 600s  # 客户端连接的超时时间为 600 秒
    timeout server 600s  # 服务器连接的超时时间为 600 秒
    maxconn     60000    # 默认的最大连接数限制为 60000
    retries     3		 # 尝试连接失败后的重试次数为 3 次
```

### listen 配置

该区段定义了一个完整的代理，属于 frontend 和 backend 的结合体，在新版中该区段不是必须的。但在老版本中所有的配置都在这一部分完成，为保证配置的兼容性，这一部分被保留。

示例:

```bash
listen admin_stats					# 监听器名字
    stats   enable                      # 启用统计信息收集，允许通过 HTTP 访问 HAProxy 的统计信息
    bind    *:65000                     # 该监听器监听所有网络接口上的 65000 端口
    mode    http                        # 处理的是 HTTP 请求
    option  httplog                     # 启用了 HTTP 日志记录，将记录有关 HTTP 请求和响应的详细信息
    log     global                      # 日志记录的位置和级别，将使用 global 部分定义的设置
    maxconn 10                          # 限制了该监听器的最大连接数为 10 个
    stats   refresh 30s                 # 统计信息页面的刷新频率为 30 秒
    stats   uri /admin                  # 访问统计信息页面的 URI 为 /admin
    stats   realm haproxy               # 统计信息页面的域名称为 haproxy
    stats   auth admin:admin            # 访问统计信息页面所需的用户名和密码为 admin:admin
    stats   hide-version                # 隐藏统计信息页面中的 HAProxy 版本信息
    stats   admin if TRUE               # 根据条件是否启用统计信息页面，这里设置为始终启用
```

### Prometheus 监控收集

```bash
frontend stats
   bind *:8404
   http-request use-service prometheus-exporter if { path /metrics }
   stats enable
   stats uri /stats
   stats refresh 10s
```

### 转发 TCP

```bash
listen grafana
    bind 0.0.0.0:13000
    mode tcp                            # 监听器配置为 TCP 模式，即处理的是 TCP 连接
    option tcplog                       # 启用了 TCP 日志记录，将记录有关 TCP 连接的详细信息
    timeout connect 60000s
    timeout client 60000s
    timeout server 60000s
    balance roundrobin                  # 使用 Round Robin 负载均衡算法来分配请求给后端服务器
    option tcpka                        # 启用了 TCP 保持活动功能，以在客户端和服务器之间保持长连接
    server s1 172.168.1.58:3000         # 指定了一个后端服务器，其中 s1 是服务器的名称
```

## send-proxy 模式

在 HAProxy 中，send-proxy 模式是一种功能，用于在代理之间传递客户端的原始连接信息。它允许在代理之间传递客户端的原始 IP 地址和端口信息，而不是只传递已经建立的连接。

通常情况下，在 TCP 代理中，当客户端连接到代理时，代理会建立一个新的连接到后端服务器，而此时代理服务器和后端服务器之间的连接是新建立的，与客户端的连接不同。这就导致后端服务器无法获取客户端的真实 IP 地址。

但是，通过使用 send-proxy 模式，代理服务器可以在与后端服务器建立连接时，发送客户端的原始连接信息，包括客户端的 IP 地址和端口等。后端服务器收到这些信息后，就可以知道客户端的真实 IP 地址，并可以根据需要进行相应的处理，比如记录日志、做访问控制等。

```
server backend1 192.168.1.10:80 send-proxy
```

这会告诉 HAProxy 在与后端服务器建立连接时，发送客户端的原始连接信息。在后端服务器的配置中，你也需要相应地配置以接收这些信息。

总的来说，send-proxy 模式可以帮助你解决代理服务器无法获取客户端真实 IP 地址的问题，提高了代理服务的灵活性和功能性。

当你启用 send-proxy 模式后，在与后端服务器建立连接时，HAProxy 会在 TCP 数据包的头部添加一些特殊的代理协议头。这些头部信息包含了客户端的 IP 地址和端口，以及一些其他的元数据。
