AnyCast 负载均衡

原作者: 马修·普林斯

2013年3月初,Cloudflare 中断了一个小时。值得庆幸的是,这种中断对于我们的服务而言是相对罕见的事件。尽管有成千上万的客户,他们产生了大量合法流量,并且我们不断代他们减轻大规模拒绝服务攻击。上周末的中断暴露了我们正在努力消除的架构缺陷,但我们的系统在很大程度上已设计成平衡的,没有单点故障。我们没有过多讨论CloudFlare系统的体系结构,但认为其他社区可能会受益于看到我们做出的一些选择,如何对系统进行负载均衡以及如何使我们快速有效地扩展。

失败不是选择,而是事实

CloudFlare的架构始于一个假设:故障将要发生。 所以我们必须为每个级别的故障进行计划,并设计一个在故障发生时能够妥善处理的系统。 要了解我们如何做到这一点,您必须了解CloudFlare边缘系统的组件。我们在网络边缘部署以下四个关键组件:

  1. 网络: CloudFlare的23个数据中心(内部称为PoP)通过多个提供商连接到世界其他地区。这些连接既通过传输(带宽)提供程序,也通过我们直接与之对等的其他网络进行。
  2. 路由器:在我们每个PoP的边缘都有一个路由器。该路由器宣布数据包从Internet其余部分到达CloudFlare网络的路径。
  3. 交换机:在每个PoP中,将有一个或多个交换机在PoP的局域名网(LAN)内聚合流量。
  4. 服务器:每个交换机后面都有一组服务器。这些服务器执行一些关键任务来增强CloudFlare的服务,包括DNS解析,代理,缓存和日志记录。

这些是我们在全球各地运行的机架中的四个组件。您会注意到典型的硬件堆栈中的某些内容似乎丢失了。例如,没有硬件负载平衡器。硬件负载平衡器(和硬件防火墙)的问题在于,它们经常成为瓶颈并自己造成单点故障。我们使用路由协议来分散流量并处理故障,而不是依靠硬件来在我们的网络上进行负载平衡。

Anycast是您的朋友

对于大多数Internet,IP地址对应于连接到公共Internet的单个设备。在您的家庭或办公室中,您可能有多个设备使用网络地址转换(NAT)坐在网关后面,但是只有一个公用IP地址,而位于网络后面的所有设备都使用唯一的私有IP地址(例如,空格192.168.XX或10.XXX)。互联网上的一般规则是每个设备一个唯一的IP。这是一种称为单播的路由方案。但是,这不是唯一的方法。

有四种主要的路由方案:单播,组播,广播和任意播。组播和广播是所谓的一对多路由方案。使用广播,一个节点发送的数据包到达所有接收者节点。广播不再被广泛使用,实际上并没有在IPv6中实现(它最大的当代用途可能是动了SMURF DDoS攻击)。使用多播,一个节点发送的数据包会击中已选择加入组的多个(但不是全部)接收方节点(例如,有线电视公司如何通过IP网络传送电视广播)。

没有负载均衡器的负载均衡

单播和任意播是一对一的路由方案。在这两种情况下,数据包都有一个发送者和一个接收者。两者之间的区别在于,虽然整个网络上对于通过单播发送的数据包只有一个可能的目的地,但对于Anycast,则存在多个可能的目的地,并且网络本身会选择最优先的路由。在广域名网(WAN)上。Internet-此首选项是从发送方到接收方的最短路径。在LAN上,可以使用路由器所遵循的权重来设置首选项。

WAN上的任意播

在CloudFlare,我们在两个级别上使用Anycast:WAN和LAN。在WAN级别,CloudFlare的23个数据中心中的每个路由器都宣布了我们所有的外部IP地址。例如,CloudFlare宣布用于DNS服务的IP之一是173.245.58.205。所有23个CloudFlare数据中心都宣布了到该IP地址的路由。当您将数据包发送到该IP地址时,它会通过一系列路由器。这些路由器查看通向CloudFlare端点的可用路径,并将数据包沿途中停靠最少的路径(即“跳数”)发送。您可以运行traceroute来查看每个步骤。

