域名劫持,解析失败,调度不精准,没有异地容灾,域名解析变更生效不实时,这些问题是否一直困扰着你?作为网络请求最前置的环节,域名解析的稳定与精准程度直接决定了 App 的访问体验效果。跟随本文来一起了解域名解析,探索移动互联网场景下域名解析的最佳实践方案。
域名(英语:Domain Name),又称网域,是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称,用于在数据传输时对计算机的定位标识(有时也指地理位置)。
由于 IP 地址具有不方便记忆并且不能显示地址组织的名称和性质等缺点,人们设计出了域名,并通过网域名称系统(DNS,Domain Name System)来将域名和 IP 地址相互映射,使人更方便地访问互联网,而不用去记住能够被机器直接读取的 IP 地址数串。—— 来源自百度百科“域名”词条
作为一次网络通信最前置的环节,域名解析的重要性不言而喻。在传统的基于浏览器的网站访问场景下,域名解析环节由浏览器内核实现,网站开发者无需关心域名解析的细节。But there are always two sides to every coin,一旦域名解析环节发生异常,开发者面对这样的黑盒架构就会显得束手无策,一个很典型的例子即域名劫持问题,关于这一点我们在后文会有更详细的介绍。
我们来看一看一次传统的域名解析流程具体是如何发生的:
如上图所示,以访问 www.taobao.com 为例,一次完整的域名解析流程包括:
注意:Local DNS 服务器包含缓存模块,在实际域名解析过程中 Local DNS 服务器会首先查询缓存,缓存命中且解析结果 TTL 未过期的情况下直接返回,否则才启动递归查询的流程。
域名劫持一直是困扰许多开发者的问题之一,其表现即域名 A 应该返回的 DNS 解析结果 IP1 被恶意替换为了 IP2,导致 A 访问失败或访问了一个不安全的站点。下面我们是几种常见的域名劫持的场景。
一种可能的域名劫持方式即黑客侵入了宽带路由器并对终端用户的 Local DNS 进行篡改,指向黑客自己伪造的 Local DNS,进而通过控制 Local DNS 的逻辑返回错误的 IP 信息进行域名劫持。
另一种我们最常碰到的域名劫持现象是缓存污染。我们知道在接收到域名解析请求时,Local DNS 首先会查找缓存,如果缓存命中就会直接返回缓存结果,不再进行递归 DNS 查询。这时候如果 Local DNS 针对部分域名的缓存进行更改,比如将缓存结果指向第三方的广告页,就会导致用户的访问请求被引导到这些广告页地址上。
部分业务场景下开发者对域名解析结果变更的生效时间非常敏感(这部分变更操作是开发者在权威 DNS 上完成的),比如当业务服务器受到攻击时,我们需要最快速地将业务 IP 切换到另一组集群上,这样的诉求在传统域名解析体系下是无法完成的。
Local DNS 的部署是由各个地区的各个运营商独立部署的,因此各个 Local DNS 的服务质量参差不齐。在对域名解析缓存的处理上,各个独立节点的实现策略也有区别,比如部分节点为了节省开支忽略了域名解析结果的 TTL 时间限制,导致用户在权威 DNS 变更的解析结果全网生效的周期非常漫长(我们已知的最长生效时间甚至高达 48 小时)。这类延迟生效可能直接导致用户业务访问的异常。
DNS 首次查询或缓存过期后的查询,需要递归遍历多个 DNS 服务器以获取最终的解析结果,这增加了网络请求的前置延时时间。特别是在移动互联网场景下,移动网络质量参差不齐,弱网环境的 RTT 时间可能高达数百毫秒,对于一次普通的业务请求而言,上述延时是非常沉重的负担。另一方面,弱网环境下的解析超时、解析失败等现象屡见不鲜,如何合理优化 DNS 解析对于整体网络访问质量的提升至关重要。
传统域名解析面临的诸多问题与挑战本质根源在于 Local DNS 的服务质量不可控,如果有一个更安全、稳定、高效的递归 DNS 服务帮助我们代理了域名解析的过程,这些问题就可以彻底地得到解决。
HTTPDNS 在这样的背景下应运而生。我们一起来看看 HTTPDNS 的基本概念以及它是如何解决传统 DNS 解析面临的问题的。
HTTPDNS 使用 HTTP 协议进行域名解析,代替现有基于 UDP 的 DNS 协议,域名解析请求直接发送到 HTTPDNS 服务端,从而绕过运营商的 Local DNS。
HTTPDNS 代替了传统的 LocalDNS 完成递归解析的功能,基于 HTTP 协议的设计可以适用于几乎所有的网络环境,同时保留了鉴权、HTTPS 等更高安全性的扩展能力,避免恶意攻击劫持行为。另一方面,商业化的 HTTPDNS 服务(比如阿里云 HTTPDNS、腾讯云 HTTPDNS)缓存管理有严格的 SLA 保障,避免了类似 Local DNS 的缓存污染的问题。
在域名解析生效周期方面,HTTPDNS 也有着传统域名解析体系所无法具备的能力。前面我们提到由于各个地区的 Local DNS 是独立维护的,服务质量参差不齐,缓存实现不一,因此导致的解析变更全网生效滞后的问题,在商业化的 HTTPDNS 服务上就不会存在(HTTPDNS 严格遵循 DNS TTL 限制进行缓存更新)。另一方面,即便我们假设 Local DNS 严格遵循域名 TTL 时间进行缓存管理(这里我们假设运维配置的域名 TTL 时间为 5min),当我们的业务受到攻击并需要快速进行切换时,Local DNS 也会遵循域名 TTL,在持续 5min 的时间段内返回旧 IP 信息,这 5min 的业务影响对于中大型企业而言是一个不小的损失(对于电商类的大型企业,5min 的访问异常可能意味着几百万的交易额下跌)。以阿里云 HTTPDNS 服务,HTTPDNS 在快速生效方面有专有的方案,配合阿里云的权威 DNS 服务云解析(我们的域名都是部署在阿里云的权威 DNS 服务云解析上面),用户在权威 DNS 变更的解析结果将快速同步给 HTTPDNS,覆盖原有的缓存记录,帮助用户实现毫秒级的域名解析切换。
商业化的 HTTPDNS 服务,都具备 99.99% 的高可用性, 确保域名解析服务稳定可靠。
HTTPDNS 客户端直接通过 IP 来进行域名解析请求的,HTTPDNS SDK 内部维护一个 IP 轮询池,当某个 IP 不可用时,会自动切换其他的 IP,并且 IP 轮询池也会更新。
HTTPDNS 服务端方面,拿阿里云的 HTTPDNS 来说,在全球有数十个服务集群,各个服务集群互相备份,具备异地容灾备份功能,当某个服务集群不可用时,会自动切换到其他的服务集群,可以确保解析和缓存正常。
绝大多数的 APP 在应用初始化阶段都有一个启动期,我们可以在这个启动期做一些 preflight 工作,即在初始化阶段我们可以针对业务的热点域名在后台发起异步的 HTTPDNS 解析请求。这部分预解析结果在后续的业务请求中可以直接使用,进而消除首次业务请求的 DNS 解析开销,提升 APP 首页的加载速度。
懒加载策略的实施可以让我们真正实现 DNS 的零延迟解析。所谓懒加载策略,核心的实现思路如下:
下图描绘了预解析+懒加载的实现框架:
HTTPDNS 方案一共分为两期,一期方案为模拟统计方案,暂不接入 HTTPDNS SDK,主要目的是进行数据统计。统计出我们需要解析的域名列表,以配置在 HTTPDNS 后台。此外,还需要统计出我们的域名占比,方便后续的进行预加载。最后,也是最重要的一点,预估我们的费用,通常商业化 HTTPDNS 服务都是按解析次数计费的。
服务端控制灰度下发,命中灰度的情况下走 HTTPDNS 模拟器逻辑,没有命中灰度的情况下走老逻辑。灰度为 0 的时候全量走老逻辑,灰度为 100 的时候全量切 HTTPDNS 模拟器逻辑。
我们需要一个 HTTPDNS 模拟器,用来模拟 HTTPDNS SDK 的行为、数据统计、埋点上报。模拟器流程如下:
模拟 HTTPDNS SDK 中域名解析结果的缓存时间,version 用于埋点区分,ttl 由各自的版本决定:
版本查询流程:
每一次进入 HTTPDNS 模拟器,最后都需要进行埋点上报,上报的字段有:
二期会正式接入阿里云 HTTPDNS SDK,支持 HTTPDNS 域名解析。同时,支持预解析、灰度控制、白名单等功能。
配置中心控制 HTTPDNS 功能灰度下发,以及 HTTPDNS 可配置的白名单。灰度控制走 HTTPDNS 域名解析流程的用户占比,为 0 时全量走标准 DNS 解析,为 100 时 全量走白名单判断。命中灰度的情况下,在降级过滤器里面,白名单内的走 HTTPDNS 流程,白名单外的走标准 DNS 解析流程。
埋点时机:命中标准 DNS 的时候进行埋点,对解析异常情况进行监控。
综上可以看到,当我们需要实现零延迟解析的效果时,在客户端还是有比较多的工作需要做的。当然对于复杂的生产环境,埋点和监控也是必不可少的环节。
文|走歌人
关注得物技术,携手走向技术的云端
领取专属 10元无门槛券
私享最新 技术干货