您当前的位置: 首页 >  http

凌云时刻

暂无认证

  • 2浏览

    0关注

    1437博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

我的 HTTP/1.1 好慢啊!

凌云时刻 发布时间:2021-02-23 11:00:00 ,浏览量:2

凌云时刻 · 技术

导读:问你一句:「你知道 HTTP/1.1 该如何优化吗?」本文从几个方面介绍了关于HTTP/1.1 协议的优化。

前言

问你一句:「你知道 HTTP/1.1 该如何优化吗?」

我想你第一时间想到的是,使用 KeepAlive 将 HTTP/1.1 从短连接改成长链接。

这个确实是一个优化的手段,它是从底层的传输层这一方向入手的,通过减少 TCP 连接建立和断开的次数,来减少了网络传输的延迟,从而提高 HTTP/1.1 协议的传输效率。

但其实还可以从其他方向来优化 HTTP/1.1 协议,比如有如下 3 种优化思路:

  • 尽量避免发送 HTTP 请求;

  • 在需要发送 HTTP 请求时,考虑如何减少请求次数;

  • 减少服务器的 HTTP 响应的数据大小;

下面,就针对这三种思路具体看看有哪些优化方法。

如何避免发送 HTTP 请求?

这个思路你看到是不是觉得很奇怪,不发送 HTTP 请求,那还客户端还怎么和服务器交互数据?小林你这不是耍流氓嘛?

冷静冷静,你说的没错,客户端当然要向服务器发送请求的。

但是,对于一些具有重复性的 HTTP 请求,比如每次请求得到的数据都一样的,我们可以把这对「请求-响应」的数据都缓存在本地,那么下次就直接读取本地的数据,不必在通过网络获取服务器的响应了,这样的话 HTTP/1.1 的性能肯定肉眼可见的提升。

所以,避免发送 HTTP 请求的方法就是通过缓存技术,HTTP 设计者早在之前就考虑到了这点,因此 HTTP 协议的头部有不少是针对缓存的字段。

那缓存是如何做到的呢?

客户端会把第一次请求以及响应的数据保存在本地磁盘上,其中将请求的 URL 作为 key,而响应作为 value,两者形成映射关系。

这样当后续发起相同的请求时,就可以先在本地磁盘上通过 key 查到对应的 value,也就是响应,如果找到了,就直接从本地读取该响应。毋庸置疑,读取本次磁盘的速度肯定比网络请求快得多,如下图:

聪明的你可能想到了,万一缓存的响应不是最新的,而客户端并不知情,那么该怎么办呢?

放心,这个问题 HTTP 设计者早已考虑到。

所以,服务器在发送 HTTP 响应时,会估算一个过期的时间,并把这个信息放到响应头部中,这样客户端在查看响应头部的信息时,一旦发现缓存的响应是过期的,则就会重新发送网络请求。HTTP 关于缓说明会的头部字段很多,这部分内容留在下次文章,这次暂时不具体说明。

如果客户端从第一次请求得到的响应头部中发现该响应过期了,客户端重新发送请求,假设服务器上的资源并没有变更,还是老样子,那么你觉得还要在服务器的响应带上这个资源吗?

很显然不带的话,可以提高 HTTP 协议的性能,那具体如何做到呢? 

只需要客户端在重新发送请求时,在请求的 Etag 头部带上第一次请求的响应头部中的摘要,这个摘要是唯一标识响应的资源,当服务器收到请求后,会将本地资源的摘要与请求中的摘要做个比较。

如果不同,那么说明客户端的缓存已经没有价值,服务器在响应中带上最新的资源。

如果相同,说明客户端的缓存还是可以继续使用的,那么服务器仅返回不含有包体的 304 Not Modified 响应,告诉客户端仍然有效,这样就可以减少响应资源在网络中传输的延时,如下图:

缓存真的是性能优化的一把万能钥匙,小到 CPU Cache、Page Cache、Redis Cache,大到 HTTP 协议的缓存。

如何减少 HTTP 请求次数?

减少 HTTP 请求次数自然也就提升了 HTTP 性能,可以从这 3 个方面入手:

  • 减少重定向请求次数;

  • 合并请求;

  • 延迟发送请求;

 减少重定向请求次数

我们先来看看什么是重定向请求?

服务器上的一个资源可能由于迁移、维护等原因从 url1 移至 url2 后,而客户端不知情,它还是继续请求 url1,这时服务器不能粗暴地返回错误,而是通过 302 响应码和 Location 头部,告诉客户端该资源已经迁移至 url2 了,于是客户端需要再发送 url2 请求以获得服务器的资源。

那么,如果重定向请求越多,那么客户端就要多次发起 HTTP 请求,每一次的 HTTP 请求都得经过网络,这无疑会越降低网络性能。

另外,服务端这一方往往不只有一台服务器,比如源服务器上一级是代理服务器,然后代理服务器才与客户端通信,这时客户端重定向就会导致客户端与代理服务器之间需要 2 次消息传递,如下图:

如果重定向的工作交由代理服务器完成,就能减少 HTTP 请求次数了,如下图:

而且当代理服务器知晓了重定向规则后,可以进一步减少消息传递次数,如下图:

除了 302 重定向响应码,还有其他一些重定向的响应码,你可以从下图看到:

其中,301 和 308 响应码是告诉客户端可以将重定向响应缓存到本地磁盘,之后客户端就自动用 url2 替代 url1 访问服务器的资源。

 合并请求 如果把多个访问小文件的请求合并成一个大的请求,虽然传输的总资源还是一样,但是减少请求,也就意味着减少了重复发送的 HTTP 头部。

另外由于 HTTP/1.1 是请求响应模型,如果第一个发送的请求,未收到对应的响应,那么后续的请求就不会发送,于是为了防止单个请求的阻塞,所以一般浏览器会同时发起 5-6 个请求,每一个请求都是不同的 TCP 连接,那么如果合并了请求,也就会减少 TCP 连接的数量,因而省去了 TCP 握手和慢启动过程耗费的时间。

接下来,具体看看合并请求的几种方式。

有的网页会含有很多小图片、小图标,有多少个小图片,客户端就要发起多少次请求。那么对于这些小图片,我们可以考虑使用 CSS Image Sprites 技术把它们合成一个大图片,这样浏览器就可以用一次请求获得一个大图片,然后再根据 CSS 数据把大图片切割成多张小图片。

这种方式就是通过将多个小图片合并成一个大图片来减少 HTTP 请求的次数,以减少 HTTP 请求的次数,从而减少网络的开销。

除了将小图片合并成大图片的方式,还有服务端使用 webpack 等打包工具将 js、css 等资源合并打包成大文件,也是能达到类似的效果。

另外,还可以将图片的二进制数据用 base64 编码后,以 URL 的形式潜入到 HTML 文件,跟随 HTML 文件一并发送.

            
关注
打赏
1663816507
查看更多评论
0.0745s