如果我从位于旧金山的CloudFlare的办公室运行跟踪路由,则我的数据包采用的路径是:

 $ traceroute 173.245.58.205
 到173.245.58.205(173.245.58.205)的traceroute,最大64跳,52字节数据包
 1 192.168.2.1(192.168.2.1)3.473毫秒1.399毫秒1.247毫秒
 2 10.10.11.1(10.10.11.1)3.136毫秒2.857毫秒3.206毫秒
 3 ge-0-2-5.cr1.sfo1.us.nlayer.net(69.22.XX)2.936毫秒3.405毫秒3.193毫秒
 4 ae3-70g.cr1.pao1.us.nlayer.net(69.22.143.170)3.638毫秒4.076毫秒3.911毫秒
 5 ae1-70g.cr1.sjc1.us.nlayer.net(69.22.143.165)4.833毫秒4.874毫秒4.973毫秒
 6 ae1-40g.ar2.sjc1.us.nlayer.net(69.22.143.118)8.926毫秒8.529毫秒6.742毫秒
 7 as13335.xe-8-0-5.ar2.sjc1.us.nlayer.net(69.22.130.146)5.048毫秒
 8 173.245.58.205(173.245.58.205)4.601毫秒4.338毫秒4.611毫秒

如果您从伦敦的Linode服务器运行相同的traceroute,则我的数据包采用的路径是:

 $ traceroute 173.245.58.205
 跟踪路由到173.245.58.205(173.245.58.205),最大30跳,60字节数据包
 1 212.111.XX(212.111.XX)6.574毫秒6.514毫秒6.522毫秒
 2 212.111.33.X(212.111.33.X)0.934毫秒0.935毫秒0.969毫秒
 3 85.90.238.69(85.90.238.69)1.396毫秒1.381毫秒1.405毫秒
 4 ldn-b3-link.telia.net(80.239.167.93)0.700毫秒0.696毫秒0.670毫秒
 5 ldn-bb1-link.telia.net(80.91.247.24)2.349毫秒0.700毫秒0.671毫秒
 6 ldn-b5-link.telia.net(80.91.246.147)0.759毫秒0.771毫秒0.774毫秒
 7 cloudflare-ic-154357-ldn-b5.c.telia.net(80.239.161.246)0.917毫秒0.853毫秒0.833毫秒
 8 173.245.58.205(173.245.58.205)0.972毫秒1.292毫秒0.916毫秒

在这两种情况下,第八跳和最后一跳都是相同的。但是,您可以从第七跳的提示(下面以红色突出显示)中看到它们正在访问不同的CloudFlare数据中心:as13335.xe-8-0-5.ar2。SJC 1.us.nlayer.net暗示它是打圣何塞和CloudFlare的-IC-154357- LDN -b5.c.telia.net暗示它是打伦敦。

由于数据包将遵循最短路径,因此,如果取消了特定路径,则数据包将找到通往下一条最短可用路由的路径。对于不维护状态的简单协议(如UDP),Anycast是理想的选择,并且已广泛用于平衡DNS负载一段时间。在CloudFlare,我们已经进行了大量的工程设计,以允许TCP在Anycast上运行而不会发生波动。这包括仔细调整路由以获取最佳路由,还调整我们处理协议协商本身的方式。尽管维护工作比单播网络复杂,但好处是我们可能会丢失整个数据中心,并且数据包会流到下一个最近的设备,而不会引起任何注意和打h。

局域名网中的任意播

数据包到达特定的CloudFlare数据中心后,我们要确保它到达可以正确处理请求的服务器。CloudFlare的服务器执行四个关键任务:DNS,代理,缓存和日志记录。我们倾向于遵循类似Google的方法,并部署可以执行许多不同功能的通用白盒服务器。(顺便说一句,如果有人感兴趣,我们正在考虑撰写博客文章,以“浏览”典型的CloudFlare服务器,并讨论在与制造商合作设计服务器时所做的选择。)由于服务器可能会发生故障或过载,因此我们需要以便能够围绕问题智能地路由流量。为此,我们回到了我们的老朋友Anycast。

没有负载均衡器的负载均衡

