# 背景

前段时间在处理 iOS 端的 HTTPDNS 相关 SDK,在接入和测试环节发现大家对 HTTP 的整体请求流程包括 HTTP 劫持原理以及 HTTPDNS 的工作原理并不是太清楚,所以写下这边文章帮助大家深入 web 请求过程:如何发起请求,HTTP 协议解析,DNS 域名解析。

# HTTP 发起一个请求过程

当我们在手机端请求一个 @"www.baidu.com" 的域名的时候

  • 1. 请求到达运营商的 DNS 服务器并由其把这个域名解析成对应的 IP 地址。

  • 2. 根据 IP 地址在互联网上找到对应的服务器,向这个服务器发起一个 get\post 请求。

  • 3. 由这个服务器找到对应的资源原路返回给访问的用户。

这里只是一个大概的流程实际每一步都有复杂的结构和逻辑例如:服务器可能有很多台,到底指定哪台服务器来处理请求,需要一个负载均衡设备来平均分配所有用户的请求。请求的数据是存储在分布式缓存中还是一个静态文件中,或是在数据库里。当数据返回浏览器时,浏览器解析数据发现还有一些静态资源(如 CSS、JS 或者图片)时又会发起另外的 HTTP 请求,而这些请求很可能会在 CDN 上,那么 CDN 服务器上又会处理这个用户的请求。

# HTTP 劫持

我们使用 HTTPDNS 的主要目的就是解决 HTTP 劫持问题。HTTP 的劫持分两种第一种是 DNS 劫持,第二种是内容劫持,后者是基于前者的基础上发展出来,是比较高级的劫持手段,目前无解,下面来分开讲解:

# 1:DNS 劫持
  • 劫持流程
    DNS 劫持又称域名劫持,是指在劫持的网络范围内拦截域名解析的请求,分析请求的域名,把审查范围以外的请求放行,否则返回假的 IP 地址或者什么都不做使请求失去响应,其效果就是对特定的网络不能访问或访问的是假网址。其实本质就是对 DNS 解析服务器做手脚,或者是使用伪造的 DNS 解析服务器可以通过下图来展示

    DNS劫持原理

    从图中可以看出红色的是劫持的流程,劫持后将你的请求转发到一个虚假的服务器。

  • 解决办法

    • DNS 的劫持过程是通过攻击运营商的解析服务器来达到目的。我们可以不用运营商的 DNS 解析而使用自己的解析服务器或者是提前在自己的 App 中将解析好的域名以 IP 的形式发出去就可以绕过运营商 DNS 解析,这样一来也避免了 DNS 劫持的问题。

    • HttpDNS 是使用 HTTP 协议向 DNS 服务器的 80 端口进行请求,代替传统的 DNS 协议向 DNS 服务器的 53 端口进行请求,绕开了运营商的 Local DNS,从而避免了使用运营商 Local DNS 造成的劫持和跨网问题

# 2:内容劫持
  • 劫持流程
    内容劫持网上很少有提到,这也是在做 httpDNS SDK 所遇到的一个问题,其实内容劫持一开始的出发点是好的,是运营商为了加快用户的访问速度同时减少自己的流量损耗而做的一个缓存机制,用户在像服务器请求数据的时候运营商会把用户的请求转移到这个缓存池中,如果缓存中有就直接返回,没有的话再去像服务器请求然后拦截并缓存服务端给用户的回调数据,这样一来可以极大的降低运营商像服务器请求的次数,也能加快用户的访问,所以出发点是好,但是一些非法的商家对缓存池内部做一些处理就是直接对返回的内容进行修改,这样一来我们就会接受到错误的数据

    内容劫持

    黄色线条就是比价危险的了,因为回调的数据很可能已经被篡改过。

  • 解决办法:
    现在暂时无法通过 HTTPdns 和其他手段解决,不过这样的劫持不是很多。

# DNS 解析过程

