优化实战 第 01 期 - 从零开始建立性能优化知识体系

6,413 阅读8分钟

性能优化作为一个老生常谈的话题,可以在网上查到各种零碎的优化点,但对于新手来说,要对项目做完整的性能优化,却不知从何下手,其根本是缺乏对性能知识体系的认识

性能优化准则

  • 不宜过早优化

    在典型的互联网开发模式中,追求的是快速的迭代和试错,过早的优化往往会成为一种无用功

  • 不宜过度优化

    在项目运营的不同阶段,对系统的性能体验都会有不一样的要求,在能够满足使用预期的情况下,就没有必要花费时间精力去做优化

为什么做性能优化

  • 用户体验金字塔

    pyramid.png

    从 2018 年 Google I/O 大会上提供的数据发现,页面加载时长是影响用户体验的最大因素

  • 性能优化业务价值

    business.png

    页面加载时长不仅对用户体验有影响,还对业务数据有影响,当页面加载时长超过 5s 就会造成 90% 的用户流失

如何建立性能知识体系

既然性能体验优化是非常有价值的,那么如何能很好地串联起零碎的优化策略点并形成知识体系呢?我们从一道经典的面试题入手:

浏览器从输入地址到页面显示的过程中发生了什么?

1、浏览器对输入的地址进行 URL 解析

2、缓存解析,如 浏览器缓存、系统缓存、路由器缓存 等

3、通过 DNS 服务器将主机域名转换为 IP 地址

4、根据 IP 地址找到对应的服务器,发起 TCP 连接

5、建立 TCP 连接后,发起 HTTP 请求

6、服务器响应 HTTP 请求,浏览器获得 HTML 代码

7、浏览器解析 HTML 代码,再请求代码中的资源,如 CSS、JS、图片 等

8、浏览器解析渲染视图页面

9、服务器断开 TCP 连接

从整个页面渲染的链路中,可以提取关键词:URL解析、DNS解析、HTTP协议、HTTP缓存、TCP连接、服务器、响应体、渲染,根据这些关键词产出性能优化策略

渲染链路:URL解析

  • 地址解析和编码

    在浏览器地址栏中输入 URL 后,浏览器会解析输入的字符串,如果是 URL 就进行编码

    encodeURI() 和 decodeURI() 编码函数只把参数中的 空格 编码为 %20 ,汉字进行编码,其余特殊字符不会转换

    encodeURIComponent() 和 decodeURIComponent() 编码方法还会对 :/ 进行编码,所以不能用它来对网址进行编码,只合适对 URI 中的参数进行编码和解码

  • 安全协议HSTS

    HSTS(HTTP Strict TransportSecurity)是一种新的 Web 安全协议,其作用是强制客户端使用 HTTPS 协议与服务器创建连接,浏览器会自动将输入带有 http 的地址转写成 https 直接发送请求

渲染链路:DNS解析