使用Anycast,CloudFlare的每个数据中心内的每个服务器都设置为接收来自我们任何公共IP地址的流量。到这些服务器的路由是通过边界网关协议(BGP)从服务器本身宣布的。为此,我们使用了一个名为Bird的软件。尽管所有服务器都为所有IP宣布了通过LAN的路由,但每个服务器都为每个IP路由分配了自己的权重。然后将路由器配置为优先选择权重最低的路由。

如果服务器崩溃,Bird将停止宣布到路由器的BGP路由。然后,路由器开始使用加权值第二低的路由向服务器发送流量。我们还监视每台服务器上的关键进程。如果这些关键过程中的任何一个失败,那么它可以通知Bird撤回一条路线。这不是全部或全部。监视器知道服务器自身的负载以及数据中心中其他服务器上的负载。如果特定服务器开始变得超载,并且其他地方似乎有足够的容量,则仅某些BGP路由可以撤出,以使某些流量脱离超载的服务器。

除了故障转移之外,我们还开始尝试使用BGP进行真正的负载平衡。在这种情况下,对多台服务器的权重相同,并且路由器对源IP,目标IP和端口进行哈希处理,以便始终如一地将流量路由到同一台服务器。可以调整哈希映射表以增加或减少集群中任何计算机的负载。使用简单协议(如UDP)相对容易,因此我们正在将其用于DNS。对于需要维护某些会话状态的协议(例如TCP)而言,这比较棘手,当您插入SSL时,协议仍然棘手,但是我们实验室中有一些很酷的功能,可以帮助我们更好地将负载分散到所有可用资源上。

故障场景

没有负载均衡器的负载均衡

要了解此设计架构,仔细考虑一些常见的故障场景很有用。

  1. 进程崩溃:如果核心进程(DNS,代理,缓存或日志记录)崩溃,则服务器上运行的监视器守护程序会检测到故障。监控器向Bird发出信号,要求撤回路由到该进程的BGP路由(例如,如果仅DNS崩溃,则将撤消用于CloudFlare名称服务器的IP,但服务器仍将响应代理流量)。撤回路由后,数据中心中的路由器会将流量发送到权重倒数第二低的路由。监视守护程序将重新启动DNS服务器,并在验证它干净无误后,向Bird发出信号以再次开始通告路由。
  2. 服务器崩溃:如果整个服务器崩溃,Bird也会随之崩溃。到服务器的所有BGP路由都将被撤消,并且路由器将以最低的路由权重将流量发送到服务器。数据中心内控制服务器上的监视进程尝试使用IPMI管理界面重新启动该盒子,如果失败,则从新电源板(PDU)重新启动电源。监视进程确认框已完全恢复正常之后,Bird将重新启动,并重新启动到服务器的路由。
  3. 交换机崩溃:如果交换机发生故障,则到该交换机后面的服务器的所有BGP路由都会自动撤消。如果路由器丢失了到计算机的足够路由,从而将与那些路由相对应的IP丢弃到WAN Anycast池之外,则配置路由器。这些IP的流量故障转移到下一个最近的数据中心。受影响的数据中心内外的监视器都会向我们的网络团队发出警报,该团队监视网络24/7发生了交换机故障,以便他们可以调查并尝试重新启动。
  4. 路由器崩溃:如果路由器发生故障,则会撤消该路由器负责的数据中心的所有WAN上的BGP路由。到数据中心的流量会自动故障转移到下一个最近的数据中心。受影响的数据中心内外的监视器都会向我们的网络团队发出警报,该团队监视网络24/7发生了路由器故障,以便他们可以调查并尝试重新启动。
  5. 全球热核战争:这很糟糕,但是CloudFlare可能仍然能够将流量路由到互联网上剩下的任何部分。随着设施的蒸发(从拉斯维加斯开始),他们的路由器将停止宣布路由。只要某些设施与网络的其余部分保持连接(也许是澳大利亚的悉尼?),它们就会为目的地客户的流量提供一条路径。我们对网络进行了设计,以使其一半以上可以完全失效,并且我们仍然能够跟上流量。

觉得文章有用?

点个广告表达一下你的爱意吧 !😁