如何使用Digital Ocean DNS和Nginx设置全局负载均衡?

37

更新:查看我在AWS上最终设置的解决方案提供的答案。

我目前正在尝试实现Digital Ocean上我的应用服务器的全局负载均衡层的方法,但还有一些部分我需要整合。

目标

通过将所有连接路由到SFO、NYC、LON和最终的新加坡的最近的“集群”服务器,为我的用户提供高可用性的服务。

此外,我最终希望编写一个守护进程来自动化维护该系统,可以监视、扩展和修复系统中的任何服务器。或者我将组合各种服务以实现相同的自动化目标。首先,我需要手动弄清楚如何做。

堆栈

  1. Ubuntu 14.04
  2. Nginx 1.4.6
  3. node.js
  4. 来自Compose.io(前身为MongoHQ)的MongoDB

全局域名分配

一旦我把所有东西都连起来,我的域名会像这样:

**GLOBAL**
global-balancing-1.myapp.com
global-balancing-2.myapp.com
global-balancing-3.myapp.com

**NYC**
nyc-load-balancing-1.myapp.com
nyc-load-balancing-2.myapp.com
nyc-load-balancing-3.myapp.com

nyc-app-1.myapp.com
nyc-app-2.myapp.com
nyc-app-3.myapp.com

nyc-api-1.myapp.com
nyc-api-2.myapp.com
nyc-api-3.myapp.com

**SFO**
sfo-load-balancing-1.myapp.com
sfo-load-balancing-2.myapp.com
sfo-load-balancing-3.myapp.com

sfo-app-1.myapp.com
sfo-app-2.myapp.com
sfo-app-3.myapp.com

sfo-api-1.myapp.com
sfo-api-2.myapp.com
sfo-api-3.myapp.com

**LON**
lon-load-balancing-1.myapp.com
lon-load-balancing-2.myapp.com
lon-load-balancing-3.myapp.com

lon-app-1.myapp.com
lon-app-2.myapp.com
lon-app-3.myapp.com

lon-api-1.myapp.com
lon-api-2.myapp.com
lon-api-3.myapp.com

如果任何给定区域的任何一层出现了任何压力,我可以启动一个新的droplet来帮助解决:nyc-app-4.myapp.comlon-load-balancing-5.myapp.com等。

当前工作方法

  • 最少三个global-balancing服务器接收所有流量。这些服务器采用“DNS轮询”平衡,如本文所示(非常令人困惑):如何配置DNS轮询负载平衡.

  • 使用Nginx GeoIP模块MaxMind GeoIP数据确定任何请求的来源,直至$geoip_city_continent_code

  • global-balancing层然后将请求路由到适当集群的load-balancing层中连接最少的服务器:nyc-load-balancing-1sfo-load-balancing-3lon-load-balancing-2等。该层也是最少三个droplets。

  • 区域load-balancing层然后将请求路由到app或api层中连接最少的服务器:nyc-app-2sfo-api-1lon-api-3等。

有关Nginx kung fu的详细信息,请参见本教程:Villiage Idiot: Setting up Nginx with GSLB/Reverse Proxy on AWS。有关Nginx负载均衡的更多一般信息,请参见此处此处

问题

我应该把global-balancing服务器放在哪里?

让我觉得奇怪的是,我要么把它们都放在一个地方,要么将该层分散到全球。例如,我将它们全部放在纽约。然后来自法国的人点击我的域名。请求将从法国发送到纽约,然后返回到LON。或者如果我在SFO、NYC和LON中各放一个,那么从多伦多(Parkdale,代表)发出的用户请求仍然可能会被发送到LON,然后再路由回NYC吗?

是否将后续请求路由到同一IP地址?

例如,如果多伦多的用户发送了一个global-balancing层确定应该前往NYC的请求,则来自相同来源的下一个请求是否直接发送到NYC,或者仍然需要通过最近的global-balancing服务器(在这种情况下为NYC)随机选择呢?

会话怎么办?

我已经配置了Nginx使用


