美文网首页
# Web 性能优化基础认知

# Web 性能优化基础认知

作者: jecyu | 来源:发表于2020-12-07 23:53 被阅读0次

# 前言

web 性能优化是什么?相信不少开发过 web 应用的小伙伴可能在项目上或多或少做过一些性能优化,例如前端界面的渲染优化,通过代码实现根据用户的操作触发懒加载某些资源,从而提升初始页面的渲染速度,比如常见的专题树。

本文通过《从浏览器地址栏输入 URL 到页面渲染出来的过程》涉及到的性能知识做一个概述,来提升读者对 web 性能优化的基础认知,类似给读者提供一个框架,之后读者能够就可以在这个框架上引入各种性能元素。

目标读者

  • who:对 web 应用做过一些性能优化但没有建立对 web 性能优化的全局了解。
  • when:当他读完本文后,能够对 web 网站性能优化有基础的认知,从大体上能够知道什么是性能优化、为什么要做性能优化、怎么做性能优化。

文章大纲

  • 访问页面
  • 文档加载完成
  • 导致页面响应缓慢的原因
  • 如何优化

# 访问页面

页面是通过网络传输的,在说网络传输之前,我们先简单回顾下因特网(internet)。什么是因特网,举个小例子,程序员金木同学,今天工作时运行一个比较大的项目导致电脑卡死了,熟练的操作,打开任务管理程序,杀死进程。想了想,从大学到现在这个电脑已经跟随他五年了。今天刚好发工资,攒够钱的小 A 于是打开了某知名品牌电脑网站,从看中电脑到下单不用 5 分钟搞掂,第二天电脑就到了手上了。这个拿货的速度得益于今天强大的快递网络,大大小小的网点、仓库,密密麻麻遍布在整个城市、国家,连接着全世界,它就像一个巨大的蜘蛛网一样。

