我刚刚做了个测试,测试环境如下:
服务器 A ,IP 192.168.0.3
服务器 B IP 192.168.0.4
两台服务器都启动了一个 http 服务,端口是 7891
然后,我在本地 hosts 文件添加了以下的信息
192.168.0.3 test.com
192.168.0.4 test.com

在这个环境下,我 curl test.com:7891 当然是能访问的。这时候基本上都是访问了 192.168.0.3:7891 了。
curl 的输出符合预期。
然后我现在把 A 的 http 服务关了,超出我预期的情况发生了。curl 依然能返回 http 服务的返回数据。
我 curl -v 看了下,出现了类似这样的信息:
Trying 192.168.0.3:7891...

  • connect to 192.168.0.3 port 7891 failed: 拒绝连接*
    Trying 192.168.0.4:7891...
  • Connected to test.com (192.168.0.4) port 7891 (#0)

这超出我的意料了。而后我也尝试了下最新版本的 chrome ,也有这样的特性。
这是一直以来所有的 http 客户端都有的特性吗?

不能
多解析实际上更多用在负载平衡里(手段之一)

看一些架构师的文章,会提到这个技巧,当你的一个出口负载已经完全无法承载压力了,就让 DNS 服务器来帮你分流吧。
但是,走到这一步的话,要考虑的事情也是很多的。不到迫不得已,没必要这么做。比如数据一致性等。

另一个,“尝试一个 host 下所有的 ip”,应该不是所有 http 客户端的特性,还是要看语言具体的实现的。

不能是指什么?

你这个只是本机测试,你感觉可以用
但是放到线上环境
你的客户的并不一定支持尝试其他解析 IP
此外你的业务也不可能是单一页面单一节点

所应该是刚好我测试的 curl 和 chrome 这两个 http 客户端有这个特性了。了解。

这不是客户端的功能. 这是 dns 解析服务器的功能. 云服务厂商都提供了这个服务, dns 可以解析多个 ip, 而且可以指定入网的 ip 段来制定解析对应的 ip, 具体就是我指定联通网请求 dns 返回 123 的 ip, 电信网请求 dns 返回 456 的 ip.

浏览器在好多年前就会自动切换了,多 IP 的网站,浏览器访问一个 IP 超时之后,自动刷新使用到下一个 IP

但是 DNS 解析多个 IP 一般只用来做负载均衡,不用来做高可用,因为超时要等待好几秒,用户有可能还没等到切换 IP ,就以为网站打不开从而关掉页面了

不是,我只是第一次知道了有些 http 客户端有此特性,因此想求证下此特性是否是一个比较旧的 http rfc 了。 还不打算用于线上环境的。

了解。。这个超时是 dns 服务器决定的,还是客户端自身决定的?

你说的应该跟我想说的不是一回事。我想说的这个特性,是能够在访问 test.com--> 192.168.0.3 --> 192.168.0.3:7891 拒绝访问时,就切到了 test.com--> 192.168.0.4 --> 192.168.0.4:7891 ,这已经不但但是 dns 协议了,此切换还涉及了 tcp 协议。

看看我写的高可用?
isno.github.io/ 下一章节:负载均衡和网关

这里的目的,是分散可用,从而表现成一种高可用.你的测试仅代表你一个客户端,不适合这个解释。
在公网下很显然全球各地,每个区域都有不同的可用性结论,多 dns 解析可以经过一些逻辑,就近选用 dns

这应该是 curl 和 chrome 自己加戏了。
正常情况下,取得解析结果中的某一个结果,例如 192.168.0.3 。 然后尝试连接,如果出错,那就停止。 并没有规定要去尝试其他的解析结果。

另外如果 192.168.0.3 端口能够正常连接,但是返回 500 ,而 192.168.0.4 正常,返回 200 。 这个时候 curl 和 chrome 并不会去尝试连接 192.168.0.4 。

所以仅仅依靠 dns 解析,无法实现高可靠。

客户端吧,而且不同客户端的超时时间不一样,它们也不会特意缓存 IP 有效性,现在 A 超时自动切换到 B ,过一会儿 DNS 缓存失效了,它再次解析再次使用 A 地址也是可能的,然后再等超时再切换

DNS 可以用来做负载均衡,但做不了高可用。
因为 DNS 层层缓存,更新起来非常慢,有些垃圾网络环境甚至一天不更新的。

你的 hosts 貌似只第一个生效,你可以 ping 一下看看

你的回答是最直接,最全面解答了我的疑问了。。感谢。

嗯嗯,这个的确是。

这个只能负载均衡降低单 ip 负载,其它甚至会导致 sSLA 降低

上面的是错误的。。这不是加戏,是按文档的规范行为

可以去看 getaddrinfo 文档,建议也思考下 ipv6 浏览器如何使用。再了解下 happy eyeball 有哪些方案

这个是属于哪个规范的?

谢谢你,长见识了。

这相当于把负载均衡交给 dns 了,客户端随机从解析值挑一个 ip ,只能作为分流手段,高可用不太现实,如果 dns 返回了一个已经挂掉的 ip ,dns 也没办法知道,除非你前置一个检测手段检测服务挂了自动更改 dns 解析,差不多可以实现基础高可用。

这个叫 DNS round-robin ,或者叫 DNS 轮询。
en.wikipedia.org/wiki/Round-robin_DNS

这个是客户端功能,不是 DNS ,DNS 正常情况把一堆 IP 给客户端,你这个还只是简单的多 IPv4,目前客户端要处理的是 v6,v4 优先级.

感觉这个特性还真能做到某种层面的高可用,比如我们曾有服务 IP 地址被运营商封掉,如果方式那个服务的域名绑定了两个 IP ,哪怕是同一个主机,也不会导致某省用户全面掉线+我们花了整整一天排查这个问题

chrome 、curl 自己实现的自动重试下一个连接。

不过为了支持 ipv6 ,应该不少软件都会有类似的实现了。
ipv6 一般都是一个协议短期未成功则立刻同步另一个协议尝试。
顺便加上同协议多个 ip 地址并不麻烦。

另外 go 标准库我记得也是实现了单 ip 失败自动切换到另一个 ip 尝试。

因为我记得以前是没有这个特性的。看到 chrome 和 curl 都实现了,我猜应该是某个时候开始出现的一个共识,然后楼上就提到了 happy eyeball 。应该就是当时为了解决 ipv4 和 ipv6 并存的问题而被提出的,然后逐渐大家都这么干了。

不能,因为要看客户端实现,可能客户端就是随机选择其中一个