在多个静态文件服务器之间进行负载平衡以实现带宽分配的最佳方法?

在多个静态文件服务器之间进行负载平衡以实现带宽分配的最佳方法?

首先,我先向你解释一下我的情况。我正在运营一个相当受欢迎的网站,作为一个副业,所以我不能投入大量资金。我目前只有一台服务器,前端有 HAProxy,向 Apache 发送普通请求,所有静态文件请求都发送到 Lighttpd。这非常有效,因为所有 php 和 post 请求都由 Apache 处理,而所有图像都发送到更快的 Lighttpd(该网站主要是图像,所以这一点非常重要)。如果不必设置子域来提供图像就好了,因为短 URL 也非常重要,这就是我使用 HAProxy 的原因。

我找到了一个提供相当便宜的无限带宽的托管服务提供商,我一直在使用它,当我开始推出 100mbs 网卡可以处理的尽可能多的带宽时,问题就出现了,因此需要第二台服务器。

我花了很多心思考虑我的选择,所以我会向你解释每一个。希望你能提供一些见解,告诉我哪一个对我来说是最好的选择,或者也许还有其他我还没有想到的选择。

要求:

  • 均匀带宽分配是必须的。我有一台相当强大的服务器,因此扩展不是一个选择。我需要扩展以获得更多带宽。

  • 短网址。我真的不想设置子域名,如 img.example.com,来提供我的图片。example.com/image.jpg 就是现在的样子,我真的希望它保持原样。但如果没有其他办法,那么我理解。

  • 让最近的服务器处理请求确实很好,但不是必须的。需要记住这一点。

HAProxy 进行负载平衡:

  • 由于我已经在使用 HAProxy,因此这确实很容易做到。但是,我认为问题出现在分配带宽时。我可能错了,但 HAProxy 不是将请求发送到服务器,然后服务器处理该请求,然后通过 HAProxy 将其发送回客户端吗?因此,所有流量都会通过负载均衡器返回,导致它使用的带宽与所有服务器的总带宽一样多。

DNS 循环:

  • 这可能是我最好的选择。只需将网站复制到多个服务器并执行我现在正在做的事情。缺点是,如果一台服务器出现故障,客户端仍会发送到该服务器。我还需要在多台服务器上复制网站。我有点希望我可以有一台主服务器来处理除静态文件之外的所有内容,然后有几台静态文件服务器。我还读到这有点像“穷人的负载平衡”,如果能有更复杂一点的东西就好了。

直接服务器返回:

  • 这看起来真的很复杂,但可能是一个不错的选择。我还能将某些 URL 发送到某些服务器吗?就像现在使用 HAProxy 一样,每个以正确的文件扩展名结尾的 URL 都会发送到 Lighttpd,而其他扩展名则会发送到 Apache。所以我需要类似的东西。例如,所有 php 请求都由运行平衡软件的同一台服务器处理,而所有 jpg 请求都会发送到多台服务器。

理想情况下,如果 HAProxy 支持 Direct Server Return,那么我的问题就解决了。我也不想使用 CDN,因为它们真的很贵,而且这毕竟只是一个附带项目。

你明白我的问题了吗?如果我没有解释清楚或者你需要更多信息,请告诉我。

答案1

绘制应用程序的请求/响应周期图并隔离瓶颈。您说得对,单个代理将负载分配到许多应用程序服务器将需要所有应用程序服务器的总带宽。经典解决方案是 RR DNS。Google、Yahoo 和 Amazon 都使用这种技术,TTL 较短。我前段时间做了一些调查,记录我的发现

另一种解决方案是使用一种花哨的企业负载平衡解决方案,该解决方案使用虚拟 IP 寻址来平衡具有真实 IP 地址的多个应用服务器之间的请求。我曾使用过 Netscaler 和 Stonesoft 产品。两者的性能都很好,但都有一些糟糕的特性,而且相当复杂。

答案2

