HAproxy
HAProxy 是一款免费、非常快速且可靠的解决方案,为 TCP 和 HTTP 应用程序提供高可用性、负载均衡和代理功能。它特别适用于流量非常大的网站,并为许多世界上访问量最大的网站提供支持。多年来,它已成为事实上的标准开源负载均衡器,现在已包含在大多数主流 Linux 发行版中,并经常在云平台中默认部署。
安装
运行
启用 haproxy.service。可以通过以 root 身份重新加载 haproxy.service 来实时重新加载 HAProxy 的配置。
配置
示例配置文件位于 /etc/haproxy/haproxy.cfg。根据您的需求进行编辑,然后启动 haproxy.service。
通用配置
ACLs
HAProxy 支持 ACL(访问控制列表),可用于测试条件并根据测试结果执行给定操作。典型的 ACL 如下所示:
/etc/haproxy/haproxy.cfg
acl photo_page path_beg /photos
在这种情况下,如果用户的请求路径以 /photos 开头,则匹配 ACL。
后端
在 HAProxy 的术语中,后端 (backends) 是接收转发请求的服务器或服务器集。后端可以基于多种负载均衡算法进行负载均衡,包括:
- 轮询 (Round-robin)
- 静态轮询(也称为加权轮询)
- 最少连接 (Least connections)
示例后端配置如下:
/etc/haproxy/haproxy.cfg
backend http-in balance roundrobin server s1 web1.example.com:80 check server s2 web2.example.com:80 check
前端
前端 (Frontends) 用于定义请求应如何转发到后端。它们包括以下内容:
- IP 地址和端口
- ACLs
- use_backend 规则
健康检查
当后端声明了 check 选项时,HAProxy 将在启动和计划的间隔时检查后端是否可用以处理转发的请求。如果后端未能通过健康检查,它将被移出轮换,直到被认为健康为止(即通过健康检查)。
默认情况下,HAProxy 将尝试建立到后端的 TCP 连接以确定健康状况。
如果大量后端声明了 check 选项,HAProxy 将在启动时查询所有后端,这可能会延迟启动时间。
使用 systemd 进行日志记录
要配置 HAProxy 使用 systemd 的 /dev/log 兼容套接字,请在您的配置文件中的 global 部分添加以下内容:
log /dev/log local0 info
如果您在全局配置中使用 chroot 选项,则需要将套接字绑定到 chroot 环境中。
为此,我们将使用一个 systemd.mount(5) 单元。使用以下命令生成单元名称:
# systemd-escape --suffix=mount --path /var/lib/haproxy/dev/log
我们希望将 /dev/log 挂载到 chroot 中,但仅在 journald 启动之后。创建一个 替换单元文件:
/etc/systemd/system/var-lib-haproxy-dev-log.mount
[Unit] Requires=systemd-journald.service Description=/Expose Systemd Log for HAProxy [Mount] What=/dev/log Where=/var/lib/haproxy/dev/log Type=none Options=bind
创建了挂载文件后,就可以扩展原始服务单元以正确挂载所有内容了。为 haproxy.service 使用一个 drop-in 文件并添加:
/etc/systemd/system/haproxy.service.d/override.conf
[Unit] Requires=var-lib-haproxy-dev-log.mount
执行 TLS/SSL 终止
要将 haproxy 用作 TLS 终止器,您必须在 frontend 部分设置:
bind :80 bind :443 ssl crt /path/to/combined/cert
cat certificate-full-chain certificate-private-key > combined-cert。bind :443 行末尾添加 alpn h2,http/1.1。将 HTTP 重定向到 HTTPS
在您的 frontend 部分设置:
redirect scheme https code 301 if !{ ssl_fc }
类似虚拟主机的配置
假设您有两个后端:foo 和 bar,每个后端只应处理特定域的请求。为了在您的 frontend 部分实现此目的,您可以配置:
use_backend foo-backend if { hdr(host) -i foo.example.com || hdr(host) -i www.foo.example.com }
use_backend bar-backend if { hdr(host) -i bar.example.com || hdr(host) -i www.bar.example.com }