渲染链路:HTTP1.1协议

  • 概述

    超文本传输协议,是互联网应用最为广泛的一种网络协议,它规范了浏览器和服务器的数据通信规则

    其灵活性,允许传输任意类型的数据对象,使用 Content-Type 加以标记即可

    Content-Type: application/x-www-form-urlencoded

    Object.keys(data).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`).join('&')
    

    form 表单的提交形式,提交的数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码

    Content-Type: multipart/form-data

    用于 form 表单上传文件,如果使用 new FormData() 的形式上传文件,则 Content-Type 字段不需要指定任何值,否则会造成数据传输不成功

    Content-Type: application/json

    JSON.stringify(data)
    

    告诉服务端消息主体是序列化后的 JSON 字符串,由于 JSON 规范的流行,这种方式使用的越来越多

  • 关联优化

    第 03 期 - 对异步任务并发量进行限流

渲染链路:HTTP2协议

  • 协议概述

    HTTP2 为 HTTP 协议提供了优化传输,它支持 HTTP1.1 的所有核心功能,但旨在以多种方式提高效率

  • 协议特性

    二进制传输

    将请求和响应的数据分割为更小的帧,并对它们采用二进制编码

    头部压缩

    头部 headers 是以纯文本传输且请求越多导致消耗在头部的流量就越多,尤其是每次都要传输 User-Agent 和 Cookie 这类不会频繁变动的内容,完全是一种浪费

    1、维护一份相同的静态字典 Static Table,包含常见的头部名称,以及特别常见的头部名称与值的组合

    2、维护一份相同的动态字典 Dynamic Table,可以动态地添加内容

    多路复用

    multiple.jpeg

    使用同一个连接传输所有的并行请求和响应,而交错的多个并行请求响应却不受阻塞影响

    服务器推送

    为单个客户端请求发送多个响应的能力

渲染链路:HTTP缓存

  • 缓存过程分析

    cache.png

    浏览器与服务器的通信方式为应答模式,即:浏览器发起HTTP请求 -> 服务器响应该请求

    由图可得:

    1、浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识

    2、浏览器每次拿到返回的请求结果都会将该结果和缓存标识存入浏览器缓存中

  • 强制缓存

    man-cache.png

    通过 Expires 和 Cache-Control 两个响应头字段来控制,如果同时存在,则后者优先级高于前者

    HTTP1.0标准 Expires: Mon, 06 Apr 2020 12:08:42 GMT 使用客户端时间和服务端返回的时间做对比,容易产生误差

    HTTP1.1标准 Cache-Control: max-age=3600 时间单位为秒,表示 1 小时

    符合强制缓存策略时,使用本地的缓存,不再向服务器发送请求,状态为 Status Code: 200 OK (from disk cache) 或 Status Code: 200 OK (from memeory cache)

  • 协商缓存

    neg-cache.png

    通过 Last-Modified 和 Etag 两个响应头字段来控制,如果同时存在,则后者优先级高于前者

    Last-Modified: Wed, 25 Mar 2020 08:33:53 GMT

    Etag: "5e7b16bd-a0ba" 资源文件的唯一标识,由服务器生成

    强制缓存失效后,浏览器携带缓存标识(If-Modified-Since / If-None-Match)向服务器发起请求,如果文件未修改过,可继续使用本地缓存,状态为 Status Code: 304 Not Modified

  • 清除缓存

    Cache-Control: no-cache, no-store, max-age=0, must-revalidate

    no-store 完全禁止缓存,用于某些变化非常频繁的数据

    no-cache 可以在客户端缓存资源,但每次都需要向服务端去做新鲜度校验,来决定从服务端获取新的资源(200)还是使用客户端缓存(304)

    在客户端发送 GET 请求时也可通过添加时间戳参数来禁用缓存

渲染链路:TCP连接

  • 建立TCP连接

    通过三次握手,客户端与服务器利用 SYN 报文段交换彼此的初始序列号,互相维持一个具有连接特性的状态

handshake.jpeg

  • 客户端发起HTTP请求 && 服务端响应请求

    process.jpeg

  • 关闭TCP连接

    通过四次挥手,确保数据传输的完整性,当被动方的数据全部传输给主动方后进行连接的关闭

wave.jpeg

渲染链路:CDN服务器

  • CDN作用

    完成 TCP 连接后,进入服务器响应。对于静态资源,可以接入 CDN 服务器来有效地 提升网站的稳定性,大大地缩减资源加载时间

  • CDN图示

    cdn.png

渲染链路:响应体压缩

  • GZIP压缩

    服务器返回响应体,其内容未经压缩的话,体积往往比较大,可以采用 GZIP 压缩来 大大的缩减文本类的资源体积,而对于图片资源则效果不大

  • GZIP原理

    gzip.png

    GZIP 采用的是 LZ77 和 哈夫曼 算法,都是针对文本类的压缩算法

  • GZIP压缩标识

    响应头字段中包含 Content-Encoding: gzip 表示已经开启压缩

渲染链路:解析渲染页面

  • 解析渲染流程

    1、根据 HTML 解析出 DOM 树

    2、根据 CSS 解析出 CSS 规则树

    3、结合 DOM 树和 CSS 规则树,生成渲染树

    4、根据渲染树计算 DOM 节点的信息(节点的大小、位置)

    5、根据计算好的信息绘制页面(CSS的颜色、背景、字体等)

  • 解析渲染图示

    render.jpeg

  • 一起交流学习

    加群交流请看 沸点