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

时间:2014-09-05 03:02:13

标签: nginx dns global load-balancing digital-ocean

  

更新:请参阅我在下面提供的答案,了解我最终在AWS上设置的解决方案。

我目前正在尝试使用有关如何在Digital Ocean上为我的应用服务器最佳实现全局负载均衡层的方法,还有一些我尚未整理的内容。

目标

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

此外,我最终希望通过编写可以监视,扩展和修复系统上任何服务器的守护程序来自动维护此操作。或者我将结合各种服务来实现相同的自动化目标。首先,我需要弄清楚如何手动完成。

筹码

  1. Ubuntu 14.04
  2. Nginx 1.4.6
  3. 的node.js
  4. 来自Compose.io(原名MongoHQ)的MongoDB
  5. 全球域名细分

    一旦我完成了所有工作,我的域名将会是这样的:

    **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
    

    然后,如果任何给定的图层上存在任何压力,在任何给定的区域,我都可以启动一个新的小滴来帮助:nyc-app-4.myapp.comlon-load-balancing-5.myapp.com等......

    当前的工作方法

    • ({最小)三个global-balancing服务器接收所有流量。 这些服务器DNS Round-Robin平衡,如下所示 (坦率地说是令人困惑的)文章:How To Configure DNS Round-Robin Load Balancing

    • 使用Nginx GeoIP ModuleMaxMind GeoIP Data 任何给定请求的来源都归结为 $geoip_city_continent_code

    • global-balancing图层然后将请求路由到相应least connected层上的load-balancing服务器 群集:nyc-load-balancing-1sfo-load-balancing-3lon-load-balancing-2等。这一层也是(最小)的三重奏 液滴。

    • 然后,区域load-balancing图层将请求路由到 app或api层中的least connected服务器:nyc-app-2sfo-api-1lon-api-3等......

    本教程中可以找到Nginx功夫的详细信息:    Villiage Idiot: Setting up Nginx with GSLB/Reverse Proxy on AWS。有关Nginx负载平衡的更多常规信息可用    here    和    here

    问题

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

    令我感到奇怪的是,我将它们全部放在一个地方,或者将这一层传播到全球各地。比方说,我把它们都放在纽约市。然后来自法国的人来到我的域名。请求将从法国,到纽约,然后被路由回LON。或者,如果我将每个中的一个放入SFO,NYC和LON,那么来自多伦多(Parkdale,代表)的用户是否仍然可以发送最终转到LON的请求才能被路由回纽约? / p>

    后续请求是否路由到同一个IP?

    同样,如果来自多伦多的用户发送了global-balancing图层确定应该去纽约市的请求,那么来自该来源的下一个请求是否会直接转到纽约市,或者它仍然是抽奖的运气它将命中最近的global-balancing服务器(在这种情况下为NYC)。

    会话怎么样?

    我已将Nginx配置为使用ip_hash;指令,因此它会将用户定向到相同的appapi端点(在我的情况下是一个节点进程)但是,如果有的话,全球平衡将如何影响这一点?

    任何DNS示例?

    我不是一个DNS专家(我目前正试图弄清楚为什么我的CNAME记录没有解析)但是我提供了一个可靠的例子,我是一个快速的研究。有没有人之前经历过这个过程,并且可以提供DNS记录成功设置的样本?

    SSL / TLS怎么样?

    我是否需要为每台服务器提供证书,或仅为三台global-balancing服务器提供证书,因为这是唯一面向公众的网关?

    如果你读完这整件事,那就用蛋糕奖励自己吧。提前感谢您的帮助。

4 个答案:

答案 0 :(得分:20)

  

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

     

然后,全局平衡层将请求路由到最后   连接服务器......

如果我正确地阅读您的配置,您实际上是从全球平衡器代理到每个地区的平衡器。这不符合您将用户路由到最近区域的目标。

我知道有三种方法可以满足您的需求:

  1. 30x重定向
    您的全局记录器会收到HTTP请求,然后根据IP将其重定向到其认为请求来自的区域内或附近的服务器组地址。这听起来像你想要设置的。此方法对某些应用程序具有副作用,并且还增加了用户获取数据所需的时间,因为您增加了大量开销。只有当您重定向到的资源非常大时才有意义,并且本地区域群集将能够更有效地提供服务。

  2. 任播(利用BGP路由)
    这就像Akamai这样的大玩家用于他们的CDN。基本上,互联网上有多个服务器具有完全相同的可路由IP地址。假设我在多个地区都有服务器,它们的IP地址为192.0.2.1。如果我在美国并尝试连接到192.0.2.1,并且有人在欧洲试图连接到192.0.2.1,那么我们可能会被路由到最近的服务器。这使用互联网自己的路由来查找流量的最佳路径(基于网络条件)。不幸的是,你不能只使用这种方法。您需要自己的AS号和物理硬件。如果你找到一个VPS提供商,让你有一大块他们的Anycast块,请告诉我!

  3. 地理DNS
    有些DNS提供商提供的服务通常称为“地理DNS”。他们在任播地址上托管了一堆DNS服务器,可以将流量路由到最近的服务器。如果客户端查询欧洲DNS服务器,则应返回欧洲区域服务器的地址,而不是其他区域的某些服务器。地理DNS服务有很多变化。其他人只是简单地维护一个地理IP数据库并返回他们认为更接近的区域的服务器,就像重定向方法一样,但是在发出HTTP请求之前用于DNS。这通常是价格和易用性的好选择。

  4.   

    后续请求是否会路由到同一个IP?

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

      

    会话怎么样?

    这正是你想要那种粘性的原因。说到会话数据,您将不得不找到一种方法来使所有服务器保持最新状态。实际上,这并不总是得到保证。你如何处理它取决于你的应用程序。您是否可以保留Redis实例或其他任何内容,以便您的所有服务器能够可靠地从世界各地进行攻击?你真的需要每个地区的会话数据吗?或者您可以让主应用程序服务器在一个位置处理会话数据吗?

      

    任何DNS示例?

    针对这些提出单独的问题。每个人的“成功设置”看起来都不同。

      

    SSL / TLS怎么样?

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

答案 1 :(得分:12)

工作解决方案

在过去的几个月中,我已经疯狂地驾驭整个Global-HA设置。很有趣,我终于找到了一个非常有效的装备,并且与上面提到的问题完全不同。

我仍然计划以教程的形式写这篇文章,但是当我进入最后的冲刺阶段以便在明年初推出我的应用程序时,时间很少,所以这里是我最终的工作装备的快速概述

<小时/>

<强>概述

我最终将整个部署移至AWS。我喜欢数字海洋,但坦率的现实是,在一个屋檐下提供的服务方面,AWS比他们(以及每个人)都要轻松多年。我的每月费用略有增加,但是一旦我完成了调整和精简,我最终得到的解决方案是,对于最基本的部署,每个区域的成本约为75美元/月(ELB背后的2个实例)。一个新的区域可以在大约30分钟内完成并部署。

<小时/>

全球平衡

我很快发现(感谢@ Brad上面的回答)试图启动我自己的全局平衡DNS层是疯了。找到像这样的层是如何工作的,这是一个很有趣的地方,但是没有在飞机上刮我的指关节,在世界各地安装价值数百万美元的设备,这是不可能滚动我的自己的。

当我终于找到了我想要的东西时,我找到了我最好的朋友:AWS Route 53。它提供了一个强大的DNS网络,大约50-odd nodes globally,并能够做一些非常酷的路由技巧,如基于位置的路由,基于延迟的路由(这有点棒),以及AWS Alias自动记录&#39; #39;将流量路由到您将要使用的其他AWS服务(与ELB一样用于负载平衡)。

我最终使用了基于延迟的路由,将全局流量定向到最近的区域Elastic Load Balancer,该平衡器在任何给定区域都附加了Auto-Scaling组。

我会留给您做其他提供商的作业:www.f5.comwww.dyn.comwww.akamai.comwww.dnsmadeeasy.com。根据您的需求,可能会有更好的解决方案,但这对我来说非常有效。

<小时/>

内容分发网络

Route 53非常好地与AWS Cloudfront集成。我设置了一个S3存储桶,用于存储用户将上传的所有静态媒体文件,并且我已将Cloudfront分配配置为从我的media.myapp.com S3存储桶中获取。还有其他CDN提供商,您的购物也是如此。但Cloudfront获得了相当不错的评论,而且设置很简单。

<小时/>

负载均衡&amp; SSL终止

我目前正在使用AWS Elastic Load Balancer来平衡我的应用程序实例的负载,这些实例位于Auto-Scaling Group。该请求首先由ELB收到,此时SSL终止,请求将传递给Auto-Scaling组中的实例。

注意: ELB的一个巨大警告是,有点讽刺的是,它并没有很好地处理大量尖峰。 ELB最多可能需要15分钟才能触发自身的放大事件,同时创建500次/超时。据说可以很好地处理稳定,持续的流量增加,但是如果你遇到尖峰,它可能会让你失望。如果您知道自己会受到打击,那么您可以提前打电话给&#39;和AWS会为你热身你的ELB,这对于AWS的本质来说是非常荒谬和反模式的,但是我想他们要么正在制作它,要么忽略它,因为它并不是那么大一个问题。如果ELB不适合您,您可以随时启动自己的HAProxyNginx负载均衡层。

<小时/>

Auto-Scaling Group

每个区域都有一个ASG,可以在负载超过某个指标时进行编程:

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

我还没有完成ELB / ASG组合的步伐。这在我的待办事项列表中有一点点,但我知道有很多其他人使用此设置,但它似乎没有任何重大的性能问题。

在我看来,Auto-Scaling Group的配置有点令人费解。它实际上分为三个步骤:

  1. 根据您的喜好创建AMI。
  2. 创建使用您已创建的AMI的启动配置。
  3. 创建一个Auto-Scaling组,该组使用您已创建的启动配置来确定要为任何给定的SCALEUP事件启动的AMI和实例类型。
  4. 要在任何实例启动时处理配置和应用程序部署,您可以使用"User Data"字段输入将在任何给定实例启动时运行的脚本。这可能是历史上最糟糕的命名法。如何&#34;用户数据&#34;描述了只有作者知道的启动脚本。无论如何,你在哪里坚持处理所有apt-gets,mkdirs,git克隆等的脚本。

    <小时/>

    实例&amp;内部平衡

    我还添加了一个额外的内部平衡层&#39;使用Nginx,让我可以“扁平化”每个实例上的所有Node.js应用程序(app.myapp.com,api.myapp.com,mobile.myapp.com,www.myapp.com,etc.myapp.com)。当实例收到从ELB传递给它的请求时,Nginx会处理将请求路由到任何给定应用程序的正确Node.js端口。有点像穷人的集装箱化。这样做的另一个好处是,只要我的某个应用需要与另一个应用进行通信(例如app.需要向api.发送请求),就可以通过localhost:XXXX完成而不是必须通过AWS网络或互联网本身。

    此设置还可以通过消除任何空闲基础架构来最大限度地利用我的资源,如果它所托管的应用层恰好接收到轻量级流量。它还避免了为每个应用程序提供ELB / ASG组合的需要,从而节省了更多现金。

    我在使用这种设置时遇到过没有问题或警告,但在健康检查方面需要有一个解决方法(见下文)。

    还有一个很好的好处,因为所有实例都具有IAM角色,这意味着your AWS creds are 'baked in' to each instance在出生时可通过您的ENV vars访问。而AWS&#39;自动化&#39;为你转动你的信誉。非常安全,非常酷。

    <小时/>

    健康检查

    如果你走上述设置的路线,将所有应用程序平放在一个盒子上并运行内部负载均衡器,那么你需要创建一个小实用程序来处理ELB Health Checks。我做的是创建一个名为ping.myapp.com的附加应用程序。然后我配置了我的ELB运行状况检查,将任何运行状况检查发送到运行我的ping应用程序的端口,如下所示:

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

    这会将所有运行状况检查发送给我的小ping帮助程序,后者会在驻留在该实例上的所有应用程序上点击localhost:XXXX/ping。如果他们都返回200响应,我的ping应用程序然后返回200响应ELB运行状况检查,实例再生存30秒。

    注意:如果您正在使用ELB,请不要使用Auto-Scaling Health Checks。使用ELB运行状况检查。它有点令人困惑,我认为它们是同一个东西,它们不是。您可以选择启用其中一个。和ELB一起去。

    <小时/>

    数据层

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

    <小时/>

    <强>钽沓!

    啤酒预算的全球高可用性。我花了6个月才弄明白。

    喜欢听到任何恰好阅读此内容的人的任何意见或想法。

答案 2 :(得分:2)

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

答案 3 :(得分:-1)

Digital Ocean现在支持服务器本身的负载平衡。设置起来非常简单,效果很好!节省您必须添加不必要的组件,如nginx(如果您只想用于负载平衡)。

我们在数字海洋服务器上使用nginx上传SSL文件时遇到了问题,但是自从Digital Ocean更新以来,我们已经删除了nginx,现在使用了Digital Ocean的负载均衡功能,它就像我们需要的那样工作!