「真®全栈之路 - DNS篇」故事从输入URL开始.....

前言

很久没写博客了,我原先的标题是 “从输入url到页面加载完成的XXX”?css

但想着,这是别人嚼烂不少次的内容,缺少挑战性,并且,页面操做过程当中能优化的地方实在太多了。html

那就干脆给本身挖个坑吧,好歹也在运维开发部待过一年的时间。前端

本文将尝试从先后端或运维多个角度,来述说整个站点从解析到操做过程当中的优化。vue

1. 流程回顾

1. URL的输入到浏览器解析的一系列事件

不少大公司面试喜欢问这样一道面试题,输入URL到看见页面发生了什么?,今天咱们来总结一下。 简单来讲,共有如下几个过程webpack

  1. 浏览器中输入网址
  2. 域名解析(DNS),找到IP服务器
  3. 发起TCP链接,HTTP三次握手,发送请求(Request
  4. 服务器响应HTTP(Response)
  5. 浏览器下载资源 html css js images
  6. 浏览器解析代码(若是服务器有gzip压缩,浏览器先解压)
  7. 浏览器渲染呈现给用户

2. 结合操做页面到关闭标签页

咱们在页面渲染完成以后执行某些操做:nginx

  • 按钮重复点击
  • 滚动操做
  • 条件查询检索

姑且将以上都归为 ==> 8. 界面操做web

还在步骤3:发起TCP链接 前插入:面试

  • 浏览器容许的并发请求优化

下面就让咱们从DNS解析开始...算法

2. DNS解析流程

Chrome浏览器为例:chrome

  1. Chrome浏览器 会首先搜索浏览器自身的DNS缓存。

    (缓存时间比较短,默认只有1分钟,且只能容纳1000条缓存)

注: chrome://net-internals/#dns来进行查看 Chrome自身的缓存)

  1. 若是浏览器自身的缓存里面没有找到对应的条目,那么Chrome会搜索操做系统自身的DNS缓存
  • Windows - 在Windows中查看DNS缓存条目的过程很是简单。只需打开命令提示符并输入如下命令:ipconfig /displaydns

  • Mac - 在Mac上查看DNS缓存条目的过程略有不一样。须要先打开控制台应用,从左侧边栏选择设备,而后输入:any:mdnsresponder进入搜索栏。接下来,打开命令行并输入如下命令:

    sudo log config --mode "private_data:on"
    sudo killall -INFO mDNSResponder
    复制代码

    而后,返回控制台应用程序并查看缓存的DNS记录列表。例如,下面的屏幕截图显示了wx.qlogo.cn的缓存CNAME记录。

  1. 若是在系统的DNS缓存也没有找到,那么尝试读取hosts文件。看看这里面有没有该域名对应的IP地址,若是有则解析成功。

    • 注:Windows位于C:\Windows\System32\drivers\etc,Mac则是/etc/hosts
    • 这种操做系统级别的域名解析一般会被不怀好意的人利用,经过修改你hosts文件里的内容把域名解析到他指定的ip地址上,形成所谓的域名劫持,因此将hosts文件设置成了只读模式,防止被恶意篡改。
  2. 若是在hosts文件中也没有找到对应的条目,浏览器就会发起一个DNS的系统调用,请求本地域名服务器localDNSLDNS)来解析这个域名。

  • 经过UDP协议向DNS的53端口发起请求,这个请求是递归的请求,也就是运营商的DNS服务器必 须得提供给咱们该域名的IP地址)
  • 第一次就会请求本地域名服务器(LDNS)来解析这个域名,这台服务通常在你城市的某个角落,距离不会很远,而且他的性能很好,通常都会缓存域名解析结果,大概80%的域名解析到这里都结束了。
  • 若是本地域名解析服务器也没有该域名的记录,则开始递归+迭代解析