如果是 iOS 设备请直接跳到第三步骤

  • 1. 系统会检查浏览器缓存中有没有这个域名对应的解析过的 IP 地址,如果缓存中有,这个解析过程就将结束。浏览器缓存是受这个域名的失效时间和缓存的空间大小控制的。

  • 2. 如果用户的浏览器缓存中没有,浏览器会查找操作系统缓存中即为本地的 Host 文件。

  • 3. 如果本地 Host 文件中没有那么操作系统会把这个域名发送给这里设置的 LocalDNS,也就是本地区的域名服务器。这个 DNS 通常都提供给你本地互联网接入的一个 DNS 解析服务。这个专门的域名解析服务器性能都会很好,它们一般都会缓存域名解析结果,当然缓存时间是受域名的失效时间控制的,一般缓存空间不是影响域名失效的主要因素。大约 90% 的域名解析都到这里就已经完成了,所以 LDNS 主要承担了域名的解析工作。

  • 4. 如果 LDNS 仍然没有命中,就直接到 Root Server 域名服务器请求解析

  • 5. 根域名服务器返回给本地域名服务器一个所查询的域的主域名服务器(gTLD Server)地址。gTLD 是国际顶级域名服务器,如.com,.cn、.org 等。全球只有 13 台左右。

  • 6. 本地域名服务器(Local DNS Server)再向上一步返回的 gTLD 服务器发送请求。

  • 7. 接受请求的 gTLD 服务器查找并返回此域名对应的 Name Server 域名服务器的地址,这个 Name Server 通常就是你注册的域名服务器,例如你在某个域名服务提供商申请的域名,那么这个域名解析任务就由这个域名提供商的服务器来完成

  • 8.Name Server 域名服务器会查询存储的域名和 IP 的映射关系表,正常情况下都根据域名得到目标 IP 记录,连同一个 TTL 值返回给 DNS Server 域名服务器。

  • 9. 返回该域名对应的 IP 和 TTL 值,Local DNS Server 会缓存这个域名和 IP 的对应关系,缓存的时间由 TTL 值控制。

  • 10. 把解析的结果返回给用户,用户根据 TTL 值缓存在本地系统缓存中,域名解析过程结束。
    以上的流程可以简化为下图

DNS解析

绿色的为非 iOS 设备的操作流程

# CDN 工作机制

# CDN 简介

CDN,全称 Content Delivery Network,根本的作用是将网站的内容发布到最接近用户的网络 “边缘”,使用户可以就近取得所需的内容,提高用户访问网站的响应速度。他 - 有别于镜像,它比镜像更智能,可以这样做一个比喻:CDN = 镜像(Mirror) + 缓存(cache) + 整体负载均衡(GSLB),因而,CDN 可以明显提高 Internet 中信息流动的效率。目前 CDN 都以缓存网站中的静态数据为主,如 CSS、JS、图片和静态网页等数据。用户在从主站服务器请求到动态内容后再从 CDN 上下载这些静态数据,从而加速网页数据内容的下载速度,如淘宝有 90% 以上的数据都是由 CDN 来提供的。这里引用一个网上比较形象的例子:A 家的网速 100M 的,但他只用了 10M 的速度,B 家的网速是 10M 的,但是他需要 15M 的速度才行。怎么办呢。 C 是一家 CDN 服务商,在 A 家有个节点(就像 A 是一个赞助商一样)B 在 C 家买了 CDN 加速服务。当 B 的速度不够的时候,CDN 加速就会选择有节余的节点来帮 B,提高 B 的速度。这样 B 的速度就能达到或超过 15M ,A 没浪费,B 速度有了,C 赚了钱,皆大欢喜。 当 C 的节点在全国都有,非常多的时候。那么你用 C 家的 CDN 加速服务,你就会健步如飞了

# CDN 工作流程

一个用户访问某个静态文件(如 CSS),这个静态文件的域名假如是 www.baidu.com,而这个域名最终会被指向 CDN 全局中 CDN 负载均衡服务器,再由这个负载均衡服务器来最终分配是哪个地方的访问用户,返回给离这个访问用户最近的 CDN 节点。之后用户就直接去这个 CDN 节点访问这个静态文件了,如果这个节点中请求的文件不存在,就会再回到源站去获取这个文件,然后再返回给用户。

# 负载均衡

负载均衡就是对工作任务进行平衡、分摊到多个操作单元上执行,如图片服务器、应用服务器等,共同完成工作任务。它可以提高服务器响应速度及利用效率,避免软件或者硬件模块出现单点失效,解决网络拥塞问题,实现地理位置无关性,为用户提供较一致的访问质量。
CDN 整体的工作流程可以大概归为下图:

image.png

# 总结

以上就是 Http 请求的一些理解,如果有不对的地方及时与我来沟通。