我们日常使用的网络协议,如 TCP/IP、DNS 等,是在几十年前为局域网而设计的。虽然现代的网络日新月异,但出于兼容的考虑,协议层的改进并不多,各大厂商的推进速度都很慢。
在这样的背景下,Surge 做了很多针对现代网络的改进,以提升用户的网络体验。
一、DNS 并发查询
背景
我们知道,一个域名并不能被直接访问,需要先将其转换为 IP 地址,这个过程就叫做 DNS。
一般情况下系统允许配置多个 DNS 服务器。但是,仅当第一个 DNS 服务器返回结果超时后,才会去查询第二个服务器。如果查询过程中出现了丢包,或者首要 DNS 服务器不可用,那么所有的 DNS 查询都将等待数秒后才能得到结果。
改进
Surge 会向所有配置的 DNS 服务器并发进行查询(与 dnsmasq 的行为类似),并直接使用最先返回的结果。以保证在不稳定网络环境下的查询效率,同时防止因首要 DNS 服务器失效产生的延迟。
二、TCP 并发连接
背景
你所访问的网站或者网络服务,通常都是由多个服务器进行负载均衡处理的,实现原理是当你查询一个域名时,DNS 服务器会对单个域名返回多个 IP 地址。如:
dig apple.com
; <<>> DiG 9.10.6 <<>> apple.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11908
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;apple.com. IN A
;; ANSWER SECTION:
apple.com. 1922 IN A 17.142.160.59
apple.com. 1922 IN A 17.172.224.47
apple.com. 1922 IN A 17.178.96.59
主流的操作系统/浏览器会优先使用返回第一个 IP 去进行请求。所以为了达到负载均衡的效果,DNS 服务器每次返回的 IP 顺序都是随机的(即 Round-robin DNS)。
如果返回的第一个 IP 不可用,那么操作系统/浏览器会去尝试第二个 IP,但是对于第一个 IP 失败这个问题,不同客户端判定的差异很大,最短的超时可能只有 10 秒,但是慢的可达 180 秒。也就是说,如果 DNS 返回的第一个服务器不可用,你要等 10 ~ 180 秒才能够切换到下一个服务器。
(有的时候我们发现某网站连不上,清空一下本地 DNS 缓存能解决,就是这个原因,清空后 DNS 返回了新的 IP 顺序)
另外如果第一个 IP 可用,大多数客户端再也不会去关心剩下的 IP 地址们,如果该网站的不同节点的响应速度差距很大,而你很不幸的连到了一个较慢的节点,那么在 DNS 结果过期前你都没有可能换到更好的节点去了。
改进
Surge 对于有多个 IP 的域名,会直接并发向所有 IP 进行 TCP 握手,并选择最快完成握手的连接进行后续请求。
不必担心这样的行为会增加整体的网络负担,TCP 握手的开销很小,而且仅当第一次访问该域名时才会进行并发测试,后续的请求将按照先前的测试结果使用优选 IP,如果出现了问题再重新尝试其他 IP。
这样的逻辑可以保证在访问有大量均衡节点的网站时,总能使用响应速度最快的节点,且遇到问题节点能直接绕过。
三、代理 DNS 查询
对于巨型网络服务商,其服务器可能遍布于全球各地,所以需要根据用户的网络环境去判断应该返回哪些节点的 IP,所以当我们使用代理服务器时,很重要的一点就是确保使用代理服务器的网络环境去执行 DNS 查询。如果在本地网络进行 DNS 查询后拿到 IP 地址,再通过代理网络去访问该 IP,访问速度会大打折扣甚至直接无法使用。
Surge 保证所有使用代理策略的请求一定由远端服务器进行 DNS 查询。
四、Optimistic DNS
背景
为了解决第二条中所述的节点服务器失效问题,很多网络服务商配置的 DNS TTL 非常短(即记录的缓存失效时间),如 Facebook 的 TTL 就为 30s。
这样服务商在发现节点异常时,可以迅速修改 DNS 记录以替换掉出问题的节点,也可以非常灵活的调整节点服务器部署。但是意味着客户端每 30 秒后就要重新进行一次 DNS 查询,为了防范故障情况而频繁地浪费时间去进行 DNS 查询,对于一般用户并不划算。
而且如果是访问的是冷门网站,DNS 解析时间可能会高达数秒,若该网站配置了极短的 TTL(如 30s),那么每 30 秒后的新请求就要卡上几秒,非常影响体验。
改进
Surge 参照了 Apple 在 WWDC 2018 中提出的 Optimistic DNS 方案,在本地 DNS 缓存过期时任然继续使用本地缓存结果的 IP 进行连接,同时进行新的 DNS 查询去更新缓存。如果原 IP 连接失败,再用新的结果进行重试。
该方案非常优雅的解决了因缓存过期带来的反复 DNS 延迟,同时并不影响服务商调整 DNS 记录。
(Apple 已经在部分产品上开始使用该方案,如 CloudKit)