高可用性高性能 Web 缓存
简介
本文档解释了如何使用 HAProxy 和 ucarp 来提供高性能和高可用性服务。本文档已使用 Alpine Linux 2.2.3 进行测试。
在本文档中,我们将使用 Squid web 缓存 作为示例服务。Squid 通常只使用单个处理器,即使在多处理器机器上也是如此。为了获得更高的 web 缓存性能,最好将 web 缓存扩展到多个(廉价)物理机上。虽然 web 缓存被用作示例服务,但本文档适用于其他服务,例如邮件、web 加速等。
网络拓扑图
最后,我们将拥有一个如下所示的架构
工作站都连接到 192.168.1.10 上的 HAProxy 实例。192.168.1.10 是一个由 ucarp 控制的虚拟 IP;也就是说,HAProxy 在任何给定时间都在一个 web 缓存服务器上运行,但任何 web 缓存都可以是 HAProxy 实例。
HAProxy 将 web 流量分配到所有活动的 web 缓存服务器,这些服务器缓存来自 Internet 的资源。
优势
- 图表中的 HAProxy 服务器是“虚拟的” - 它代表在任何 web 缓存服务器上运行的服务
- 每个 web 缓存服务器都配置为其他服务器的镜像 - 这简化了添加额外容量。
- HAProxy 将忽略已失败或已离线的服务器,并在它们返回服务时发出通知
- 此配置允许在“滚动停机”中升级或修改单个服务器,而不会给用户带来停机时间。
- 如果运行 HAProxy 的服务器崩溃,Ucarp 会自动在另一个缓存上重启 HAProxy 服务。这是自动恢复,从客户端的角度来看,通常停机时间少于 3 秒。
初始服务
获得高可用性的第一步是拥有多个服务器;在每个 cache1-4 上执行以下操作
- 安装 squid
apk add squid
- 创建一个最小的 /etc/squid/squid.conf
acl all src all acl localhost src 127.0.0.1/32 acl localnet src 10.0.0.0/8 # RFC1918 possible internal network acl localnet src 172.16.0.0/12 # RFC1918 possible internal network acl localnet src 192.168.0.0/16 # RFC1918 possible internal network icp_port 3130 icp_access allow all cache_peer 192.168.1.11 sibling 3128 3130 cache_peer 192.168.1.12 sibling 3128 3130 cache_peer 192.168.1.13 sibling 3128 3130 cache_peer 192.168.1.14 sibling 3128 3130 http_access allow localnet http_access allow localhost http_access deny all http_port 3128 forwarded_for off