直到这里,浏览器能作的全部DNS解析已完成,接下来的步骤就是和服务器相关了。不想看的能够忽略。

  1. 若是localDNS仍然没有命中,就直接到Root Server域名服务器请求解析。
  2. 根域名服务器返回给本地域名服务器一个所查询的主域名服务器(gTLD Server)地址。gTLD是国际顶级域名服务器,如.com.cn、.org等,全球只有13台左右。
  3. 本地域名服务器localDNS再向上一步返回的gTLD服务器发送请求。
  4. 接受请求的gTLD服务器查找并返回此域名对应的Name Server域名服务器的地址,这个Name Server一般就是用户注册的域名服务器,例如用户在某个域名服务提供商申请的域名,那么这个域名解析任务就由这个域名提供商的服务器来完成。
  5. Name Server域名服务器会查询存储的域名和IP的映射关系表,在正常状况下都根据域名获得目标IP地址,连同一个TTL值返回给DNS Server域名服务器。
  6. 返回该域名对应的IPTTL值,LDNS会缓存这个域名和IP的对应关系,缓存时间由TTL值控制。
  7. 把解析的结果返回给用户,用户根据TTL值缓存在本地系统缓存中,域名解析过程结束。

注:在实际的DNS解析过程当中,可能还不止这11步(第1步其实能够忽略不计。),如Name Server可能有不少级,或者有一个GTM来负载均衡控制,这都有可能会影响域名解析过程。

不想看文字能够看图:

3. DNS优化

首先须要明确一点:DNS缓存存在多级缓存,从离浏览器的距离排序的话,有如下几种:

  • 浏览器缓存
  • 系统缓存
  • 路由器缓存
  • IPS服务器缓存
  • 根域名服务器缓存
  • 顶级域名服务器缓存
  • 主域名服务器缓存。

若是每次都通过这么多步骤解析,是否太耗时间?如何减小该过程的步骤呢? 那就须要DNS优化了。而在前端优化中与DNS有关的有两点:

  • 减小DNS的请求次数
  • DNS预解析

DNS做为互联网的基础协议,其解析的速度彷佛很容易被网站优化人员忽视。如今大多数新浏览器已经针对DNS解析进行了优化,典型的一次DNS解析须要耗费20-120毫秒,减小DNS解析时间和次数是个很好的优化方式。这里就再也不述说,着重谈DNS预解析吧。

3.1 前端:DNS prefetch

DNS prefetch是让具备此属性的域名不须要用户点击连接就在后台解析,而域名解析和内容载入是串行的网络操做,因此这个方式能 减小用户的等待时间,提高用户体验 。

默认状况下浏览器会对页面中和当前域名(正在浏览网页的域名)不在同一个域的域名进行预获取,而且缓存结果,这就是隐式的 DNS Prefetch

若是想对页面中没有出现的域进行预获取,那么就要使用显示的 DNS Prefetch

其用法也很简单,只要在link标签上加上对应的属性:

/* 这是用来告知浏览器当前页面要作DNS预解析 */
<meta http-equiv="x-dns-prefetch-control" content="on" /> 
<link rel="dns-prefetch" href="//example.com">
复制代码
  • 若是你的页面中须要大量访问不一样域名的资源,能够利用这项技术加快资源的获取,从而得到更好的用户体验。
  • 须要注意的是,DNS预解析虽好,可是也不能滥用。若是对多页面重复DNS预解析,会增长DNS的查询次数。

目前不少大型站点也应用了这一优化,例如:

淘宝:

京东:

若是须要禁止隐式的 DNS Prefetch,可使用如下的标签:

<meta http-equiv="x-dns-prefetch-control" content="off">
复制代码

3.2 后端&运维:CDNHTTPDNS

实际上后端&运维能作的优化有三种:

  • CDN
  • HTTPDNS
  • DNS负载均衡

但稍微大型的Web站点,基本舍弃DNS负载均衡这一方案了,缺点太多。感兴趣的能够自行搜索了解。

1. CDNDNS循环

CDN, 全称是Content Delivery Network,即内容分发网络。其目的是经过在现有的Internet中增长一层新的CACHE(缓存)层,将网站的内容发布到最接近用户的网络”边缘“的节点,使用户能够就近取得所需的内容,提升用户访问网站的响应速度。

DNS循环: 当权威DNS发现一个域名映射多个IP时,会使用IP轮询的方式来将IP平均分配给多个DNS请求,从而达到负载均衡的效果。

