iOS网络请求优化之DNS映射

绝大多数网络请求的第一步都是DNS解析,解析请求根据当时网络情况不同,各平台的DNS缓存策略差异等因素,对移动端app整体网络性能会产生或大或小的影响。移动端app网络性能优化涉及到很多方面,DNS映射只是其中一环,也是十分重要的一环,因为它带来的好处不仅仅是降低网络请求的延迟。

降低DNS请求带来的延迟

客户端app的请求第一步都是DNS解析,但由于cache的存在使得大部分的解析请求并不会产生任何延迟。各品台都有自己的cache过期策略。像iOS系统一般是24小时之后会过期,还有进入飞行模式再切回来,开关机,重置网络设置等也会导致DNS cache的清除。所以一般情况下用户在第二天打开你的app都会经历一次完整的DNS解析请求,网络情况差的时候会明显增加应用请求的总耗时。如果能直接跳过DNS解析这一步,当然能提升网络性能了。

预防DNS劫持

DNS劫持指的是改变DNS请求的返回结果,将目的ip指向另一个地址。一般有两种方式,一是通过病毒的方式改变本机配置的DNS服务器地址,而是通过攻击正常DNS服务器而改变其行为。不管是哪种方式,都会影响app本身的业务请求。如果遇到恶意的攻击还会衍生出各种安全问题。客户端自己做DNS与ip地址的映射就跨过了解析,让劫持者无从下手。

服务器动态部署

DNS映射实际是模拟了DNS请求的解析行为。如果客户端将自己的位置信息诸如ip地址,国家码等加入映射文件的请求参数当中,服务器就可以根据客户端所处的位置不同,下发距离其物理位置最近的server ip地址,从而减小整体网络请求的延迟,实现一定程度的服务器动态部署。

如何设计自己的DNS映射机制?

DNS解析请求简单来说,无非是输入一个域名,输出一个ip地址。做自己的映射机制也就是客户端本地维护这样一个映射文件,只不过这个映射文件需要能从服务器更新,还要做一些容错处理。我们先从这几个基本要求出发制定下面几个必须满足的需求。

  • 一个打包到app包里面的默认映射文件,这样可以避免第一次去服务器取配置文件带来的延迟。
  • 有一个定时器能每隔一段时间从服务器获取最新的映射,并覆盖本地。
  • 每次取到最新的映射文件之后,同时把上一次的映射文件保存起来作为替补,一旦出现线上配置失误不至于导致请求无法处理。
  • 如果映射文件不能处理域名,要能回滚使用默认的DNS解析服务。
  • 如果一个映射过后的ip持续导致请求失败,应该能从机制上保证这个ip地址不再使用。也就是需要一个无效映射淘汰机制。
  • 无效的ip地址能及时上报到服务器,及时发现问题更新映射文件。

基于这些基本需求,可以做出如下简单的设计:

[图一]

大致有3个角色,mapper,validator,reporter。各自职责如下:

mapper

mapper是和外部交互的部分,主要负责在输入domain的情况下输出ip,同时还要检测来自应用层请求成功和失败的信息。失败的情况下要将失败的ip进行进一步的检测,以确定是否真的是ip地址无效,如果无效则进行上报。mapper还要负责从mapper文件的更新机制。

validator

validator在接受到请求失败的ip时,要负责对这个ip做进一步的有效性检测。检测规则的强弱可自己定制。但一般来说流程在后台线程使用这个地址做多次连接尝试。如果失败则告诉mapper这个地址确实无效。如果成功则表明这个地址有效,很有可能只是当时的网络环境导致了请求的失败。

reporter

reporter主要负责告诉server整个mapping机制的健康状况。在出现某个ip经过validator检测依然失败的情况下,要及时的告诉server出问题的ip。很有可能出现了某个服务器故障或者映射文件的配置失误等等。

在上面这些基础需求之外,还可以根据自身的业务特点及技术条件做一些深度定制。比如从服务器定期更新映射文件,可以改成socket长链接通道在需要更新时push,或者利用http2.0的server push机制。还有上报机制,除了上报错误的ip地址映射之外,还可以对请求的总量,成功率,映射成功率等数据进行侦测。

PPDNSMapping

PPDNSMapping是根据以上设计原则所做的iOS平台例子,附有测试demo代码。

PPDNSMappingManager对应图一当中的mapper,PPIPValidator对应validator,PPDNSReporter对应reporter。

github地址