【HttpDns】解决 APP 无法找到主机问题

本文中会提到部分厂商,不过均为举例需要或客观推荐的解决方案,并无任何利益关系

有用户反应产品偶然会出现『未能找到使用指定主机的服务器』问题,应该是 DNS 没有正确解析。从监控记录中并没有发现什么问题,各地的监测点的结果都很正常,那就应该是用户所处网络环境出了问题。

为了尽量提高产品可用性,进行了 HTTP DNS 的改造。


什么是 HTTP DNS

普通的网络请求,系统自动通过 DNS Server 将目标域名解析成 IP 地址,然后向这个 IP 地址发送请求完成数据交互。这个解析的过程对于 APP 来说是不可见的。

HTTP DNS 则是 APP 主动向 HTTP DNS Server 发送解析请求,Server 返回目标域名对应的 IP 地址,然后 APP 直接向目标地址发送请求,绕开了系统解析的这个环节,避免了用户所处环境带来的干扰。

当然 HTTP DNS Server 也是通过 IP 地址直接访问的,比如 DNSPod 免费版的 119.29.29.29,还有其他厂商可以自己寻找。

如何进行改造

根据改动范围是否设计后端(包括运维)有两种方法

A. 前后端配合版

这种改造方案非常简单,后端 Web Server 将 IP 地址直接绑定到目标站点,APP 在发起请求前,直接将所有 URL 中自己域名的部分换为通过 HTTP DNS 获得目标 IP 即可。

当然如果后端有针对域名的逻辑也需要处理下,比如防盗链用的 Referer 校验等。

另外有的第三方库(比如支付宝)需要 APP 传入 Server 回调地址。这种是没必要改的,毕竟请求来自 IDC 机房等网络环境很好的场合。不过一定要改的话,这种地址可能在第三方平台上有绑定审核,实际动手前请提前准备审核。

B. APP 单独版

不同公司合作开发或者一台 Server 托管了若干站点的情况,只能 APP 自己想办法了。这种稍微麻烦点,针对不同用途的 URL 需要做不同的处理。

  1. 普通请求,类似于 REFTful API,每次请求完成一个动作,比如获得数据之类
    这种可以直接用 IP 替换域名,然后在 HTTP request header 中将 Host 指定为域名即可。

  2. Webview 中加载 Web page
    如果只是加载用户协议、关于我们这种单页纯文本的东西,和普通请求相同改法即可。不过很多网页内都会有相对地址的超链接,Webview 内的超链接跳转时无法指定 Host 字段,后端 Server 可能无法正确处理这种请求。另外 cookie 等和域有关对的东西也容易出问题,所以这种类型最好还是维持域名访问的原状。

  3. 传给第三方库使用的回调地址
    同样,这种本来就没问题,强行改的话反而会出问题,所以不要更改。

  4. 第三方地址,比如 Apple Store 的评分页面,或者点击广告后跳转的营销页
    这种可改可不改,视具体情况而定,总体建议维持原状比较好。

一些有用的实践经验

  • APP 启动时异步 HTTP DNS 查询 IP 地址
    毕竟大部分用户网络状况都是正常的,没必要影响所有人的启动速度

  • 查到后将 IP 地址缓存
    除了内存外最好也能持久化缓存,这样下次启动时即使万一 HTTP DNS 查询比较慢也能确保有可用的 IP。

  • HTTP DNS 查询后触发进行一次系统的 DNS 解析
    仍有使用域名请求的场景(比如APP单独改造时用到 Webview)下使用。
    如果域名不是被刻意劫持或干扰,一般无法找到主机的问题只是解析过慢,提前触发查询后,等用户操作到相关逻辑时正常的概率就会更高。

  • 发送请求前若有 IP 则使用 IP,否则使用域名
    这是当然的 XD

  • 网络状况发生变化时,重新异步 HTTP DNS 查询 IP 地址
    如果产品在不同线路部署有不同 Server 的话,重新查询一遍可以确保总是使用最合适的那台。

第三方库

iOS/Android 都有现成的第三方库可供使用,GitHub 上有新浪和七牛的项目

Objective-C Java
新浪:貌似不成熟,开发者不推荐商用 新浪:功能异常强大,解释也很详细,请直接查看该项目主页
七牛:提供 DNSPod 等 HTTP 方式,也支持 nslookup 方式(可以指定 DNS Server) 七牛:同左边

另外七牛项目的分别发布到了 CocoaPods 和 maven 上更易使用,所以推荐七牛。

你可能感兴趣的:(【HttpDns】解决 APP 无法找到主机问题)