如何让你的Web网站更快的响应
我们所处的互联网世界里存在的应用,很大一部分功能都是由网页应用提供的。我们所使用的微信公众号信息流、小程序、营销页面都与之息息相关。
腾讯大数据的移动用户行为报告的数据表明,加载超过5秒就会有74%的用户离开页面。
因此提升网站的响应能极大的提高用户留存。
那么作为开发者,我们能在用户发出请求网站的流程中做点什么来提升用户体验和效率呢?
那我们就从用户请求一个URL的流程开始说起。
DNS寻址优化
当用户在浏览器中输入域名,会触发DNS解析流程,寻找目标域名的IP地址。
那么我们如何优化DNS解析呢?
那我们得先了解一下DNS的解析流程。
当用户输入一个域名,浏览器会先去本地查询这个域名是否在 (浏览器/系统/路由器/ISP互联网服务商) 存在着域名缓存,如果存在,就直接向IP地址发出请求。如果不存在,继续向根域名服务器查询,还不存在就会向顶级域名服务器、主域名服务器进行查询,查询到之后就将结果存储在本地。
找到域名了服务器IP,那用户的请求就可以到达服务器了。
可是对应的网站,一个域名对应一个IP的话,所有用户都会访问到同一台服务器,如果访问量巨大。服务器的下行带宽和性能资源都会被耗尽,这样给用户的反馈结果就是无法访问或者访问速度极慢。
如何解决单台服务器无法负载那么大的请求呢?
答案就是让DNS服务器告诉不同用户不同的IP地址,这样就可以让一个域名存在多个IP地址。并且DNS服务器甚至可以根据用户的实际地域分配一个可以提供最佳访问速度的IP地址,这也是CDN的基本原理。
HTTP/HTTPS 优化
用户终于得知了服务器IP,向服务器发起了资源请求。
早先的 http 1.0 版本,是一种无状态,短连接的应用层协议。
每次请求都会重新建立 tcp 连接,因此无法复用。并且存在队头阻塞,下一个连接建立之前,前一个响应必须到达。
为了解决这些问题 http 1.1 出现了。
支持长连接,一个 TCP 可以传输多个 HTTP 响应,并且支持了缓存处理。
但是优化的还不够。http 1.0 的解析基于文本,并且header重复信息会被多次发送。
http 2.0 使用了二进制格式(Binary Format)替换 http 1.x的文本解析。并且压缩了header减少重复的传输。
http 3.0 则基于 UDP 重发丢失的包,不需要重传整个连接。
作为开发者我们在这个流程中能做什么?
- 使用最新的 HTTP 协议。
- 合理的设置请求的强弱缓存。
- 减少http强制跳转https的几率。
响应资源优化
服务器终于接收到了用户的请求,返回所需要的资源数据。
如何让服务器的资源更快的展示给客户端呢。
一个方向就是想办法减少资源数据的传输,以更小的带宽代价传输资源。
一个方向是想办法加快资源数据的生成,更快的生成用户所请求的数据,对于耗时的操作,可以使用异步处理策略。
还有一个就是服务端主动 push 数据到客户端。
在实际的优化过程中这几个方向是并行的。
在实际的生产环境中,我们常常采用以下几种加速方法。
- 开启服务器 gzip 压缩。
- 对于网页应用,使用工具压缩 JavaScript、 CSS、HTML资源,优化打包策略减少不必要的资源构建,减少总体传输,使用 Server Push 提前推送资源,使用 websocket 建立长连接,减少轮询操作。前端SSR应用,缓存服务器渲染结果。使用恰当的缓存策略,减少不必要的请求。
- 对于数据接口,不返回无效的空值字段。对热点数据使用缓存策略。必要的时候使用 BFF 服务提供特制接口。如有耗时操作,使用消息队列进行异步处理,之后再进行结果通知。
本站优化策略
本站打算使用或者正在使用的优化策略。
- 开启 HSTS 浏览器自主强制 HTTPS ,避免服务端跳转消耗,解决在此过程中可能被劫持的问题。
- 静态资源开启 CDN 。
- 开启 prefetch 预加载功能 。
- 图片标签开启懒加载。
- nginx 开启 gzip 压缩。
- 开启代码 分割 和 压缩 功能,避免初次加载过大的 js 。
- js 文件开启 defer 或者 async 标签避免阻塞渲染。
- 缓存 SSR 渲染结果,不必每次都让服务器渲染页面。
- 使用 PWA 。
- 后端使用微服务,按模块提供接口,避免多余的接口数据返回。
- 部分热点数据后端使用 Redis 进行缓存。
- 异步加载数据,不要为了 SEO 失了智,需要 SEO 的模块才使用服务端渲染。
- 使用 HTTP2.0 , 等待 Nginx 支持 QUIC 。
- 使用消息队列,加快响应,方便后期扩展功能。
特别鸣谢
感谢以下用户对本文的支持与鼓励