为何须要CDN?

  • 因为DNS循环时平均分配,不能根据不一样服务器的负载状况优化分配,甚至若是有一台服务器宕机了,DNS不能及时了解到该状况把该服务器的IP分配出去,便会形成没法访问。
  • 所以,在权威 DNS 和 服务器之间加上一个CDN层就显得很必要了。
  • CDN 在具有调度分配服务器能力的基础上,可以同步服务器运行状况,而后根据该状况及时适当调整调度策略,从而使得负载均衡能力大大提升。

CDN好处:

  • 解决服务器端的“第一千米”问题。
  • 缓解甚至消除了不一样运营商之间互联的瓶颈形成的影响。
  • 减轻了各省的出口带宽压力。
  • 缓解了骨干网的压力。
  • 优化了网上热点内容的分布。

CDN的访问步骤:

(1)未部署CDN应用前:

网络请求路径:

  • 请求:本机网络(局域网)——》运营商网络——》应用服务器机房
  • 响应:应用服务器机房——》运营商网络——》本机网络(局域网)

在不考虑复杂网络的状况下,从请求到响应须要通过3个节点,6个步骤完成一次用户访问操做。

(2)部署CDN应用后:

网络路径:

  • 请求:本机网络(局域网)——》运营商网络
  • 响应:运营商网络——》本机网络(局域网)

在不考虑复杂网络的状况下,从请求到响应须要通过2个节点,2个步骤完成一次用户访问操做。

与不部署CDN服务相比,减小了1个节点,4个步骤的访问。极大的提升的系统的响应速度。

如下是结合具体网络运维的步骤:

step1:用户向localDNS发起请求查询输入域名对应的IP地址(如有缓存直接返回,不然去rootDNS查询);

step2:localDNS迭代向rootDNS查询,逐级迭代,rootDNS=>顶级DNS=>权限DNS;

step3:得到权限DNS后,localDNS向权限DNS发起域名解析请求;

step4:权限DNS一般会将域名CNAME
【若是有有CNAME则解析CNAME对应的CDN服务,不然的话默认为普通请求,直接返回解析到的IP】到另外一个域名,这个域名最终会被指向CDN网络中的智能DNS负载均衡系统;

step5:DNS负载均衡系统经过一些智能算法,将最合适的CDN节点IP地址返回给localDNS;

step6:localDNS将得到的IP地址返回给用户;

step7:用户获得节点的IP地址后,向该节点发起访问请求;

step8:CDN节点返回请求文件,若是该节点中请求的文件不存在,就会再回到源站获取这个文件,而后返回给用户。
复制代码

2. HTTPDNS:解决DNS挟持:

来自:也谈 HTTPS - HTTPDNS + HTTPS

在惯有的印象中,不少时候以为站点上完HTTPS协议就VANS。其实否则:

  • 尽管使用了 HTTPS 技术,部分邪恶的运营商,仍然使用DNS污染技术,让域名指向的他们本身服务器。
  • 而这些服务器并无部署SSL服务(就算部署了,也会触发 SSL 证书 Common name 不一致报警), 致使 443 端口直接被拒绝。

运营商为了赚广告钱、省网间结算是不择手段的。 他们广泛使用的劫持手段是经过 ISP提供的 DNS 伪造域名。 那有没有什么方法能够解决 DNS劫持呢?

业界有一套解决这类场景的方案,即 HTTPDNS

HTTPDNS使用HTTP协议进行域名解析,代替现有基于UDP的DNS协议,域名解析请求直接发送到HTTPDNS服务器,从而绕过运营商的Local DNS,可以避免Local DNS形成的域名劫持问题和调度不精准问题。

HTTPDNS 的原理很简单,将 DNS这种容易被劫持的协议,转为使用HTTP协议请求Domain <-> IP 映射。 得到正确IP以后,Client本身组装HTTP协议,从而避免ISP篡改数据。

腾讯做为首家提供HttpDNS服务的云服务商,有两篇相隔四年发布的文章,很是详细的揭示其中技术细节:

未完待续...

下一篇的内容讲围绕HTTP 优化的两个大方向::

  • 减小请求次数。
  • 减小单次请求所花费的时间。

与其对应的内容有:

  • 浏览器容许的并发请求优化,nginx配置/ 域名发散收敛。
  • 资源的压缩与合并,webpack/Gzip 相关。
  • 还有其它兴趣使然的内容...

做者掘金文章总集

须要转载到公众号的喊我加下白名单就好了。

公众号

相关文章
相关标签/搜索