2
说实话,我的设置几乎完全相同,并且已经尝试了几种方法来解决这个问题。我很好奇在您扩展数字海洋全球构建时遇到了哪些问题。如果您愿意,请随时通过brad@musatcha.com给我发电子邮件。 - Brad
@Brad 我刚刚给你发送了一封电子邮件。 - adrianTNT
4个回答

27
目标:通过将所有连接路由到SFO,NYC,LON和最终的新加坡最近的“集群”服务器,为我的用户提供高可用服务。然后,全球平衡层将请求路由到最少连接的服务器...
如果我正确理解您的配置,您实际上是从全局负载平衡器代理到每个地区的负载平衡器。这不符合您将用户路由到最近地区的目标。
我知道有三种方法可以实现您想要的内容:
1. 30x重定向: 您的全球负载平衡器接收HTTP请求,然后根据IP地址将其重定向到在或靠近它认为请求来源的区域内的服务器组。这听起来像是您尝试设置的内容。这种方法会对某些应用程序产生副作用,并且增加了用户获取数据所需的时间,因为您正在添加大量开销。只有在您重定向到的资源非常大,而本地区域集群能够更有效地提供服务时,才有意义。 2. Anycast(利用BGP路由): 这是像Akamai这样的大型播放器用于他们的CDN的方法。基本上,在互联网上有多个具有完全相同可路由IP地址的服务器。假设我在几个地区都有服务器,并且它们具有192.0.2.1的IP地址。如果我在美国并尝试连接到192.0.2.1,并且有人在欧洲尝试连接到192.0.2.1,则可能会将我们路由到最近的服务器。这使用互联网自己的路由来查找流量的最佳路径(基于网络条件)。不幸的是,您不能仅使用此方法。您需要拥有自己的AS号和物理硬件。如果您找到一个允许您拥有它们的Anycast块的VPS提供商,请告诉我!
  • Geo-DNS
    有一些DNS提供商提供一种通常被营销为“Geo-DNS”的服务。它们在任播地址上托管了一堆DNS服务器,可以将流量路由到您最近的服务器。如果客户端查询欧洲DNS服务器,则应返回您在欧洲地区的服务器的地址,而不是其他地区的服务器。 Geo DNS服务有许多变体。其他人只需维护一个地理IP数据库并返回他们认为更接近的地区的服务器,就像重定向方法一样,但是在HTTP请求之前为DNS。这通常是一个好选择,价格和易用性都很好。

  • 后续请求会路由到同一个IP吗?

    许多负载均衡器都有一个“粘性”选项,该选项表示应将来自相同网络地址的请求路由到同一个终端服务器(前提是该终端服务器仍然正常运行)。

    那会话呢?

    这正是您希望具有这种粘性的原因。当涉及会话数据时,您将不得不找到一种方法来使所有服务器保持最新状态。从现实角度来看,这并不总是保证的。如何处理取决于您的应用程序。您可以在世界各地保留一个Redis实例或其他可以可靠地访问的服务器吗?您真的需要在每个地区的会话数据吗?还是您的主要应用程序服务器在一个位置处理会话数据?

    有DNS示例吗?

    为此发布单独的问题。每个人的“成功设置”看起来都不同。

    那SSL / TLS呢?

    如果您正在代理数据,则只需要全局负载均衡器处理HTTPS。如果您正在重定向,则所有服务器都需要处理它。


    我需要对任何给定的30x重定向细节以及DNS服务器之间的通信方式进行一些功课。 - AJB
    嘿,布拉德,只是想向你更新我的进展。我已经从 DO DNS 转移到 Route53,以利用其提供的多种“路由策略”:延迟、GeoIP、故障转移。重新发明轮子没有任何意义(即使它很有趣和富有教育性),而且 Route53 的定价对于这项服务来说是合理的。现在我正在尝试弄清楚如何完全摆脱我的负载均衡层。我将我的会话移动到集中式的 Mongo 存储(或 redis),然后我将转发端口 80/443 到我的节点端口,以尝试使用 Route53 进行 SSL 终止。我会再次更新。 - AJB
    @AJB 很好知道。我上次了解Route 53时,它似乎只支持AWS环境中的这些策略。现在不是这样了吗? - Brad
    这里也一样,现在它们提供了简单、加权、延迟、故障转移和地理位置路由策略,适用于任何 AWS 端点或外部 IP。http://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html。他们现在也提供健康检查。还有 33 个 POP。看起来是一个相当不错的交易,但我还需要继续研究。我计划更新过去 72 小时内发现的所有结果,但首先我必须继续在 Heroku 和 Appfog 上进行测试。是的,我想我最终选择了 PaaS。价格更高,但是由于所有运营工作都已经包含在内,所以看起来是最好的选择。 - AJB
    2
    哈。这是一个很棒的标题!我正在计划中。有很多笔记。我原本的工作标题是“我们走向PaaS深渊!”或者“在啤酒预算下实现全球高可用性”。不过我喜欢你的标题。无论如何,OpsWorks似乎在自动化和定制之间找到了平衡点,所以希望这是我的旋风之旅的终点,我很快就能写出我的发现。一旦我准备好草稿,我会把它发送给你阅读的。 - AJB
    显示剩余16条评论

    16

    一个可行的解决方案

    在过去的几个月里,我经历了一次疯狂的旅程,弄清了整个全局HA设置。非常有趣,最终我找到了一个非常好用的装置,与上述问题中提到的那个完全不同。

    我仍计划以教程形式撰写此内容,但时间很紧,因为我正进入最后冲刺阶段,力争在明年初推出我的应用程序,所以这里简要概述一下我最终采用的工作装置。


    概述

    我最终将我的整个部署转移到了AWS。我喜欢Digital Ocean,但事实上,AWS在提供一站式服务方面遥遥领先于他们(以及其他所有人)。我的月度开销略微增加,但一旦我完成了调整和优化,我得到的解决方案成本约为每个区域每月75美元,用于最基本的部署(2个实例位于ELB后面)。而新区域可以在大约30分钟内启动和部署。


    全球负载均衡

    我很快就发现(多亏了@Brad上面的答案),尝试自己搭建全球负载均衡DNS层是疯狂的。虽然弄清楚这样一个层是如何工作的很有趣,但除非我登上飞机,在世界各地安装价值数百万美元的设备,否则自己搭建是不可能的。

    当我最终找到我要寻找的东西时,我找到了我的新朋友:AWS Route 53。它提供了一个强大的DNS网络,全球约有50多个节点,并具有一些非常酷的路由技巧,例如基于位置的路由、基于延迟的路由(相当棒)以及AWS别名记录,可以“自动”将流量路由到其他您将使用的AWS服务(例如用于负载均衡的ELB)。

    最终,我使用了基于延迟的路由,将全球流量定向到最近的区域性弹性负载均衡器,该负载均衡器附加在任何给定区域的自动扩展组上。

    我会让你自己去了解其他提供商的情况:www.f5.com, www.dyn.com, www.akamai.com, www.dnsmadeeasy.com。根据你的需求,可能有更好的解决方案适合你,但这对我来说非常有效。


    内容分发网络

    Route 53与 AWS Cloudfront非常好地集成在一起。我设置了一个S3存储桶,用于存储所有用户上传的静态媒体文件,并配置了一个Cloudfront分发来源自我的media.myapp.com S3存储桶。还有其他CDN提供商,请仔细选择。但是Cloudfront得到了相当不错的评价,并且很容易设置。


    负载均衡 & SSL终止

    我目前使用AWS弹性负载均衡器来平衡应用实例之间的负载,这些实例位于自动伸缩组中。请求首先由ELB接收,此时SSL被终止,并将请求传递到自动伸缩组中的一个实例。

    注意: 对于ELB而言,有一个重要的限制,有点讽刺的是,它无法很好地处理巨大的流量峰值。在此期间,ELB可能需要15分钟才能触发自身的扩展事件,从而创建500 /超时。据说,稳定、持续的流量增加可以得到很好的处理,但如果你遇到流量峰值,它就会失败。如果你知道你即将受到攻击,可以提前通知AWS来为你预热ELB,这非常荒谬,并且与AWS的本质相反,但我想他们正在解决这个问题,或者忽略它,因为这并不是一个真正的大问题。如果ELB无法满足您的需求,您始终可以启动自己的 HAProxy Nginx负载平衡层。


    自动扩展组

    每个区域都有一个自动扩展组(ASG),该组被编程为在负载达到某个指标时进行扩展:

    IF CPU > 90% FOR 5 MINUTES: SCALEUP
    IF CPU < 70% FOR 5 MINUTES: SCALEDN
    

    I haven't yet put the ELB/ASG combo through its paces. That's a little way down my To-Do list, but I do know that there are many others using this setup and it doesn't seem to have any major performance issues.
    Auto-Scaling Group 的配置有点复杂。实际上,它是一个三步骤的过程:
    1. 创建按照您喜好配置的 AMI。 2. 创建使用您创建的 AMI 的 Launch Configuration。 3. 创建使用您创建的 Launch Configuration 的 Auto-Scaling Group,以确定在任何给定的 SCALEUP 事件中启动哪个 AMI 和实例类型。
    为了处理任何实例启动时的配置和应用程序部署,您可以使用 "User Data" 字段输入一个脚本,该脚本将在任何给定实例启动时运行。这可能是有史以来最糟糕的命名方式。只有作者知道“用户数据”如何描述启动脚本。无论如何,那就是您放置处理所有 apt-get、mkdir、git clone 等操作的脚本的地方。


    实例和内部平衡

    我还添加了一个额外的“内部平衡层”,使用Nginx,使我能够在每个实例上“平铺”所有我的Node.js应用程序(app.myapp.com、api.myapp.com、mobile.myapp.com、www.myapp.com等)。当实例从ELB接收到传递给它的请求时,Nginx会处理将请求路由到任何给定应用程序的正确Node.js端口。有点像穷人的容器化。这样做的另一个好处是,任何时候我的应用程序需要相互通信(比如当app.需要向api.发送请求时),都是通过localhost:XXXX完成的,而不必经过AWS网络或互联网本身。

    这种设置还通过消除托管它的应用程序层接收轻量级流量时的任何空闲基础设施来最大化使用资源。它还避免了为每个应用程序拥有ELB/ASG组合的需要,从而节省更多现金。

    我没有遇到使用这种设置的任何问题或注意事项,但是需要就健康检查(见下文)进行一些解决。

    这也有一个很好的优点,即所有实例都具有 IAM 角色,这意味着在每个实例出现时,您的 AWS 凭证已经“嵌入”到每个实例中,并可以通过您的环境变量访问。而且 AWS 会自动为您轮换凭证。非常安全,非常棒。


    健康检查

    如果你选择以上设置的路线,将所有应用程序打包在一个盒子上并运行内部负载均衡器,那么你需要创建一个小工具来处理ELB健康检查。我创建了一个名为ping.myapp.com的附加应用程序。然后,我配置我的ELB健康检查将任何健康检查发送到我的ping应用程序正在运行的端口,如下所示:

    Ping Protocol: HTTP
    Ping Port:     XXXX
    Ping Path:     /ping
    

    这将所有健康检查发送到我的小型ping助手,该助手转而在实例上驻留的所有应用程序上命中localhost:XXXX/ping。如果它们都返回200响应,则我的ping应用程序会向ELB健康检查返回200响应,实例将继续运行30秒。
    注意:如果您正在使用ELB,请不要使用自动缩放健康检查。请使用ELB健康检查。这有点令人困惑,我以为它们是一样的,但它们并不相同。您可以选择启用其中一个。选择ELB。


    数据层

    我设置中明显缺少的一件事就是数据层。我使用Compose.io作为我的托管数据层提供者,并在AWS上部署,因此我的应用程序层和数据层之间的延迟非常低。我已经进行了一些初步调查,了解如何全球范围内推出我的数据层,并发现这非常复杂 - 也非常昂贵,因此我将其降低到我的问题列表中,因为它还不需要解决。最坏的情况是我只能在美国东部运行我的数据层并加强硬件。这并不是世界上最糟糕的事情,因为我的API严格遵循JSON数据传输,因此平均响应相对较小。但是我可以看到,在非常大规模的全球范围内,这可能会成为瓶颈 - 如果我曾经到达那里的话。如果有人对这一层有任何建议,我很想听听你们的意见。


    瞧!

    在预算有限的情况下实现全球高可用性。我花了6个月的时间才想明白。

    很乐意听取任何阅读此文的人的意见或想法。


    非常酷,很高兴看到你把所有的东西都搞定了!在过去的6个月里,我也曾为一个应用程序使用AWS,但对于我的主要业务却远离它。在我的Node.js应用程序中使用Elastic Beanstalk。那里的应用程序有非常简单的要求。它使用S3进行数据存储,并通过HTTP向客户端输出。即使如此,由于您可以设置Beanstalk的限制,这仍然证明是一个真正的麻烦。如果我需要重新开始,Docker将成为我处理任何Beanstalk应用程序的首选,但这并不适用于您的情况。 - Brad
    1
    关于健康检查,请看这个链接:https://github.com/STRML/node-toobusy/。我强烈建议将该健康检查嵌入到你的应用程序中(如果在你的情况下有意义的话)。这样,如果事情变得有些过载(从Node.js的角度来看),你可以让负载均衡器知道。我曾经遇到过Node.js只是IO绑定的情况,使得正常的健康检查自由地声明一切正常,但事实并非如此。事件循环测试可能会或可能不会帮助你,但值得探究。 - Brad
    1
    对于我的应用程序,我基本上重新发明了负载均衡...我接到了一个新的业务要求。我有一些客户拥有过剩带宽,所以我可能会制定一些方案,让他们为我托管一个盒子,以换取降低成本或免费服务,就像Skype一样。在这种情况下,我需要很大的灵活性,并需要将质量检查内置到应用程序层中。速度也很重要。目前,如果我的服务器之一崩溃,流量停止路由到它,在约100ms内。这对我来说是有效的,但并非所有人都需要。 - Brad
    是的。Docker 对我来说也是下一步,但在我发布之后,我的女友不会让我使用它。而且我可能会使用 ECS,这甚至还没有推出,所以可能要等 12-18 个月的时间。目前,这个方法可行且稳定,所以我会继续使用它。我也觉得 Elastic Beanstalk 有限制。最好使用 Docker 版本,但我从未成功地“简单启动任何应用程序”。 - AJB
    是的,几乎没有任何诊断或调试的方法就隐藏了视图。这是一个非常令人沮丧的工具。检测到死节点的时间大约为100毫秒,速度非常快。我目前的时间是30秒,我知道这可能会有些问题。只是还没有到解决这个问题的列表上。 - AJB
    显示剩余2条评论

    3

    如果您使用Cloudflare免费计划,可以免费为您的Web服务使用Anycast。


    0
    数字洋现在支持服务器自身的负载平衡。它非常容易设置并且效果很好!如果您只想用于负载平衡,它可以省去添加不必要组件,如nginx。
    我们在数字洋服务器上使用nginx上传SSL文件时遇到了问题,但由于数字洋的更新,我们已经删除了nginx并现在使用数字洋的负载平衡功能,它正按照我们的需求工作!

    我不确定为什么会有人对此进行负投票。点个赞来平衡一下吧。是的,我也看到了。DO正在取得巨大进展,并最终会追上其他竞争对手。希望尽早实现,我宁愿把我的钱交给他们。 - AJB
    1
    也许他们想要更详细的说明如何登录到Digital Ocean,然后前往Networking -> Load Balancers -> Create Load Balancer!是的,我们现在已经将大部分基础设施切换到DO了,社区投入的资金越多,这些功能就会更快速和先进! - Sean _space
    1
    负载均衡仍然只能在单个区域内进行,这是一个缺点。 - Kenny Grant
    1
    通过使用CloudFare和DigitalOcean,您可以以更实惠的价格获得相同或更好的结果。没有免费的午餐,AWS和DO都有自己的优缺点。CloudFare的另一个好处是您可以选择不同的供应商,例如OVH。 - Gurjinder Singh

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接