一些答案:

  • 是的,所有流量都通过 HAProxy 发出,因为它充当 HTTP 级代理。即使 HAProxy 安装在单独的服务器上,对多个后端服务器进行负载平衡,情况也是如此。因此,如果您的托管服务提供商仅提供 100MBit 网络端口,而您已经在推送 100MBit,那么您就会遇到问题。
  • 关于域名,最佳做法是从与你的 web 应用不同的域名提供图像 - 不是子域名,而是不同的域名,这样 cookie 就不会随图像请求一起发送。请参阅Steve Souders 原创作品, 或者Stack Overflow 上的实现。如果短 URL 对您来说非常重要,那么最好的办法可能是将 Web 应用程序移出主 URL,即将文件管理应用程序移至 login.sitename.com?

您需要对图像请求进行身份验证吗?如果没有,那么使用 Amazon S3 之类的东西怎么样?它具有大规模可扩展性,并且数据传输成本相当便宜。在这种情况下,我会使用 i.sitename.com 之类的东西作为 Amazon S3 存储桶主机名的 DNS CNAME,参见亚马逊文档据我所知,您不能将根域名 (sitename.com) 作为 CNAME,因此您必须使用像 i.sitename.com 这样的子域名来实现这一点。

您还可以在多个服务器之间对图像进行哈希处理。即,您创建一个 DNS 结构,如 login.sitename.com 和 a.sitename.com ; b.sitename.com ; c.sitename.com 等。 “a.”和“b.”等服务器仅包含一个带有图像的文件系统和一个轻量级 HTTP 服务器(您已经在使用 Lighttpd,因此继续使用它。对于未来的项目,我建议将 nginx 视为更好的替代品。)当用户上传图像时,您会创建一个唯一标识符的哈希值,可能是用户名,也可能是文件名,或者是多个标识符的组合通过这个哈希值,你可以确定将图像存储在哪个服务器上。

编辑我应该看到哈希算法已经讨论过了。本质上,我在这里提出的建议只是在主机名上也使用哈希算法,以将网络流量均匀分布在多个主机上。

我不知道你需要多便宜——但是当你推动 100MBit 的网络流量时,“便宜又好”很快就会变成幻觉。也许你应该先考虑建立一个好的商业模式,一个能提供经常性收入的模式,然后再实施适当的技术?

答案3

我假设 HAProxy 与您的其他应用程序位于同一台服务器上?您可以将 HAProxy 拆分到另一个系统来运行请求,并让它将普通请求发送到一台服务器,将图像请求发送到另一台服务器。问题是,所有请求仍然会发送到一个盒子,如果您的带宽已饱和,那么这可能对您没有多大帮助。

您说短 URL 很重要。为什么?将图像从“example.com”切换到“i.example.com”真的有那么大的问题吗?您可以使用 Lighttpd 将“i”在其自己的服务器上设置为自己的 IP,并完全绕过 HAProxy,从而解决吞吐量问题。您还可以获得 Web 浏览器允许同时打开更多请求的好处,因为它会将它们视为不同的域名并可以打开更多并发连接。如果单个“i”服务器饱和,您可以使用 DNS 循环来添加另一个。希望到那时您已经产生足够的收入来实施更好的解决方案。

答案4

我假设对于任何一组相当大的图像,您都不会根据其原始文件名来存储图像,因为您很快就会遇到名称冲突。

许多处理此类问题的应用程序都使用文件的哈希值和基于该哈希值的目录结构。目录结构如下所示,其中目录路径是哈希值的前两个字符,而第二级目录是哈希值的后两个字符。

/image root/AA/AA/images  
/image root/AA/AB/images

这样做的好处是哈希可以让文件分布得相当均匀,并且它为你提供了一个易于在多个服务器上拆分的命名空间。基本上,你从不同的服务器提供哈希空间的部分服务,并且在扩展时,你可以根据需要进一步细分它。

缺点是哈希并不完美,可能会发生冲突。我不确定如何处理这个问题。所以你可能需要做一些研究。我想象代理中的重写规则应该能够获取哈希 A3A8BBC83261.jpg 并将其重写为http://img3.domain.com/A3/A8/BBC83261.jpg。不过您可能不认为这是一个短网址。

相关内容