通常,像 Amazon 的弹性负载均衡器这样的负载均衡器使用具有多个 A 记录的 DNS 记录集来提供多个负载均衡器实例,这些实例可以处理到请求端点的流量:
$ dig +short my-fancy-elb.us-east-1.elb.amazonaws.com
10.0.1.1
10.0.1.2
如果我尝试以详细模式卷曲此 URL,我注意到这curl
似乎是对两个 IP 地址的循环尝试:
$ curl -ivs http://my-fancy-elb.us-east-1.elb.amazonaws.com | grep -i 'connected'
* Connected to my-fancy-elb.us-east-1.elb.amazonaws.com (10.0.1.1)
$ curl -ivs http://my-fancy-elb.us-east-1.elb.amazonaws.com | grep -i 'connected'
* Connected to my-fancy-elb.us-east-1.elb.amazonaws.com (10.0.1.2)
curl
对记录集中描述的 A 记录进行循环处理的事实是由curl
二进制文件本身完成的,还是 Linux 内核为它做的事情?
TCP 存在于第 4 层,DNS 存在于第 7 层,所以我想各个二进制文件和库必须实现自己的负载平衡和故障转移:获取给定域名的 DNS 记录集并选择一个 TCP 地址从该集合连接到。
我可以合理地期望像 curl 这样的编程语言、浏览器和库会为我在 A 记录上进行负载平衡和故障转移吗?
简短的回答是它会有所不同。
当答案集中存在多个地址记录时,被查询的 DNS 服务器通常以随机顺序返回它们。操作系统通常会按照接收到的顺序将返回的记录集呈现给应用程序。也就是说,交易双方(名称服务器和操作系统)都有可能导致不同行为的选项。通常不使用这些。
/etc/gai.conf
例如,在基于 glibc 的系统上,一个鲜为人知的文件控制着这一点。Zytrax 书(火箭科学家的 DNS)很好地总结了这个主题的历史,并得出结论认为RFC 6724是应用程序和解析器实现应该遵守的当前标准。
从这里值得注意的是来自 RFC 6724的选择引用:
该标准鼓励应用程序在失败时不要停在第一个地址,但这既不是要求,也不是许多随意编写的应用程序将要实现的行为。除非您确定更大(或至少最重要)百分比的使用应用程序会很好地发挥作用,否则您永远不应仅仅依靠多个地址记录来实现高可用性。现代浏览器往往在这方面做得很好,但请记住,它们不是您要处理的唯一消费者。
(另外,正如@kasperd 在下面指出的那样,区分这在 HA 和负载平衡中给您带来的好处很重要)
我的猜测是记录的 DNS TTL 设置得非常低,
curl
每次都需要重新解析,并且会从 DNS 服务器获取另一个 IP。无论
curl
是内核还是内核都完全不知道这种 DNS 级别的负载平衡发生了,你不能合理地期待这样的事情。基本的事情是 DNS 服务器通常以伪随机方式循环记录。
在 curl 的情况下,它有自己的 DNS 解析库,它尊重服务器呈现的顺序。
在https://daniel.haxx.se/blog/2012/01/03/getaddrinfo-with-round-robin-dns-and-happy-eyeballs/上有一个关于这个主题的故事。那里也提到了 curl 的实现。
两者都不。它通常是更改 IP 地址的 DNS 服务器。curl 库需要解析主机名以获取每个请求的 IP 地址。它将请求发送到 DNS 服务器,该服务器发回 IP 地址列表。DNS 服务器也可以在同一台机器上进行本地缓存。大多数 DNS 服务器会在每个请求中轮换 IP 列表。因此,随着列表的顶部 IP 发生变化,您在每个请求中都会获得不同的 IP。如果您从一台 linux 机器上 ping www.google.com,您可能每次都会看到不同的地址。
我使用 curl 进行了测试以通过 http 获取文件。当第一个 IP 不可访问(故障转移)时,Curl 能够使用另一个 IP 重试。所以'故障转移'正在使用 curl 处理 http 请求。