icp
和 cache_peer
条目允许所有四个 squid 服务器共享缓存信息。一旦一个服务器检索到一个项目,其他服务器就可以从本地服务器获取信息,而无需重新检索。
- 确保 squid 在启动时启动
rc_update add squid rc-service squid start
此时,您应该能够将浏览器设置为使用任何 192.168.1.1[1-4]:3129 作为代理地址,并连接到 Internet。由于此配置文件未使用任何优化,因此浏览速度将比正常慢。这是可以预期的。您对一个服务器的 squid 配置所做的任何优化都可以应用于数组中的所有服务器。此示例的目的是表明服务在整个数组中是一致的。
Ucarp 虚拟 IP 管理器
Ucarp 在所有服务器上运行,并确保虚拟 IP 地址可用。在示例图中,我们使用虚拟 IP 192.168.1.10。
- AlpineLinux ucarp init 脚本期望它在多宿主机上运行;能够在每个接口上运行 ucarp 进程。复制接口的脚本
apk add ucarp ln -s ucarp /etc/init.d/ucarp.eth0 cp /etc/conf.d/ucarp /etc/conf.d/ucarp.eth0
- 编辑 /etc/conf/ucarp.eth0 文件
REALIP= VHID=1 VIP=192.168.1.10 PASSWORD=SecretPassword
- 创建 etc/ucarp/vip-up-eth0.sh
#!/bin/sh # Add the VIP address ip addr add $2/24 dev $1 for a in 330 440 550; do beep -f $a -l 100; done
- 创建 /etc/ucarp/vip-down-eth0.sh
#!/bin/sh # Remove the VIP address ip addr del $2/24 dev $1 for a in 550 440 330; do beep -f $a -l 100; done
- 使脚本可执行
chmod +x /etc/ucarp/*.sh
- 启动 ucarp 并保存更改
rc-update add ucarp.eth0 rc-service ucarp.eth0 start lbu commit
- 对每个缓存服务器执行上述步骤。
一旦它在每个服务器上运行,依次拔下每个服务器上的网线。几秒钟后,其他服务器应该会发出提示音,因为它们举行选举以选择新的主服务器。(注意,所有服务器都会短暂地成为主服务器,然后其他服务器会迅速降级自身。)无论哪个服务器被选为主服务器,您都应该能够 ping 通 192.168.1.10。
HA Proxy 负载均衡器
HA 负载均衡器
- 自动跨 web 缓存分配请求
- 自动检测缓存何时更改状态,并禁用或重新启用向其发送请求。
- 在每个 web 缓存上安装 haproxy。
apk add haproxy
- 我们将 haproxy 用作简单的 tcp 负载均衡器,因此我们不需要高级 http 选项。以下是一个简单的 `/etc/haproxy.cfg` 文件
global uid haproxy gid haproxy chroot /var/empty defaults # 30 minutes of waiting for a web request is crazy, # but some users do it, and then complain the proxy # broke the interwebs. timeout client 30m timeout server 30m # If the server doesnt respond in 4 seconds its dead timeout connect 4s listen http_proxy 192.168.1.10:8080 mode tcp balance roundrobin server cache1 192.168.1.11:3128 check server cache2 192.168.1.12:3128 check server cache3 192.168.1.13:3128 check server cache4 192.168.1.14:3128 check
如果您的 squid 缓存具有公共、可路由的 IP 地址,您可能希望将平衡算法更改为 source
。当客户端的 IP 地址在请求之间发生变化时,某些 web 应用程序会感到困惑。使用 balance source
将客户端负载均衡到所有 web 代理,但一旦客户端被分配给特定的代理,它将继续使用该代理。
- 确保您拥有 haproxy 用户和组
adduser -s /bin/false -D -h /dev/null -H haproxy
- 不要启动 haproxy 或将其添加到 rc 脚本;我们稍后会这样做。
- 对 cache2-4 执行上述步骤;请注意,所有实例的 `/etc/haproxy.cfg` 完全相同。
- 在当前拥有 192.168.1.10 ucarp 地址的缓存上
rc-service haproxy start
- 将您的浏览器更改为使用 192.168.1.10:8080 作为代理地址。
- 您应该能够浏览 Internet
- 您的浏览应该分布在所有 4 个 squid 服务器上
启用 HA 服务
按照上述说明操作后,您应该具备以下条件
- Squid 正在每个 web 缓存上运行
- 您可以通过 ip 地址连接到每个 web 缓存并浏览互联网
- ucarp 正在所有实例上运行
- 您可以 ping 通 192.168.1.10
- 如果您拔下连接到提供 192.168.1.10 的盒子的以太网电缆,另一个盒子会取代它
- haproxy 已在每个缓存服务器上配置,但未运行
- 更新每个服务器上的 `etc/ucarp/vip-up-eth0.sh` 以包含启动 haproxy 的语句
#!/bin/sh # Add the VIP address ip addr add $2/24 dev $1 rc-service haproxy start for a in 330 440 550; do beep -f $a -l 100; done
- 更新每个服务器上的 `etc/ucarp/vip-down-eth0.sh` 以包含停止 haproxy 的语句
#!/bin/sh rc-service haproxy stop # Remove the VIP address ip addr del $2/24 dev $1 for a in 550 440 330; do beep -f $a -l 100; done
- 保存更改
lbu commit
维护
haproxy 进程在所有可用的 web 代理之间负载均衡请求。如果代理崩溃,haproxy 会自动将其从池中删除,并将传入的请求重定向到其余可用的代理。一旦代理恢复服务,haproxy 会自动注意到并再次开始向其发送请求。
ucarp 进程确保“haproxy”始终在虚拟 ip (192.168.1.10) 上运行。即使运行 haproxy 的机器崩溃,客户端也不需要重新配置。另一个盒子接管虚拟地址,一切“正常工作”
要从服务中删除代理,只需将其关闭即可。更优雅的方法是更新 haproxy.conf
并告诉 haproxy 使用新配置。例如,要从池中删除 192.168.1.11
- 登录到 192.168.1.10
- 编辑 /etc/haproxy.conf 并注释掉 192.168.1.11 行
# server cache1 192.168.1.11:3128 check # 192.168
- 请求 haproxy 的软重启
/usr/bin/haproxy -D -p /var/run/haproxy.pid -f /etc/haproxy.cfg -sf \ $( cat /var/run/haproxy.pid )
这会导致现有的 haproxy 完成连接,但不接受新的连接。最终,旧的 haproxy 进程将死亡,只留下新的进程。由于 web 请求可能需要很长时间,因此旧的 haproxy 实例可能会持续数分钟。在关闭 web 代理服务器之前,请确保旧进程已终止。
同样,要将 web 缓存添加到 farm 中,请使用上述命令让 haproxy 开始使用新的配置文件。
“-sf”标志允许对 web 缓存进行滚动维护,而对客户端没有可观察到的影响。