(图片来源:Echart 地图 3D 路径

为了让保证快递的速度,装有电脑的包裹会从离金木同学最近的仓库发出。

同样的,因特网也是由许许多多的部件构建一个强大的信息网络,它是连接全世界的计算机设备的网络。

图上的路径则是显示:金木同学利用他的电脑作为客户机去访问该品牌电脑商的服务器,请求下载以访问它的官方网站。

# 回顾网络传输

在复杂交错的网络中,快递包裹想要顺利发送到金木同学手上,是需要约定好接收方与发送方以及途径一些中间方的规定。

对于网络传输来说,则是网络分层模型以及它们依赖的网络协议。就拿浏览器访问 Web 网站来说,它的应用层协议是 HTTP 协议,HTTP 定义了 Web 客户端向服务器请求 Web 页面的方式,它们之间发送的包(packet)会沿着图中的路线进行传输。

如果我们在 Linux 下使用命令$ traceroute targetIp 或者在 Windows 下使用批处理 > tracert targetIp,都可以定位用户与目标计算机之间经过的所有路由器,不言而喻,用户和服务器之间距离越远,经过的路由器越多,延迟也就越高。使用 CDN 的目的之一便是解决这个问题。

例如,假如我要访问淘宝的网站,可以先通过 ping 获取具体的 ip 地址,再使用上面的命令进行路由器查询。

huasenyumideMacBook-Pro:Web-Performance-Optimization linjy$ ping www.taobao.comPING www.taobao.com.danuoyi.tbcache.com (116.253.26.214): 56 data bytes64 bytes from 116.253.26.214: icmp_seq=0 ttl=52 time=2.875 ms64 bytes from 116.253.26.214: icmp_seq=1 ttl=52 time=3.874 ms64 bytes from 116.253.26.214: icmp_seq=2 ttl=52 time=2.211 ms64 bytes from 116.253.26.214: icmp_seq=3 ttl=52 time=2.190 ms64 bytes from 116.253.26.214: icmp_seq=4 ttl=52 time=2.224 ms64 bytes from 116.253.26.214: icmp_seq=5 ttl=52 time=3.409 ms^C6 packets transmitted, 6 packets received, 0.0% packet lossround-trip min/avg/max/stddev = 2.190/2.797/3.874/0.656 ms 

可以看到当前是这个 ip (116.253.26.214) 接受了我们的请求,因为淘宝做了集群处理,因此每次 ping 的时候,服务器的 ip 是不同的。例如,在 mac 中可以用 Host 命令(更多命令可以看 How to determine the IP address of a computer or website ):

huasenyumideMacBook-Pro:Web-Performance-Optimization linjy$ host www.taobao.comwww.taobao.com is an alias for www.taobao.com.danuoyi.tbcache.com.www.taobao.com.danuoyi.tbcache.com has address 113.16.206.233www.taobao.com.danuoyi.tbcache.com has address 116.253.26.214www.taobao.com.danuoyi.tbcache.com has address 116.253.26.213www.taobao.com.danuoyi.tbcache.com has IPv6 address 240e:950:1:0:3::3f2www.taobao.com.danuoyi.tbcache.com has IPv6 address 240e:49:5b00:100:2::e3

这是因为淘宝了集群的处理。现在我们可以挑选 113.16.206.233 ip 地址,进行 traceroute 命令处理。其实 traceroute 是可以直接使用 host 作为参数的,上面通过 ip 只不过是为了展示下集群也是一种提升 Web 性能优化的途径。

huasenyumideMacBook-Pro:~ linjy$ traceroute www.taobao.comtraceroute: Warning: www.taobao.com has multiple addresses; using 113.16.206.233traceroute to www.taobao.com.danuoyi.tbcache.com (113.16.206.233), 64 hops max, 52 byte packets 1  10.0.2.254 (10.0.2.254)  2.367 ms  2.540 ms  3.050 ms 2  219.159.71.1 (219.159.71.1)  3.423 ms  4.325 ms  4.752 ms...

其中 64 hops max 代表最多经过的路由节点,52 byte packets 为数据包的大小。更多请看traceroute 使用与实现原理分析

# 从浏览器地址栏输入 URL,页面构建

现在我们看看,金木同学在电脑的浏览器地址输入:http(s)://www.aaa.bbb.com/product/xxx.html 后到整个界面出现可操作的过程,经历了哪些操作呢?

一个简单的图是这样的:

再扩展开来是这样的:

根据上图,为了让浏览器与服务器成功进行通信进行 HTTP 请求响应,要经历以下步骤:

# 1. 首先浏览器解析 URL

浏览器要成功发起一个 HTTP 应用请求,先要进行 TCP 的连接,而要进行 TCP 的连接,则需要知道目标服务器的 IP 地址,而现在浏览器只知道用户输入的 URL 地址:

因此,浏览器要先解析输入的 URL 地址:

A. http(s): + // + Web 服务器名 + (/ + 目录名 + / ..... + 文件名)

  • URL 开头表示访问数据源的机制,也就是协议
  • “//“ 后面的字符串表示服务器的名称
  • () 里面的则表示数据源(文件)的路径名

B. 以上文中提到的 URL 为例,

https://www.apple.com.cn/macbook-pro-13/index.html

C. 按照 A 中的元素对 B 解析的结果是:

https: + // + www.apple.com.cn + / + macbook-pro-13 + / + index.html

# 2. 向 DNS 服务器查询 Web 服务器的 IP 地址

通过浏览器解析后,已经知道 www.apple.com.cn 是目标服务器的域名,之后就根据域名查询获得了服务器的 ip 地址。

# 3. TCP 连接、HTTP 请求抛出

既然金木的电脑获得 ip 地址后,它能够生成 TCP 套接字,与目标服务器进行三次握手成功连接后,便可向 www.apple.com.cn 发送 HTTP GET 请求了。

# 4. 服务端处理请求,HTTP 响应返回(webserver)

www.apple.com.cn 的服务器上读取到 TCP 的套接字里面的请求报文后,会生成一个 HTTP 响应报文,并且将 index.html web 文档放入 HTTP 响应体中,并将报文发送给 TCP 套接字。

# 5. 浏览器拿到响应数据,解析响应内容,把解析的结果展示给用户

包含 index.html 的报文通过多个路由转发后,最终来到了金木同学的 Web 浏览器中,浏览器从 TCP 套接字读取 HTTP 响应报文,如果这个 web 文档是被压缩的(如gzip),还得解压下,最后对该 html 文档进行渲染显示。

多数 web 页面含有一个 HTML 基本文件,除此之外还有几个引用的对象(jsimage 等)。因此在解析 html 的过程中,web 会依次去请求这些引用的对象(重复上面的过程),最后才完成了首次文档加载(俗称的首屏渲染),最终显示了一个完整的网页给用户金木同学。

# 实战分析

由于 apple 官网使用的 https 协议,笔者测试 wireshark 无法正常进行抓包。因此,为了更好地说明以上步骤发生的事情,这里使用了一个线上的例子 http://gaia.cs.umass.edu/wireshark-labs/HTTP-wireshark-file4.html, 这个地址响应的是一个具有嵌入对象的 HTML 文档。

  1. 启动浏览器
  2. 启动 Wireshark 抓包工具
  3. 输入地址 http://gaia.cs.umass.edu/wireshark-labs/HTTP-wireshark-file4.html
  4. 获得响应的页面如下:

现在我们再来看看 Wireshark 抓包工具分析图:

按时间顺序排序:可以看到基本的顺序为:DNS -> TCP -> HTTP。

上图是输入 HTTP 的请求与过滤图,下半部分则是 某条 HTTP 请求响应 的详情图。

# 文档加载完成,产生用户交互

在首页加载完毕后,金木同学开始操作网页,间接地让 web 程序产生四个方面的行为:

  • 用户输入,web 程序响应输出
  • 动画运行
  • 空闲时间
  • 资源加载

# 导致页面响应缓慢的原因

到这里,我们已经了解从金木同学从浏览器地址栏输入 URL,到整个页面被浏览器加载完成,以及之后可能产生的交互的历程。而导致页面响应缓慢的原因,就是产生在每一个节点中,就好像双 11 快递一样,我们的快递可能被卡住某一个节点上了。

# 性能监测分析

这个是利用 webpagetest 工具对淘宝网站进行分析图,可以看到各个资源请求的响应时间。

导致网络页面响应缓慢可能有以下情况:

  • 网络层面
    • DNS 寻址
    • TCP 连接
    • 服务器的响应速度
    • ...
  • 浏览器的渲染层面
    • 动画
    • 事件运行
    • ...

除了使用 webpageTest 外,我们使用最多的就是 chrome devTool 分析,具体使用可以查看参考资料工具篇。

# 什么时候需要做性能优化

一个应用的发展周期中:稳定 > 安全 > 性能,先稳定,才有人用,有人用了,就需要解决安全的问题,人数多了,网络响应慢,就要解决性能的问题。但是并不代表性能方面不需要考虑。在快速制作的 web 应用原型时,稳定优先。在版本迭代稳定后,安全和性能也要跟着考虑了。

不要过早优化不能一概而论,比如某些功能在使用代码实现前就应该考虑性能上的问题,避免后续的更改成本过高。

对于是否需要优化,我们可以参考下延迟与用户反应的参考表格:

延迟时间 用户反应 0-16ms 用户可以感知每秒渲染 60 帧的平滑动画转场。也就是每帧 16 毫秒留给应用大约 10 毫秒的时间来生成一帧。 0-100ms 在此时间窗口内响应用户操作,他们会觉得可以立即获得结果。时间再长,操作与反应的连接就会中断。 100-300ms 轻微可觉察的延迟。 300-1000ms 延迟感觉像是任务自然和持续发展的一部分(用户觉得这是正常流,但不会觉得快。) 1000+ms 用户的注意力将离开他们正在执行的任务。 10000+ms (>10s) 用户感到失望,可能会放弃任务;之后他们或许不会再回来。

# 如何优化

决定要做性能优化了,那应该如何优化呢?网络应用本质上是对数据的操作、显示,因此可以从下面的链路:

提升数据生成的效率——服务器部署策略——缓存技术提升效率——客户端渲染效率,例如下面的 webgis 应用:

我们需要从一个 web 应用的请求与响应的过程下手,即是网络层面与浏览器的渲染响应层面。

# 关键指标

我们可以通过一些关键指标来做优化:

  • 响应:在 100ms 内响应用户输入
    • 50 ms 内处理用户输入事件,确保 100 ms 内反馈用户可视化的响应
    • 对于开销大的任务可分隔任务处理,或者放到 worker
  • 动画:动画或滚动时,10ms 产生一帧
    • 动画类型:滚动、视觉动画、拖拽(流程节点、地图缩放和平移)
  • 空闲时间:主线程空闲时间最大化
    • 利用空闲事件完成推迟的工作
  • 加载:在 1000 ms 内呈现交互内容
    • 优化关键渲染路径
    • 渐进式渲染等
    • 网络速度、硬件 CPU、解析器(JS 运行引擎)
  • 以用户为中心

# 优化策略

基于上面的分析,优化策略大体可以这样:

  • 多端协作
    • 内核(比如浏览器)
    • 中间件(web 服务器、数据库服务器等等)
    • 外壳(比如应用外壳 ,PWA)
    • 前端(资源压缩、代码执行、首评优化内容优化)
    • 后端(负载均衡、架构优化、并行优化、异步优化、算法优化、缓存优化)
  • 四种途径
    • 延迟(执行、加载)
    • 按需(加载,例如从一个组件库加载一个组件)
    • 缓存(资源)
    • 预备(提前执行、加载,例如 Chrome 当渲染引擎收到字节流之后,会开启一个预解析线程,用来分析 HTML 文件中包含的 JavaScript、CSS 等相关文件,解析到相关文件之后,预解析线程会提前下载这些文件。prefetch 和 preload )
  • 基本路线
    • 缓存
    • 发送请求
    • 服务端响应
    • 页面解析与处理
    • 静态资源优化
    • 运行时性能
    • 加载
  • 两个层面
    • 网络层面
    • 浏览器渲染层面

虽然这样分开很多,实际操作起来它们可能是相互混合的,基本离不开上面说的优化策略。我们直接从两个层面入手:网络层面浏览器渲染层面

# 网络层面

在网络层面上,比如 DNS 解析花时间,能不能尽量减少解析次数或者把解析前置。能——浏览器 DNS 缓存DNS prefetch。TCP 每次的三次握手都急死人,有没有解决方案?有——长连接预连接、接入 SPDY 协议。另外,服务端可以做负载均衡、分布式集群,把请求的资源分布到多个服务器上。

上面的过程的优化往往需要前后端协作完成,前端单方面可以做的努力有限,那么 HTTP 请求呢?前端可以减少请求次数和减小体积方面。再者,服务器越远,一次请求就越慢,那部署时就把静态资源放在离我们更近的 CDN 上是不是就能更快一些。

# 渲染层面

在渲染层面上,可以考虑以下途径的优化:

  • 资源加载优化
  • 服务端渲染
  • 浏览器缓存机制的利用
  • DOM 树的构建
  • 网页排版和渲染过程
  • 回流与重绘
  • DOM 操作的合理规避

# 一个例子

最后我们再看看一个简单的项目越来复杂时,我们可能需要做哪些东西提升性能。

没看过文章和视频,可以先看看。下面是我从例子中摘取的性能优化相关的东西,实际上一个真正的应用要做的优化远远不止这些。

  • webpack 进行资源打包和构建优化。
  • maven 来构建和打包后端项目
  • 原本我们的项目使用 mysql 来持久化存储我们的留言数据,使用 mybatis 和 springdatajpa 来操作数据库,随着访问人数的增多,数据库扛不住,我们使用 redis 来缓存一下数据,并且我们的数据库要实现分库分表和读写分离。
  • 在网页中,为了体验的友好和减轻服务器压力,我们可以使用 vuex 和 localstorage 来将数据缓存在浏览器中
  • 为了防止有些用户乱点和爬虫脚本的操作,前端开发需要防抖节流来控制用户的操作,后端可以通过 redis 来限制用户操作频率,当然我们也通过 nginx 来限制用户 IP 访问
  • 我们的用户越来越多,留言越来越多,单机完全不能支撑这个服务了,老板说分布式可以解决这个问题,于是我们后端开始考虑是使用 springcloud还是dubbo zookeeper的方案,当然我们也会用nginx的负载均衡
  • JWT 调优

虽然项目越来越复杂,但是只要我们掌握了套路,总能找到解决的方案。

# 总结

本文以一个简单的例子描述了从浏览器输入 URL 到 web 页面展示的流程,以及如何做性能优化,浅谈了 web 性能优化的基础认知。要想做好 web 性能优化,不仅要理解计算机网络的通信机制,也要清楚浏览器的缓存、渲染原理、运行机制。从全局上了解,理清每个角度的交互关系,可以让我们知道从哪里下手,逐一攻破,并且一开始就从用户使用频率最高的地方入手。

# 参考资料

相关文章

  • # Web 性能优化基础认知

    # 前言 web 性能优化是什么?相信不少开发过 web 应用的小伙伴可能在项目上或多或少做过一些性能优化,例如前...

  • WEB性能优化

    WEB性能优化

  • Awesome Extra

    性能优化 性能优化模式 常见性能优化策略的总结 Spark 性能优化指南——基础篇 Spark 性能优化指南——高...

  • 使用Webpack4优化Web性能

    利用 Webpack 来优化 Web 性能属于加载性能优化 的一部分: ☛ Web Performance Opt...

  • Web性能优化基础-1

    前因 本来这篇想写一下CSS选择器的性能优化,但是写着写着就发现相关的知识点非常的多,需要查阅很多资料才能学透彻然...

  • 前端性能优化

    js性能小贴士——优化循环 前端网页与js性能优化 我总结的js性能优化的小知识 提高 web 应用性能之 Jav...

  • 前端性能 优化 大全

    js性能小贴士——优化循环 前端网页与js性能优化 我总结的js性能优化的小知识 提高 web 应用性能之 Jav...

  • spark性能调优

    [Spark性能优化指南——基础篇][Spark性能优化指南——高级篇]

  • Web 性能优化:21种优化CSS和加快网站速度的方法

    这是 Web 性能优化的第 4 篇,上一篇在下面看点击查看: Web 性能优化:使用 Webpack 分离数据的正...

  • Web前端知识分享:3个优化Web性能的小技巧

    Web性能优化重不重要?相信每一个从事Web前端开发的人都会回答重要,毕竟Web性能优化好的网站可以给用户带来更好...

网友评论

      本文标题:# Web 性能优化基础认知

      本文链接:https://www.haomeiwen.com/subject/gsgxgktx.html