Contents
前言
如之前一篇文章末尾所说(参见文章:docker系列 Traefik文件动态配置实战:本地网络负载均衡的高效实现),我对Traefik来实现家庭数据中心内网里主博客站点和备份博客站点的负载均衡(热备)还是不太满意,考虑了一下,还是准备尝试一下HAProxy,毕竟这才是传统的对(非docker环境、非k8s环境的)应用进行负载均衡的专业解决方案:Traefik设计的初衷就是为微服务和容器化环境设计的,让它来干传统的负载均衡本来就有点水土不服。当然,最关键是又可以水一篇文章~。
注:阅读本文需要对传统负载均衡(另一个称呼为”应用交付”)有一定了解,因为需要该领域的很多基础知识,否则阅读起来可能会有一定不适(头晕、瞌睡等副作用~)。
HAproxy介绍
HAProxy 是一款高性能、可靠的开源负载均衡器和反向代理软件,广泛应用于 Web 服务、数据库和其他高并发场景。它支持 L4(传输层)和 L7(应用层)的流量分发,提供丰富的功能,包括多种调度算法、细粒度的健康检查、SSL/TLS 终止、会话保持等。凭借卓越的性能、稳定性和灵活性,HAProxy 成为众多企业和大规模网站的首选负载均衡解决方案。
相比其他常见的免费的应用负载均衡软件,HAproxy在功能全面性、性能、配置方面都有有独特的优势:
软件 | 特点 | 对比 HAProxy 的劣势 |
---|---|---|
Nginx | 轻量级,广泛用于反向代理,支持 L4 和 L7。 | 负载均衡功能不是核心,性能和灵活性稍逊,配置复杂度高于 HAProxy。 |
LVS | 内核级负载均衡,性能极高,适合超大规模流量场景。 | 仅支持 L4,缺少应用层功能,配置复杂,调试较困难。 |
Apache | 功能丰富,模块化设计,适合已有 Apache 环境。 | 性能远不如 HAProxy,配置复杂且对高并发支持较差。 |
Keepalived | 与 LVS 配合使用可实现高可用性,适合简单场景的健康检查和故障转移。 | 独立使用功能有限,偏向健康检查和高可用,非专业负载均衡器。 |
Pen/Balance | 轻量级负载均衡器,简单易用,适合小规模环境。 | 功能非常有限,仅支持基本的负载均衡需求,不适合复杂场景。 |
所以,从传统专业负载均衡软件的角度来看,HAProxy 是目前免费的负载均衡软件中最全面、最成熟的解决方案之一,特别是在以下几个方面表现得尤为突出:
1. 性能和稳定性
• 高性能:HAProxy 是专门为负载均衡设计的,优化程度非常高,单实例即可轻松支持数十万甚至上百万的并发连接。
• 稳定性:经过多年的实践检验,HAProxy 在生产环境中表现非常稳定,被广泛用于全球大流量网站和企业中。
2. 功能全面
• 支持多种协议:支持 TCP 和 HTTP/HTTPS 协议,涵盖从 L4(传输层)到 L7(应用层)的负载均衡需求。
• 多样化调度算法:支持轮询、最少连接、源地址哈希、权重等多种负载均衡算法。
• 健康检查:提供细粒度的后端健康检查,确保只有健康的后端服务器接收流量。
• SSL/TLS 终止:支持终止和转发 SSL/TLS 流量,简化后端配置。
• HTTP 层功能:支持 URL 重写、请求和响应修改、会话保持等高级功能。
3. 易于扩展和集成
• 高可用性:HAProxy 可以与 Keepalived 配合使用,实现高可用性架构(Active-Passive 或 Active-Active)。
• 动态后端管理:支持动态添加或移除后端服务器,无需重启服务。
• 日志与监控:提供详细的日志功能,并能与 Prometheus、Grafana 等监控工具集成。
4. 社区和支持
• 强大的社区:HAProxy 的社区非常活跃,文档详尽,遇到问题时容易找到解决方案。
• 企业支持:HAProxy 提供了商业版本(HAProxy Enterprise),包括更多功能(如高级健康检查、快速补丁支持等)和专业支持服务。
为什么说 HAProxy 是最全面的?
• 功能覆盖广:从小型应用到企业级部署,从简单的轮询到复杂的会话保持,HAProxy 几乎可以满足所有需求。
• 高性能和灵活性兼具:即使是高并发场景,HAProxy 依然可以灵活处理复杂规则。
• 适应传统应用场景:相比像 Traefik 这样的现代工具,HAProxy 的配置方式更加传统、直观,更适合非容器化环境。
• 易用性和文档:虽然配置文件初看可能稍显复杂,但逻辑清晰且文档丰富,学习成本相对较低。
因此,HAProxy 是传统专业负载均衡场景下的首选,尤其是在需要稳定性、性能和灵活性的应用中。
另:原本我对Traefik还充满期望,但是试用之后还是失望了。
HAproxy的部署
部署方式的选择
HAproxy有2种部署方式,源码安装(以APT方式为例)和docker安装,两种方式的优劣势对比如下:
对比项 | 源码方式部署 | Docker方式部署 |
---|---|---|
优势 | ||
部署复杂度 | 通过包管理器安装,简单快捷,无需额外工具支持。 | 无需复杂依赖,仅需 Docker 环境即可快速启动,适合跨平台部署。 |
灵活性 | 配置直接修改系统文件,操作方便,无容器限制。 | 可通过挂载配置文件和环境变量调整,隔离性强,适应不同场景。 |
性能表现 | 无容器开销,性能稳定,适合高并发场景。 | 性能适合大多数通用场景,环境隔离性强,对宿主机环境影响小。 |
更新维护 | 使用 apt upgrade 自动更新,简化维护流程。 |
镜像更新便捷,只需拉取新版本镜像并重启容器。 |
依赖管理 | 包管理器自动处理依赖,减少冲突问题。 | 镜像内封装所有依赖,隔离性强,不会干扰宿主机环境。 |
可移植性 | 使用操作系统原生方式部署,适合长期运行的固定环境。 | 镜像跨平台运行,环境兼容性强,适合分布式部署需求。 |
资源消耗 | 无容器额外开销,资源利用率高,适合资源敏感型场景。 | 容器化技术优化良好,资源隔离高效,现代系统几乎无额外负担。 |
调试难度 | 直接使用系统工具调试,操作灵活,易于排查问题。 | 容器隔离方便在不同环境中快速调试和排查问题。 |
社区支持 | 官方仓库和文档维护稳定,适合长期支持需求。 | Docker 社区活跃,资源丰富,支持快速解决问题。 |
劣势 | ||
部署复杂度 | 需管理员权限,且依赖操作系统版本,可能存在支持限制。 | 需要预先安装 Docker 环境,增加学习和维护成本。 |
灵活性 | 灵活性受限于操作系统版本,无法像源码安装那样自由调整参数。 | 镜像中依赖版本固定,需重新构建镜像以调整功能或优化。 |
性能表现 | 可能需要额外的系统级优化以满足特定性能需求。 | 容器有少量性能开销,极限场景下性能不如直接运行的本地服务。 |
更新维护 | 版本更新依赖系统仓库,可能滞后于官方最新版本。 | 需定期拉取并验证镜像来源的可靠性,防止镜像质量参差导致问题。 |
依赖管理 | 受系统仓库依赖版本限制,可能遇到部分版本不兼容的情况。 | 镜像内依赖版本不可更改,灵活性不足。 |
可移植性 | 依赖操作系统环境,跨平台能力较弱,不适合异构环境。 | 运行需要 Docker 支持,对传统环境兼容性较差。 |
调试难度 | 需要熟悉系统服务的调试工具和日志管理方式,对新手有一定门槛。 | 调试可能需要进入容器内部,增加一定复杂性。 |
社区支持 | 社区资源较少,问题解决可能需要更多时间。 | 镜像质量参差不齐,需甄别官方和可信来源。 |
这两种方式各有优劣,大家可以按需选择,我两种部署方式都会介绍。
从稳定性的角度来看,源码方式部署相比于Docker方式部署更有优势:
- 更少的依赖层
源码部署直接依赖操作系统和编译环境,减少了因容器环境(如Docker版本、基础镜像等)变化引发的兼容性问题。
- 更高的可控性
源码部署可以精细控制版本、编译参数和依赖,适合需要特定优化的生产环境,而Docker镜像可能使用通用配置,灵活性较低。
- 更新与维护稳定性
源码部署时,更新受制于手动操作和测试流程,风险可控;而Docker镜像更新可能带入额外的不兼容或不必要的组件。
- 性能与资源优化
源码部署直接运行在宿主机上,无需容器额外的抽象层,性能和资源占用可能更优。
适用场景:源码方式更适合对性能、稳定性要求极高的核心业务系统。
源码方式部署(APT方式)
源码方式部署HAProxy也有几种方式,我以最简单的APT方式为例:
apt update
apt install haproxy
确保 HAProxy 服务已经启动,然后可以通过命令查看其状态:
systemctl status haproxy
如果正常的话显示如下:
通过源码方式(APT)安装的HAProxy,其haproxy.cfg配置文件的路径位于:
/etc/haproxy/haproxy.cfg
可以用以下命令查看其内容:
cat /etc/haproxy/haproxy.cfg
输出如下:
docker方式部署
docker run方式部署
1、创建工作目录:
mkdir -p /docker/haproxy
2、创建预配置文件haproxy.cfg:
vim /docker/haproxy/haproxy.cfg
然后预先定义好的配置文件内容粘贴进去并保存(配置文件的具体格式参考文章后面的”配置文件:haproxy.cfg”部分的内容)。
3、可选步骤:如果需要haproxy进行SSL证书卸载(解密),将SSL证书和私钥文件放到宿主机的指定路径,假设为”/etc/ssl/certs”目录。
4、使用docker run方式部署的命令如下:
docker run --name haproxy -d -p 80:80 -p 443:443 --restart=always \
-v /docker/haproxy:/usr/local/etc/haproxy \
-v /etc/ssl/certs/certificate.crt:/etc/ssl/certs/mydomain.pem \
-v /etc/ssl/certs/private.key:/etc/ssl/private/mydomain.key \
haproxy:latest
docker-compose方式部署
如果使用docker-compose方式来部署,上一节内容中的第1、2、3步保持不变,而从第4步开始就变为:
4、创建docker-compose.yml文件:
vim /docker/haproxy/docker-compose.yml
然后把如下内容粘贴进去并保存:
version: '3.8'
services:
haproxy:
image: haproxy:latest
container_name: haproxy
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- /docker/haproxy:/usr/local/etc/haproxy
- /etc/ssl/certs/certificate.crt:/etc/ssl/certs/mydomain.pem
- /etc/ssl/certs/private.key:/etc/ssl/private/mydomain.key
5、启动服务:
cd /docker/haproxy
docker-compose up -d
注:采用docker方式部署HAproxy的确不够灵活,要在一开始就确定能够提供负载均衡服务的端口(比如上述配置中的80和443,因为需要确定-p
参数需要映射的宿主机到容器内部的端口),这种方式对于HTTP类型的应用倒还可以接受(可以通过域名的方式区分不同的应用),但是对于TCP和UDP类型的应用就很不友好了。所以,如果不仅仅有HTTP类型的应用,还有TCP、UDP类型的应用需要做负载均衡,建议使用源码方式部署。
配置文件:haproxy.cfg
前置知识:负载均衡(Load Balancing)基本概念梳理
注:为了便于理解HAproxy配置文件里的一些选项的含义,需要先对负载均衡中几个主要概念进行简单描述,对技术细节不感兴趣的朋友可以略过这部分内容。
一. VIP(虚拟IP地址)
• 通俗解释:VIP就像一个虚拟的门牌号,它是负载均衡系统对外展示的“入口地址”。
• 作用:当你访问一个网站时,你其实是在访问这个VIP,系统会把你的请求分配给具体的服务器处理。这样,即使后面的服务器发生变化(如增加或减少数量),VIP始终是访问的固定地址。
注:对于VIP这个概念而言,由于HAProxy 本身无法直接处理底层网络协议(如 ARP),因此只能对其宿主机网络接口上已绑定的 IP 地址进行响应。HAproxy要使用特定的虚拟 IP 地址(VIP),需要先在操作系统中手动将 VIP 绑定到网卡上,或者通过工具如 Keepalived 管理 VIP 并确保操作系统响应 ARP 请求。相比专业负载均衡器(如 F5、A10)直接内置的 VIP 和 ARP 支持,HAProxy 更依赖宿主机的网络配置来完成这些功能。
二. 服务器(具体应用的IP和端口)
• 通俗解释:服务器是处理具体任务的工人,它们有自己的“住址”(IP)和“岗位编号”(端口)。
• 作用:每个服务器负责完成用户请求,比如加载网页、处理数据等。负载均衡器会根据规则把任务分配给这些服务器。
三. 服务组(多个服务器的集合)
• 通俗解释:服务组可以理解为一队工人,这些工人共同完成同一类型的任务。
• 作用:通过把服务器组织成一个组,负载均衡器可以更高效地分配工作,比如当其中一个工人太忙或请假时,任务会被分配给其他工人。
四. 健康检查
• 通俗解释:健康检查就像是给工人做体检,确保他们能正常工作。
• 作用:负载均衡器会定期检查服务器是否健康(比如网络是否畅通、服务是否能正常响应)。如果发现某个服务器生病了,就会暂时停止给它分配任务,避免影响用户体验。
五. 会话保持
• 通俗解释:会话保持就像是给工人配备了专门的工具包,确保同一个客户总是由同一个工人来为其服务。
• 作用:在负载均衡中,会话保持确保同一个用户的请求总是被发送到同一台服务器。比如,你在购物网站浏览商品时,每次请求都会指向同一台服务器,这样网站可以记住你之前的操作,提供连续的体验。
六. 工作模式(TCP、UDP、HTTP)
• 通俗解释:工作模式就像是不同的工作环境。TCP、UDP和HTTP就像是三种不同类型的工作场所,每种环境都有自己的规则和需求。
• 作用:负载均衡器通过选择不同的工作模式来处理不同类型的流量:
• TCP模式:处理传统的网络通信流量,比如FTP、telnet等。
• UDP模式:处理实时性要求较高的流量,比如视频、语音等。
• HTTP模式:专门处理网页浏览流量,用户通过浏览器访问网站时的数据请求。
七. 连接优化(连接重用、限制最大连接)
• 通俗解释:连接优化就像是管理工人的工作效率。连接重用是指多次使用同一个工具,限制最大连接是确保工人不会被过多的工作压垮。
• 作用:
• 连接重用:通过允许多个请求使用同一个连接,避免了重复建立连接的开销,提高效率。
• 限制最大连接:防止某台服务器过载,负载均衡器通过设置最大连接数来保证服务器能够处理的请求数量适中,不至于超负荷工作。
八. SNAT(源地址转换)
• 通俗解释:SNAT就像是给任务加上统一的“身份标签”,确保每个工人的操作都不会混淆,并且能够正确地返回任务的反馈。
• 作用:SNAT(源地址转换)用于修改数据包的源IP地址。当多个客户端通过负载均衡器访问服务器时,SNAT可以将客户端的源IP地址替换为负载均衡器的IP地址。这样,服务器接收到的请求来源是负载均衡器,而不是直接来自客户端的真实IP地址。
九. SSL offload(SSL卸载)
• 通俗解释:SSL Offload 就像是在工厂的入口设置一个专门的解密站,把所有加密的信息先解开整理好,然后再送到车间加工,这样车间就可以专注于生产,而不用花时间解密。
• 作用:SSL Offload(SSL 卸载)用于在负载均衡器或专用设备上处理 HTTPS 的加解密任务。客户端与负载均衡器之间通过加密连接(HTTPS)通信,负载均衡器解密后,将明文数据转发给后端服务器(通常使用 HTTP)。这种方式减轻了后端服务器的计算负担,从而提高了整体性能。
根据不同的负载均衡部署方式,SNAT的使用方式有所不同。
1. 串行部署模式下的SNAT
在串行部署模式下,负载均衡器位于流量的必经之路,直接插入到客户端与服务器之间。这种方式下,SNAT是可选的,因为负载均衡器已经在流量的路径中,它可以通过修改源IP来实现源地址转换。然而,即使没有SNAT,负载均衡器仍然能够正确地将流量转发到服务器并处理响应。
• 举例:假设负载均衡器位于流量的中间位置,客户端发起的请求先到达负载均衡器,负载均衡器再将请求转发给后端服务器。如果没有SNAT,服务器会看到客户端的真实IP地址,负载均衡器只是负责流量分发。但若启用SNAT,负载均衡器会将请求的源IP改为自己的IP地址,这样服务器看到的请求都来自负载均衡器。
2. 旁路部署模式下的SNAT
在旁路部署模式下,负载均衡器位于流量路径之外,客户端与服务器之间并没有直接的联系。此时,SNAT是必须的,因为它保证了流量的往返路径对称。负载均衡器必须修改客户端请求的源IP地址,否则服务器会将响应返回给客户端的原始IP地址,而不是负载均衡器的IP,这会导致请求失败或响应丢失。
• 举例:在旁路部署中,客户端请求到达服务器后,服务器会直接向客户端返回响应。如果没有SNAT,服务器会尝试直接将响应发送回客户端的真实IP地址,但由于流量并未经过负载均衡器,响应不会正确到达客户端。通过启用SNAT,负载均衡器将客户端的源IP替换为自己的IP地址,确保服务器的响应能够正确地通过负载均衡器返回给客户端。
3. SNAT在不同工作模式下的使用
• HTTP模式:在HAProxy的HTTP模式下,SNAT通常并不需要。因为在HTTP模式下,HAProxy处理的是基于HTTP协议的流量,且每个请求都会通过建立新的TCP连接来转发。由于是短连接,每次请求和响应都是独立的,因此客户端的源IP会直接传递给后端服务器,HAProxy并不需要修改源IP。这个模式下的流量是短暂的,不需要通过SNAT来保证会话的正确性。
• TCP/UDP模式:在TCP和UDP模式下,连接是长连接,负载均衡器负责持续处理流量。在这种模式下,SNAT是必需的。由于连接保持不变,HAProxy需要通过修改源IP地址来确保所有后端服务器的响应都能够通过负载均衡器返回给客户端。如果没有SNAT,服务器可能会将响应发送到客户端的真实IP地址,导致响应路径不对称,最终无法正确返回给客户端。
总结
• 串行部署模式:SNAT是可选的,负载均衡器直接插入流量路径,可以选择是否进行源地址转换。
• 旁路部署模式:SNAT是必需的,确保了连接的往返路径对称,避免响应流向错误的目标。
• HTTP模式:由于每个请求是独立的短连接,通常不需要SNAT。
• TCP/UDP模式:需要SNAT来保证连接的持续性和正确的返回路径。
另:不想在本文中里讲太多负载均衡的原理,因为要讲的话几句话根本讲不清楚,而且也不是本文的重点。对负载均衡技术原理感兴趣的朋友,可以参考我之前写的一个ppt(转的pdf),链接地址如下:负载均衡基础概念介绍,这个ppt要讲才能达到最好的体验,只靠看的话,最多能有个3成的体验(转成pdf后动画效果也没了~),不过也能将就看一下了。本来是想偷懒找个好的文章随便帖个链接的,结果在网上找半天都找不到合适的,只能拿自己以前的ppt把不相关的删了后来顶一下。由于是面向用户的售前文档,所以技术性不那么强,刚好适合入门级介绍。
haproxy.cfg内容讲解
不管是用哪种方式部署HAProxy,最终都会涉及到配置文件”haproxy.cfg”,只不过,使用源码方式(APT)部署时,会自动使用默认内容生成该文件(默认路径:/etc/hparoxy/haproxy.cfg
);而使用docker方式部署时,则需要自己提前准备(因为要使用-v参数进行挂载)。
以下提供一份包含了前面提到的负载均衡基本概念的”haproxy.cfg”示范内容,假设需要负载均衡的http应用对应的服务器分别是192.168.1.11:8080、192.168.1.12:8080以及192.168.1.13:8080和192.168.1.14:8080且需要使用域名区分访问请求,需要配置健康检查,会话保持,使用指定地址进行SNAT,同时还配置了连接重用和服务器最大连接数限制等功能:
# 全局设置
global
log stdout format raw local0 # 日志输出到标准输出,便于调试和监控
maxconn 2000 # 全局最大连接数限制,防止过载
tune.ssl.default-dh-param 2048 # 设置SSL连接的默认DH参数大小
daemon # 后台运行
stats socket /var/run/haproxy.sock mode 660 level admin # 管理套接字,用于动态调整配置
nbthread 4 # 使用4个线程以充分利用多核CPU,提高并发性能
# 默认设置
defaults
log global # 继承全局日志设置
option httplog # 启用HTTP日志记录
option dontlognull # 对空连接请求不记录日志
timeout connect 5s # 连接超时设置为5秒
timeout client 30s # 客户端超时时间
timeout server 30s # 服务器超时时间
timeout http-request 10s # HTTP请求超时时间
timeout http-keep-alive 15s # 保持长连接超时时间
maxconn 1000 # 默认最大连接数
retries 3 # 连接失败时重试3次
# 前端监听配置 - HTTP
frontend http_front
bind *:80 # 监听80端口
mode http # 使用HTTP模式
option http-server-close # 每次请求后关闭与客户端的连接
acl host_app1 hdr(host) -i app1.example.com # 匹配域名app1.example.com
acl host_app2 hdr(host) -i app2.example.com # 匹配域名app2.example.com
use_backend app1_backend if host_app1 # 如果匹配域名app1.example.com,则转发到app1_backend
use_backend app2_backend if host_app2 # 如果匹配域名app2.example.com,则转发到app2_backend
default_backend default_backend # 如果域名不匹配,转发到默认后端
# 前端监听配置 - HTTPS
frontend https_front
bind *:443 ssl crt /etc/ssl/private/haproxy.pem # 监听443端口并启用SSL,使用证书文件haproxy.pem
mode http # 使用HTTP模式
option http-server-close # 每次请求后关闭与客户端的连接
acl host_app1 hdr(host) -i app1.example.com # 匹配域名app1.example.com
acl host_app2 hdr(host) -i app2.example.com # 匹配域名app2.example.com
use_backend app1_backend if host_app1 # 如果匹配域名app1.example.com,则转发到app1_backend
use_backend app2_backend if host_app2 # 如果匹配域名app2.example.com,则转发到app2_backend
default_backend default_backend # 如果域名不匹配,转发到默认后端
# 后端配置 - 应用1
backend app1_backend
mode http # 使用HTTP模式
option httpchk GET /health # 健康检查路径
balance roundrobin # 轮询负载均衡策略
server app1 192.168.1.11:8080 check # 后端服务器1
server app2 192.168.1.12:8080 check # 后端服务器2
option redispatch # 如果会话保持的服务器不可用,则重新分配到其他健康的服务器
option http-keep-alive # 后端启用长连接
default-server maxconn 100
# 后端配置 - 应用2
backend app2_backend
mode http # 使用HTTP模式
option httpchk GET /health # 健康检查路径
balance roundrobin # 轮询负载均衡策略
source 192.168.1.100 # 使用指定的地址作为SNAT的地址,而非默认的HAproxy宿主机IP
server app3 192.168.1.13:8080 check # 后端服务器1
server app4 192.168.1.14:8080 check # 后端服务器2
# 默认后端配置
backend default_backend
mode http # 使用HTTP模式
balance roundrobin # 轮询负载均衡策略
server default1 192.168.1.15:8080 check # 默认后端服务器
# 统计页面配置
listen stats
bind *:8085 # 监听端口8085
mode http # 使用HTTP模式
stats enable # 启用统计页面
stats uri /stats # 统计页面路径
stats realm Haproxy\ Statistics # 设置统计页面标题
stats auth admin:password # 设置访问统计页面的用户名和密码
stats admin if TRUE # 允许管理员权限
以前面提到的九点负载均衡基本概念的角度来解读以上配置:
配置内容解析:
- VIP(虚拟IP地址)
配置体现:
bind * :80
bind * :443 ssl crt /etc/ssl/certs/haproxy.pem。
解释:VIP 在配置中表现为监听的 IP 和端口组合。HAProxy 默认响应所有宿主机绑定的 IP 地址(如 * ),但如果需要特定的 VIP,必须在操作系统中事先绑定该 IP,或通过工具(如 Keepalived)实现。
- 服务器(具体应用的IP和端口)
配置体现:
server app1 192.168.1.11:8080 check
server app2 192.168.1.12:8080 check
解释:每个 server 定义了一台后端服务器,包括其 IP 和端口。check 参数开启健康检查,确保服务器状态可用。
- 服务组(多个服务器的集合)
配置体现:
backend app_backend
server app1 192.168.1.11:8080 check
server app2 192.168.1.12:8080 check
解释:backend 代表服务组的配置,其中包含多个 server。服务组是 HAProxy 实现负载均衡的基本单元。
- 健康检查
配置体现:
option httpchk GET /health
解释:配置为通过 HTTP 的 /health 路径检查服务器健康状态。如果后端服务器返回非 2xx 或 3xx 的响应码,则认为该服务器不可用。
- 会话保持
HAproxy默认未配置会话保持,如果要进行配置,HTTP模式和TCP、UDP模式略有不同:TCP和UDP一般使用基于源IP地址的会话保持,而HTTP模式,除了可以使用基于源IP地址的会话保持,还可以使用基于cookie的会话保持。
配置体现:
HTTP模式基于cookie的会话保持
cookie SERVERID insert indirect nocache
解释:为每个客户端插入一个 cookie,标记其关联的服务器。这样可以确保客户端的后续请求指向同一台服务器,从而保持会话连续性。
TCP或者UDP模式基于源IP地址的会话保持
# 创建 stick-table 用于源地址粘性会话保持
stick-table type ip size 200k expire 30m store conn_cur,conn_rate
# 基于源地址进行会话保持
stick on src # 使用客户端源 IP 地址进行会话保持
解释:基于源地址的会话保持通过记录客户端的 IP 地址,将其与某一台后端服务器绑定。这样一来,每次同一客户端发送请求时,负载均衡器都会根据记录将其请求始终转发到相同的服务器上。这种方式无需依赖客户端支持 cookie,适合协议不支持 cookie 或需要简化会话管理的场景。
- 工作模式(TCP、UDP、HTTP)
配置体现:
frontend http_front 中的 mode http
backend tcp_backend 中的 mode tcp
解释:配置中使用 HTTP 模式处理 Web 流量,使用 TCP 模式处理其他应用(如数据库)的流量。不同模式适配不同的协议需求。
- 连接优化(连接重用、限制最大连接)
配置体现:
option http-keep-alive
default-server maxconn 100
解释:设置了 HTTP的连接复用,减少连接建立和关闭的开销;同时限制单台服务器最大连接数,避免过载。
- SNAT(源地址转换)
配置体现:
source 192.168.1.100
解释:通过 source 指定 SNAT 使用的源 IP 地址(这个地址必须是 HAProxy 部署设备上的合法 IP 地址),而非默认的 HAProxy 监听地址。这样配置后,HAproxy将使用指定的源 IP 地址来进行源地址转换(SNAT),而不是使用默认的绑定 IP 地址。
九. SSL offload(SSL卸载)
配置体现:
bind *:443 ssl crt /etc/ssl/certs/haproxy.pem
解释:监听 HTTPS 流量并使用 SSL 证书进行解密(haproxy.pem),解密后的明文流量通过 HTTP 转发到后端服务器,减轻后端服务器的计算压力。
注:所有SSL卸载只需要在前端进行配置即可,所有后端统一使用HTTP模式配置。
总结:
此配置文件全面涵盖了HAProxy的关键功能,包括VIP绑定、服务器管理、健康检查、工作模式选择、连接优化、SNAT配置、SSL offload等。
注1:以上配置文件内容只是我认为对个人使用来说常用的内容,HAproxy还有很多其他选项,我并未一一列举出来,大家如果有其他特殊要求请常看官方文档:https://docs.haproxy.org/。
注2:我为了能够在一个示范配置中能够尽可能多的讲解这些选项,所以配置看起来比较复杂,但是在日常的使用时,没有那么多需求的话,配置文件会很简单。
注3:以上九点只是我认为的负载均衡最常用的概念,由于负载均衡本来就是一个技术领域(虽然比较小众),里面技术点实在是太多,并且主要是用在商用领域,对于个人来说没必要了解太深,所以本文中就不多涉及了,感兴趣的朋友可以自行在网上搜索。
使修改后的配置文件内容生效
如果按照前面示范内容自定义了haproxy.cfg内容,需要重新载入haproxy配置以让修改内容生效:
systemctl reload haproxy
之后,假设HAproxy的宿主机IP是192.168.1.200,那么只需要做好相关的DNS解析:将app1.example.com和app2.example.com都解析到192.168.1.200,然后就可以实现如下负载均衡的效果:
访问http://app1.example.com
和https://app1.example.com
会负载均衡到192.168.1.11:8080和192.168.1.12:8080
访问http://app2.example.com
和https://app2.example.com
会负载均衡到192.168.1.13:8080和192.168.1.14:8080
直接访问http://192.168.1.200
和https://192.168.1.200
会直接分配到默认的后端服务器:192.168.1.15:8080
和HAproxy相关的命令行工具
HAProxy 提供了几种常用的命令行工具,再结合一些系统自带的工具,就可以实时查看和管理其状态、配置以及运行时信息,就可以以下是一些HAproxy相关的常用工具和命令:
1. haproxy -v – 查看 HAProxy 版本
• 这个命令用于查看 HAProxy 的版本信息。
haproxy -v
输出示例:
HAProxy version 2.3.9-2+deb11u1 2021/12/01
Copyright 2000-2021 HAProxy Technologies
2. haproxy -c -f /path/to/haproxy.cfg – 检查配置文件语法
• 在启动或重载 HAProxy 之前,你可以使用此命令检查配置文件的语法是否正确。
haproxy -c -f /etc/haproxy/haproxy.cfg
输出示例:
Configuration file /etc/haproxy/haproxy.cfg is valid
3. haproxy -st – 终止指定进程的 HAProxy 实例
• 如果你有多个 HAProxy 进程在运行,可以通过 PID 来终止指定进程。
haproxy -st
这将优雅地终止 HAProxy 实例。
4. haproxy -D – 以调试模式运行 HAProxy
• 使用 -D 启动 HAProxy,以调试模式运行,输出详细的调试信息。
haproxy -D -f /etc/haproxy/haproxy.cfg
5. haproxy -p /var/run/haproxy.pid – 显示运行中的 HAProxy PID
• 这个命令显示当前 HAProxy 实例的 PID 文件。
haproxy -p /var/run/haproxy.pid
6. netstat 或 ss – 查看 HAProxy 的端口和连接状态
• 使用 netstat 或 ss 命令来查看 HAProxy 所监听的端口和建立的连接状态。
netstat -tuln | grep haproxy
或者使用 ss(更现代的工具):
ss -tuln | grep haproxy
7. HAProxy Stats Page(通过 web 界面查看状态)
• 如果在 HAProxy 配置中启用了 统计页面(stats),你可以通过浏览器访问该页面来查看 HAProxy 的实时状态。
示例配置:
listen stats
bind *:8085 # 监听8085端口,请根据实际环境进行修改
mode http # HTTP模式
stats enable # 启用统计功能
stats uri /stats # 统计页面访问路径
stats realm Haproxy\ Statistics # 页面标题
stats auth admin:password # 访问凭据
stats admin if TRUE # 管理员权限
然后你可以在浏览器中访问 http://
8. socat 或 nc – 通过 Unix 套接字查看 HAProxy 状态
• HAProxy 支持通过 Unix 套接字进行状态查询。在配置文件中启用 stats socket 后,可以通过命令行与 HAProxy 交互。
示例配置:
global
stats socket /var/run/haproxy.sock mode 600 level admin
通过 socat 或 nc(netcat)访问套接字:
echo "show stat" | socat unix-connect:/var/run/haproxy.sock stdio
或
echo "show stat" | nc -U /var/run/haproxy.sock
这样可以实时查询 HAProxy 的状态,如连接数、请求数、服务器状态等。
9. haproxy -q – 查询 HAProxy 状态
• 如果你启用了 stats socket,可以通过此命令快速查看 HAProxy 的当前状态。
haproxy -q
10. ps 或 top – 查看 HAProxy 进程
• 你可以通过 ps 或 top 命令查看 HAProxy 的进程状态,了解进程数量、CPU 使用等信息。
ps aux | grep haproxy
或者:
top -p $(pgrep -d',' -f haproxy)
总结:
• 使用 haproxy -v 查看版本。
• 使用 haproxy -c -f 检查配置文件。
• 使用 netstat 或 ss 查看 HAProxy 监听的端口和连接。
• 如果启用了 stats 页面,可以通过浏览器查看实时状态。
• 通过 socat 或 nc 查看 Unix 套接字状态。
• 使用 ps 或 top 查看 HAProxy 进程和资源使用情况。
这些命令和工具有助于监控和管理 HAProxy 的运行状态、连接情况以及性能。
后话
HAproxy可以独立工作,如果是熟悉HAproxy配置文件的朋友,并不需要依靠其他应用就可以正常使用,很多商用环境都是这么做的。不过,HAproxy毕竟是靠配置文件进行管理,虽然说配置文件格式也很简单,但是对于不熟悉CLI界面的朋友来说还是不太友好,所有也就有了各种第三方的Web GUI项目(貌似现在很多已经消失了~)。其中,比较出名的就是roxy-wi(也叫haproxy-wi),不过,这只是为了追求图形化配置而已,并非必须,这点大家一点要注意,我之后会用一篇文章专门来介绍roxy-wi。