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)。

部署

config
haproxy.cfg
reload.sh
setup.sh

启动脚本

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

重载脚本

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 配置

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

示例:

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 中的配置。

示例:

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 的结合体,在新版中该区段不是必须的。但在老版本中所有的配置都在这一部分完成,为保证配置的兼容性,这一部分被保留。

示例:

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 监控收集

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

转发 TCP

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 地址和端口,以及一些其他的元数据。