Skip to content

web性能优化—内容请求优化 #10

@winnieBear

Description

@winnieBear

页面请求过程优化主要是减少获取页面资源的时间,主要通过几个方面:

  • 减少(或避免)请求数
  • 减少请求和响应的数据量
  • 缩短传输的路径和延迟
  • 增加传输带宽

当浏览器请求资源时,需要通过发送网络请求来获取资源,网络请求是比较耗费时间的,如果浏览器减少网络请求的次数,甚至不发送网络请求就直接拿到需要的资源,就可以大大减少资源加载的时间,浏览器的本地缓存机制可以满足这一点。

Local cache

浏览器发送请求时,会根据url查找本地缓存,看是否本地缓存中存在该url的内容,如果不存在,则向服务器请求该url的内容;如果本地存在缓存,则按照如下策略:
浏览器本地缓存机制

优化点:

  • 给静态资源设置适当的缓存时间 expire:xxx /cache-control:max-age=xxx,对更新不频繁的资源尽量利用本地缓存来减少网络请求的时间;
  • 尽量利用条件查询请求,对资源返回的http头设置Last-Modified/Etag,当内容过期时,进行条件查询请求,尽量利用本地缓存的资源;

关于本地缓存机制,进一步阅读

浏览器缓存机制

服务器与浏览器缓存协商控制机制的总结

充分利用本地存储LocalStorage

优化点

  • 高级浏览器一般都支持本地存储,可以把需要网络请求的资源存放再浏览器的LocalStorage,需要资源时从本地存储获取,首次加载时通过服务端内联的方式返回,减少资源的网络请求;

静态资源多域名部署

在PC端或者强网络环境下,因为浏览器在同一个域名下的并发请求数有限制(4-6个url),为了能够加快静态资源的请求,可以

  • 把静态资源分发到多个域名,让浏览器同时建立多个连接,并发进行多个静态资源的请求

注意:这种方法只适用于强网络环境,譬如移动端弱网络环境下,建立链接的耗费很多时间时,此方法不适用

DNS query

浏览器向服务器请求资源,是通过http协议进行通讯的,http协议是应用层协议,底层是TCP协议。因此浏览器发送请求时,需要和服务器先建立TCP连接,而建立TCP连接需要知道服务器的IP和PORT。而请求的url一般都是通过域名而不是IP提供给用户,因此浏览器和服务器建立连接之前,首先是获取服务器的IP。浏览器通过检查是否本地DNS缓存中是否有服务器host的ip,如果没有通过DNS查询来获取服务器的ip。

无线网络的现状:

  • 2G:一般只有10KB/S下行和1KB/S左右的上行速度,延迟基本 >= 400ms;
  • 3G网络:一般为下行100-200KB/S,上行10-100KB/S,延迟0-400ms,带宽方面基本逼近2M有线网络,但延迟较高,稳定性不够

DNS查询耗时:

  • 在相对较快速的有线网络环境下,平均值为几十毫秒左右;
  • 2G网络环境下,平均值在几百毫秒左右;
  • 在网络很差的移动环境下,平均值达到几秒左右

优化点:

<link rel="dns-prefetch" href="xxx.com" >
  • 在弱网络环境下减少页面中的资源的域名的个数,或者url中直接ip而不是域名

Connect To Server 和服务器建立连接

浏览器根据DNS查询得到ip+url中的端口跟服务器建立TCP连接。
因为用户和服务器之间的距离(不仅是物理距离,还有网络链路距离,以及跨运营商中转等)不同,建立连接的时间不同。

优化点:

  • 采用CDN,让用户与它最近的服务器建立连接

TCP 3 handshake TCP建立连接3次握手

TCP建立连接3次握手
TCP建立连接3次握手

因为HTTP协议是无连接的,每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。每一个请求都要建立TCP连接,都要进行3次握手,建连成本大;

优化点:

  • 减少建立连接的次数:merge CSS/js/image,合并资源,减少请求的资源的个数
  • 减少建立连接的次数:remove empty src/href/URL
  • 减少建立连接的次数:keep-alive, 若connection 模式为close,则服务器处理完一个请求之后会主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则当服务器处理完一个请求之后,该连接会保持一段时间,在该时间内可以继续接收请求;

Send HTTP Request 发送http请求

当浏览器发送http请求头时,会把相关一些信息发送,这些信息包括:UA,Localsetting,Referer,Cookie等,为了加快发送请求的效率,减少发送请求的时间,需要减少发送给服务器的数据量。

