zoukankan      html  css  js  c++  java
  • 从输入url到页面加载完成都发生了什么

    https://zhuanlan.zhihu.com/p/23155051 参考

    一个http请求的过程

    简要介绍一下一个http请求的网络传输过程:

    • DNS Lookup先获得URL对应的IP地址(浏览器查找域名对应的网址)
    • Socket Connect浏览器和服务器建立TCP连接(浏览器根据IP地址与服务器建立socket连接)
    • Send Request浏览器发送HTTP请求(浏览器与服务器通信,浏览器发送请求,服务器处理请求)
    • Content Download服务器发送响应(浏览器与服务器断开连接,四次挥手)

    接下来讲讲这里存在的性能问题:

    • 如果你对DNS的查询还有印象的话现在反思一下,DNS Lookup就是为了获取遗传IP地址要和无数个DNS服务器通信,要消耗多少时间呢?
    • TCP连接要三次握手,如果服务器很远的话这三次我说要花多少时间?(通常到这0.5秒就出去了)
    • 发送HTTP请求的时候你要知道一点就是我们的网络带宽上行和下行通常是不一样的,通畅上行带宽要小一些,一个的话还好,但是现在的网页通常都会后续请求很多资源,带宽小的时候上行拥塞怎么办?
    • 终于到了服务器响应了,不巧你访问的这个服务器很忙,好几万人都要这个资源,服务器的上行带宽也是有限的,怎么办?

    网络方面的主要优化手段,不外乎缓存,预取,压缩,并行。下面就分阶段介绍一下现有的优化手段。

    DNS优化

    对于DNS优化,缓存无意识最简单粗暴且效果明显的了。说到缓存就一定要提到缓存层级:

    • 浏览器搜索自己的 DNS 缓存(维护一张域名与 IP 地址的对应表);
    • 搜索操作系统中的 DNS 缓存(维护一张域名与 IP 地址的对应表);
    • 搜索操作系统的 hosts 文件( Windows 环境下,维护一张域名与 IP 地址的对应表);
    • 各个DNS服务器上的缓存(
      1. 操作系统将域名发送至 LDNS(本地区域名服务器,如果你在学校接入互联网,则 LDNS 服务器就在学校,如果通过电信接入互联网,则 LDNS 服务器就在你当地的电信那里。)LDNS 查询自己的 DNS 缓存(一般查找成功率在 80% 左右),查找成功则返回结果,失败则发起一个迭代 DNS 解析请求;

        1. LDNS 向 Root Name Server (根域名服务器,其虽然没有每个域名的的具体信息,但存储了负责每个域,如 com、net、org等的解析的顶级域名服务器的地址)发起请求,此处,Root Name Server 返回 com 域的顶级域名服务器的地址;

        2. LDNS 向 com 域的顶级域名服务器发起请求,返回 baidu.com 域名服务器地址;

        3. LDNS 向 baidu.com 域名服务器发起请求,得到 www.baidu.com 的 IP 地址;

      2. LDNS 将得到的 IP 地址返回给操作系统,同时自己也将 IP 地址缓存起来;

      3. 操作系统将 IP 地址返回给浏览器,同时自己也将 IP 地址缓存起来;

      4. 至此,浏览器已经得到了域名对应的 IP 地址。

    当然DNS缓存失效期通常比较短,很多情况下都需要再去查找,为了降低用户体验到的延迟(注意这里不是网络延时)预取是一个不错的方法。比如说你敲网址的时候还没有敲完,但是浏览器根据你的历史发现你很有可能去访问哪个网站就提前给你做dns预取了,比如你打了一个“w”的时候,chrome已经帮你去找weibo.com的ip地址了。chrome用户可以看一下chrome://predictors/ 你就知道了。

    此外浏览器还会记录你过去的历史,知道每个域名下通常还会有哪些其他链接建立起的网络拓扑结构,当你访问这个域名下的网站也就会预先对其他链接的域名进行DNS解析。

    TCP优化 建立连接--三次握手

     

    看到前面DNS优化这么复杂,到TCP这一步反倒简单了。因为刚才DNS已经把IP弄到手了,那我们就顺着刚才的步骤在建立连接就好了,所以字啊你瞧第一个字母的时候DNS解析完了就会去建立连接了。这时候你的网址可能还没敲完。当你刚访问一个网站的时候浏览器刷刷刷的帮你把别的服务器的TCP连接给你建好。

    知道了服务器的 IP 地址,下面便开始与服务器建立连接了。

    通俗地讲,通信连接的建立需要经历以下三个过程:

    1. 主机向服务器发送一个建立连接的请求(您好,我想认识您);

    2. 服务器接到请求后发送同意连接的信号(好的,很高兴认识您);

    3. 主机接到同意连接的信号后,再次向服务器发送了确认信号(我也很高兴认识您),自此,主机与服务器两者建立了连接。

    补充说明

    • TCP 协议:三次握手的过程采用 TCP 协议,其可以保证信息传输的可靠性,三次握手过程中,若一方收不到确认信号,协议会要求重新发送信号。

    HTTP传输优化

    网页请求与显示

    当服务器与主机建立了连接之后,下面主机便与服务器进行通信。网页请求是一个单向请求的过程,即是一个主机向服务器请求数据,服务器返回相应的数据的过程。

    1. 浏览器根据 URL 内容生成 HTTP 请求,请求中包含请求文件的位置、请求文件的方式等等;

    2. 服务器接到请求后,会根据 HTTP 请求中的内容来决定如何获取相应的 HTML 文件;

    3. 服务器将得到的 HTML 文件发送给浏览器;

    4. 在浏览器还没有完全接收 HTML 文件时便开始渲染、显示网页;

    5. 在执行 HTML 中代码时,根据需要,浏览器会继续请求图片、CSS、JavsScript等文件,过程同请求 HTML ;

     

    写到这里可能有人会想,既然已经把TCP连接建立好了,那我干脆预取更进一步,把所有的链接内容直接预取下来不就好了,这样我网址还没敲完网页就已经加载完成了。这个想法是好的,但现实却是残酷的。因为我们的带宽是有限的,DNS和TCP连接量级都比较轻,对网络带宽不会占据太多,但是HTTP传输就不一样了。如果你所有连接都去预取的话,你的带宽很快就被占满了,这样你正常的请求无法得到满足,性能反而会严重下降。

    缓存又出现了,提到缓存必须提层次结构。

    • PageCache这个事最快的了,直接在内存中缓存了现有网页的DOM结构和渲染结果,这就是你为什么在点前进后退时这么快。
    • HTTP Cache文件级别的Cache存在本地的文件系统上按照RFC2616实现。
    • 代理Cache如果是通过代理服务器上网的话,代理服务器通常也会按照缓存标准
    • CDN 一个地理上离你很近的内容服务器,比如说你在北京请求杭州淘宝的一个图片,结果在北京的一个CDN上有这个图片,那么就不用去杭州了。
    • DMOC(distributed memory object caching system)CDN主要存放的是静态数据,但是网页中通常有很多动态的数据需要查数据库,流量多了压力就会很大,通常服务器外围还会有一层内存缓存服务器,专门缓存这些数据库中的对象,据《淘宝技术这10年》称可以减少99.5%的数据库访问。
    • Server 其实真正落在服务器上的请求已经不多了。

    大家看到这里有没有想到能在什么地方再加一层缓存呢?其实可以在2和3之间加,也就是在路由器上加缓存。小米的路由器和搜狗合作的预取引擎其实就相当于是在路由器上加一层缓存款顺便智能预取一下。

    另一个HTTP常用的优化就是压缩了,网络传输时间 = 消息大小/网速 既然网速比较贵那么就压缩一下吧,大部分服务器都会对HTTP消息进行gzip压缩。可以在Http Header中看到,具体的就不细说了。

    未来协议SPDY

    上面都是传统做法,下面说一下未来技术。

    由于HTTP协议是上个世纪制定的协议了,已经不能很好的适应现在Web的发展,所以Google提出了SPDY协议目前是指定中的HTTP2.0标准的一个底版。SPDY主要有下面的特点:

    • 一个TCP连接上并行多个HTTP连接,减少连接的建立时间
    • 请求优先级(目前还没看到具体实现)
    • HTTP头部压缩,上文提到的HTTP压缩是对HTTP body的压缩,并没有对头部压缩。对于小的HTTP消息,头部的比重还是很大的,而现在的web中存在大量小消息。
    • Server push/hint 服务器主动推送对象(可以想象成服务器帮客户端预取)

    业界目前对SPDY是有赞有弹,博主也持谨慎的态度。主要在1和4上,4其实和之前提到的HTTP直接预取的矛盾点一样,万一推送的不需要又占据了带宽怎么办,hint到底该如何实现都有困难。第一条潜在的风险就是TCP连接中途断开,那么所有的连接就全部停掉了,PC互联网这种情况可能会少一些,但是移动互联网中TCP连接断开的情况还是比较常见的。不过作为一个未来的技术还是有必要关注一下。

  • 相关阅读:
    在cmd下执行py脚本报Traceback (most recent call last)报错解决
    git上传文件方法
    js获取元素方法和jquery语法操作元素方法
    获取config.ini文件配置的方法
    利用random随机函数实现抽奖方法
    selenium封装 运行脚本+生成测试报告+发送email
    基于KB的QA系统学习记录
    python学习记录
    manjaro + kde 使用过程中问题记录及解决方法
    linux学习记录
  • 原文地址:https://www.cnblogs.com/greatluoluo/p/5914387.html
Copyright © 2011-2022 走看看