我们运行一个 Web 应用程序,为越来越多的客户提供 Web API。一开始,客户通常是家庭、办公室或其他无线网络,向我们的 API 提交分块的 http 上传。现在,我们已扩展到处理更多的移动客户端。文件大小从几 k 到几 GB 不等,被分解成更小的块,并在我们的 API 上重新组装。
我们当前的负载平衡是在两层进行的,首先,我们使用循环 DNS 为我们的 api.company.com 地址发布多个 A 记录。在每个 IP 上,我们托管一个 Linux LVS:http://www.linuxvirtualserver.org/,负载均衡器会查看请求的源 IP 地址,以确定将连接交给哪个 API 服务器。此 LVS 盒配置有 heartbeatd,以相互接管外部 VIP 和内部网关 IP。
最近,我们发现了两种新的错误情况。
第一个错误是客户端在上传过程中震荡或从一个 LVS 迁移到另一个 LVS。这反过来会导致我们的负载均衡器失去对持久连接的跟踪,并将流量发送到新的 API 服务器,从而破坏跨两个或多个服务器的分块上传。我们的目的是让下游缓存名称服务器、操作系统缓存层和客户端应用程序层遵守 api.company.com 的循环 DNS TTL 值(我们已将其设置为 1 小时)。大约 15% 的上传都会发生此错误。
第二个错误我们不太常见。客户端将发起到 LVS 框的流量,并路由到其后面的 realserver A。此后,客户端将通过新的源 IP 地址进入,LVS 框无法识别该地址,从而将正在进行的流量路由到同样位于该 LVS 后面的 realserver B。
鉴于我们上面描述的架构,我想知道人们对于更好的方法有何经验,可以让我们更优雅地处理上述每种错误情况?
编辑于2010/5/3:
这看起来就是我们需要的。对源 IP 地址进行加权 GSLB 散列。
答案1
对此的规范解决方案是不依赖最终用户的 IP 地址,而是通过 cookie 使用带有“粘性会话”的第 7 层(HTTP/HTTPS)负载平衡器。
粘性会话意味着负载平衡器将始终将给定客户端定向到同一后端服务器。通过 Cookie 意味着负载平衡器(本身就是一个功能齐全的 HTTP 设备)插入 Cookie(由负载平衡器自动创建和管理)以记住给定 HTTP 连接应使用哪个后端服务器。
粘性会话的主要缺点是后端服务器负载可能会变得有些不均衡。负载平衡器只能在建立新连接时公平地分配负载,但考虑到现有连接在您的场景中可能存在很长时间,因此在某些时间段内负载不会完全公平地分配。
几乎每个第 7 层负载均衡器都应该能够做到这一点。在 Unix/Linux 上,一些常见的例子是 nginx、HAProxy、Apsis Pound、带有 mod_proxy 的 Apache 2.2 等等。在 Windows 2008+ 上有 Microsoft Application Request Routing。作为设备,Coyote Point、loadbalancer.org、Kemp 和 Barracuda 在低端领域很常见;而 F5、Citrix NetScaler 和其他设备在高端领域很常见。
HAProxy 的作者 Willy Tarreau 有这里很好地概述了负载平衡技术。
关于DNS循环:
我们的目的是让下游缓存名称服务器、操作系统缓存层和客户端应用程序层遵守 api.company.com 的循环 DNS TTL 值(我们将其设置为 1 小时)。
它不会。 和DNS 循环不适合负载平衡。如果没有其他说服你的话,请记住由于最长前缀匹配,现代客户端可能更喜欢一个主机而不是所有其他主机固定,因此如果移动客户端改变 IP 地址,它可能选择切换到另一个 RR 主机。
基本上,可以使用 DNS 轮询作为粗粒度负载分配,通过将 2 个或更多 RR 记录指向高可用性 IP 地址,由主动/被动或主动/主动 HA 中的实际负载平衡器处理。如果您正在这样做,那么您不妨为这些 DNS RR 记录提供较长的生存时间值,因为关联的 IP 地址已经具有高可用性。
答案2
回答你关于替代方案的问题:你可以通过以下方式获得可靠的第 7 层负载平衡HAProxy。
至于如何修复 LVS 亲和性问题,我实在想不出什么切实可行的办法。问题可能很简单,比如超时或溢出。有些移动客户端在连接到网络时会切换 IP 地址;也许这就是您遇到麻烦的原因?我建议您至少将亲和性粒度扩展到至少 C 级。