优化点:

  • 能用get,不用post请求url,post至少发送两个包
  • 减少发送的http header的大小:避免发送不需要的cookie,静态资源放到独立域名的服务器上
  • 减少发送的http header的大小:缩短url的长度,不同浏览器和服务器对url的长度也有限制
GET / HTTP/1.1
Host:www.taobao.com
User-Agent:Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.17) Gecko/20110420Firefox/3.6.17
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Encoding:gzip,deflate
Accept-Language:en-us,en;q=0.5
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.
Keep-Alive:115
Connection: keep-alive
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 12May 2011 11:02:36 GMT
Content-Type:text/html; charset=GB2312
Transfer-Encoding:chunked
Connection:keep-alive

进一步阅读

IE6、IE7、IE8 URL长度支持问题

HTTP中的URL长度限制

服务器的工作

服务器接到请求后,根据请求的url和数据等,经过一系列处理,最后返回一个大字符串就是网页的内容给浏览器。一般服务器处理一个动态请求的工作过程大概分几个部分:

  • 接收请求
  • 解析请求
  • 路由转发
  • 通过缓存、接口、数据库查询等途径获取数据
  • 返回文件/渲染模版
  • 输出内容

浏览器是边下载边解析,因此优化的方法是尽量减少浏览器的首包等待时间TTFB (TIME TO FIRST BYTE) ,

优化点:

  • 服务端优化,通过各级缓存(页面缓存/数据缓存/数据库缓存/模板缓存/)及服务器多IDC部署等方法,减少服务端的数据处理时间;
  • 采用bigPipe方案,flush buffer early 不必等所有数据都拿到再拼页面,有一点就输出,早点刷新缓冲区,减少浏览器的首包时间TTFB (TIME TO FIRST BYTE) ,让
    浏览器尽早的进行解析和渲染。

传统页面展现

传统页面展现

bigpipe页面展现

bigpipe页面展现

HTTP Response Header

再服务器端配置Last-Modified 和Etag,和设置缓存时间,让浏览器端尽量利用本地缓存;当缓存过期时,如果请求的资源没有修改,通过304响应,返回很少的响应头而不用返回全部的页面内容到浏览器。

  • 304 Not Modified 浏览器还是利用老的缓存数据
  • 200 Ok 新的内容

HTTP Response Body

返回的数据越少,传输的越快

优化点:

  • 按需加载和返回页面需要的资源,优先返回首屏依赖的资源,剩余的资源按需加载
  • 资源懒加载,例如图片,依赖的模块等,滚动加载剩余
  • 异步刷新,不需要返回全部内容,只返回变化的部分,ajax等
  • 返回的内容进行压缩HTML/CSS/js/img compres gzip

首屏优化

优化点:

  • 按需加载和返回首屏需要的资源,服务端一开始只返回首屏依赖的资源,剩余的资源按需加载
  • 首屏依赖的css和js除了类库,进行页面内联
  • 页面的小图标进行base64编码之后,页面内联
  • 首屏最好不要放js资源,js资源都放在首屏的下面进行加载

采用CDN服务

通过CDN服务,把资源部署到更接近用户的物理机房,

  • 减少浏览器建立连接的时间
  • 减少数据传输的链路长度
  • 同时CDN会对数据进行缓存
  • CDN会根据用户所在的运营商,在DNS解析时返回访问最快的机房IP

通过CDN服务,可以加快浏览器的获取数据的时间

采用SPDY/ HTTP/2

针对http1及http1.1存在的问题,产生了SPDY/ HTTP/2,尤其是HTTP/2 大大提高资源的请求和响应的时间。主要体现在:

优化点:

  • HTTP/2 采用二进制格式传输数据,而非 HTTP/1.x 的文本格式。二进制格式在协议的解析和优化扩展上带来更多的优势和可能。
  • HTTP/2 对消息头采用 HPACK 进行压缩传输,能够节省消息头占用的网络的流量。而 HTTP/1.x 每次请求,都会携带大量冗余头信息,浪费了很多带宽资源。头压缩能够很好的解决该问题。
  • 多路复用,直白的说就是所有的请求都是通过一个 TCP 连接并发完成。HTTP/1.x 虽然能利用一个连接完成多次请求,但是多个请求之间是有先后顺序的,后面发送的请求必须等待上一个请求返回才能发送响应。这会很容易导致后面的请求被阻塞,而 HTTP/2 做到了真正的并发请求。同时, 流还支持优先级和流量控制。
  • Server Push:服务端能够更快的把资源推送给客户端。例如服务端可以主动把 JS 和 CSS 文件推送给客户端,而不需要客户端解析 HTML 再发送这些请求。当客户端需要的时候,它已经在客户端了。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions