认识 HTTP/1.1 协议

概要

HTTP 是一种用于在网络上传输超文本和其他资源的应用层协议,可以实现客户端和服务器通信。这句话可以拆成三个部分理解,即超文本、传输和协议。所以可以这么理解,HTTP 协议是计算机中用来在客户端和服务器之间传输文字、图片、音视频等超文本数据的约定和规范。

HTTP 协议有多个版本,发展到至今有 HTTP1、HTTPS、HTTP2、HTTP3 共 4 个版本。其中,HTTP1 是 HTTP 协议的基础。

HTTP1 版本又分为 HTTP/1.0 和 HTTP/1.1。其中,HTTP/1.0 是第一个 HTTP 协议版本。HTTP/1.1 是基于 HTTP/1.0 的基础上进行优化和拓展的。

特性

HTTP/1.1 协议之所以被大量的平台广泛使用,用于实现客户端和服务器的通信。和它的特性息息相关。下面我们来分析下 HTTP/1.1 有哪些方面的特性。

简单和易拓展

报文格式简单和易拓展。HTTP/1.1 的报文格式主要有首部和主体,如下图请求报文所示:

其中,首部主要是在请求和响应过程中传递键值对信息,这些信息用于指定请求的属性、控制缓存、身份验证等。是由建键值对组成,其中键是首部字段的名称,值是与该字段相关联的数据。每个键值对用冒号(:)分隔。

下面是常见的一些首部字段的功能和使用方式

Host 字段用于指定访问的服务器域名,如下所示:

makefile 复制代码
Host: www.A.com

Content-Length 字段用于指定本次响应的数据长度,如下所示:

yaml 复制代码
Content-Length: 1000

Connection 字段用于表示客户端要求服务器使用长连接机制,以便握手后的请求可以复用。在 HTTP/1.0 默认不支持长连接,因此请求结束后就断开连接了。HTTP/1.1 默认是支持长连接的。使用如下所示:

makefile 复制代码
Connection: Keep-Alive

Content-Type 字段用于服务器告诉客户端响应的数据格式,一般客户端会先使用 Accept 字段表明自己可以接受的数据格式,如下所示:

ruby 复制代码
Accept:*/*
Content-Type:text/html;charset=utf-8

Content-Encoding 字段用于说明数据的压缩方式,表示服务器返回的数据用什么格式压缩,客户端可以在 Accept-Encoding 中表名能接收的压缩格式,如下所示:

makefile 复制代码
Accept-Encoding:gzip,deflate
Content-Encoding:gzip

持久连接

HTTP/1.1 后默认开启长连接。HTTP/1.0 是短连接,默认情况下,每个 HTTP 请求都会在单独的 TCP 连接上进行。这意味着每个请求都需要建立一个新的连接,进行请求和响应后再关闭连接。这种模式导致了额外的延迟和资源开销。在 HTTP/1.1 后默认开启了持久连接,允许在一个 TCP 连接上发送多个请求和响应,而无需再为每个请求建立连接和关闭连接,减少了连接建立和关闭的开销,提高了性能。如下图所示:

为了兼容 HTTP/1.0,可以通过首部字段 Connection: Keep-Alive 来开启持久连接。

管道化

HTTP/1.1 支持管道化。管道化是允许客户端在单个连接上连续发送多个请求,而无需等待每个请求的响应。这样可以将多个 HTTP 请求打包到一个 TCP 报文中,减少了请求的等待时间和网络延迟,提升了性能和效率。如下图所示:

遗憾的是,iOS 的 URLSession 目前并不支持这项技术。

缓存

HTTP/1.1 支持缓存。缓存是一种在客户端和服务器之间存储和复用资源的机制,可以提高性能和减少网络流量。它允许客户端在后续请求中避免重新请求相同资源,而是直接从本地缓存中获取资源副本。HTTP/1.1 提供了两种缓存方式,强制缓存和协商缓存。

强制缓存是通过设置响应首部字段的缓存控制字段,让客户端在一定时间内强制使用本地缓存机制。即使服务器已经有更新,客户端也不会发送请求到服务器进行验证,而是直接从本地缓存中获取资源。

强制缓存主要通过两类字段进行控制,分别是 Cache-Control 和 Expires。其中:

  • Cache-Control 字段不仅可以用来指定资源的有效期,还可以指定资源的缓存策略。常见指定包含:
    • public:允许任何中间代理服务器和客户端缓存该资源;
    • private:仅允许客户端缓存该资源,不允许中间代理服务器缓存;
    • max-age:指定资源的有效期,如 Cache-Control:max-age=3600 指示资源在接下来的 3600 秒内都可以直接从缓存中获取。
  • Expires 字段用于指定资源的过期时间。如 Expires: Wed, 22 Sep 2023 12:00:00 GMT 表示资源在该时间点之后过期。
  • 若服务器的响应首部同时返回 Cache-Control 和 Expires 字段的话,Cache-Control 的优先级比 Expires 高。

协商缓存是一种在客户端和服务器之间进行资源验证的机制,用于确定客户端是否可以继续使用缓存的副本,而无需获取完整的资源内容。它通过比较资源的相关标识(如 Last-Modified 和 ETag)来确定资源是否已经发生了变化。如果资源未发生变化,服务器可以返回一个轻量级的响应,表示资源未修改,客户端可以继续使用缓存的副本。

协商缓存也是通过两类字段进行控制,分别是 Last-Modified 和 ETag。其中:

  • Last-Modified 字段用于指示请求资源最后的修改时间。当客户端发起请求时,会在 If-Modified-Since 中写入上次资源的 Last-Modified。服务器会比较两者的时间,如果资源最后修改的时间较早,则服务器返回 304 表示资源未发生变化,可以使用缓存副本。
  • ETag 字段用于指定资源的唯一性。当客户端发起请求时,它会在请求头中包含 If-None-Match 字段,该字段的值为先前获取资源时服务器返回的 ETag 值。服务器会将这两个值进行比较,如果资源的 ETag 值匹配,则服务器返回 304 Not Modified 响应,表示资源未发生变化,可以使用缓存副本。
  • ETag 的优先级比 Last-Modified 高。因为不修改文件时间也会改变,而且有些文件是在毫秒级别改变的,Last-Modified 只能精确秒。

请求方法

HTTP/1.1 提供了丰富的请求方法。这些方法主要是用来约束客户端和服务器之间进行数据传递的行为和操作。常见的方法有:

  • GET:从服务器获取资源;
  • POST:向服务器提交数据,常用于提交表单数据、上传文件等操作;
  • PUT:将数据发送到服务器,常用于创建或替代资源;
  • DELETE:从服务器删除指定的资源;
  • PATCH:用于对资源进行部分更新,只更新请求中指定的字段或属性;
  • HEAD:与 GET 方法类似,但只获取响应头信息,不返回响应体,常用于检查资源是否存在或获取资源的元数据;
  • OPTIONS:获取服务器支持的请求方法列表、服务器配置信息等;
  • TRACE:用于回显服务器收到的请求,用于测试或诊断;
  • CONNECT:将请求连接转换为透明的 TCP/IP 通道,通常用于进行加密隧道的建立,例如 HTTPS 。

状态码

HTTP 状态码是在 HTTP 请求中用于表示服务器对请求的处理结果的表示,是三位数字代码。以下是一些常见的 HTTP 状态码及其含义:

类型 分类 作用
1xx 信息性状态码
100 Continue 服务器已经收到请求的初始部分,客户端继续发送剩余部分
101 Switching Protocol 服务器已根据客户端的请求切换协议
2xx 成功状态码
200 OK 请求已成功,服务器正常处理返回请求的内容
201 Create 请求已成功,并且返回服务器已创建的资源
204 No Content 请求已成功,但响应中不包含实体内容
3xx 重定向状态码
301 Moved Permanently 请求的资源已经永久移动到新的位置
302 Found 请求的资源临时移动到不同的位置
304 Not Modified 客户端的缓存副本仍有效,可以使用缓存的版本
4xx 客户端错误状态码
400 Bad Request 服务器无法理解请求的语法或参数
401 Unauthorized 请求需要身份验证
404 Not Found 请求的资源不在
5xx 服务器错误状态码
500 Internal Server Error 服务器在处理请求时遇到错误
503 Service Unavailable 服务器无法处理请求

不足

无状态

HTTP/1.1 的连接是无状态的。当重新建立与服务器建立连接后,原有的状态无法得到恢复,从而导致在一些关联性的操作会丢失,比如我们在 A 页面的商城里面登录,在 B 页面的商城列表里,也应当带上用户的状态信息。因此,在客户端和服务器使用 HTTP1 进行通信时,客户端会生成一份 Cookie 用于保存状态信息,等下次请求的时候带上 Cookie 信息便可以恢复原来的状态。如下图所示:

不安全

HTTP/1.1 是明文传输的。使用 HTTP/1.1 进行客户端和服务端通信,传输的内容是没有经过加密的,在网络上无疑就是裸奔,可以被任何人随处查看。

HTTP/1.1 是连接和传输是不安全的。主要是两个方面,一个方面是连接上不会去甄别通信对象的身份合法性和正确性,因此会被伪装网站欺骗;另一个方面是无法保证传输内容是否被篡改过,因此容易被中间者攻击,比如植入广告等。

队头阻塞

HTTP/1.1 存在队头阻塞。虽然 HTTP/1.1 引入了管道传输,但服务端是无法并发处理所有请求的,需要处理完响应后,才能处理下一个,期间的请求都会被阻塞。因此是客户端发送是并发,服务器串行处理。

网络优化

网络优化可以提高性能和效率,下面是一些常见的策略和技术。

第一,避免发起 HTTP 请求。通过强制缓存和协商缓存,减少客户端发起 HTTP 请求的次数。一旦请求的资源缓存过期后,再重新发起网络请求。

第二,减少 HTTP 请求次数。如果无法避免发起网络请求,那可以减少发起请求的次数,如减少重定向的次数(让代理服务器去做)。或者将多个请求合并成一个请求,可以减少发送冗余的首部和 TCP 连接的次数,节省 TCP 握手的过程。

第三,减少响应数据的大小。可以客户端和服务器传输过程中的数据进行无损或有损压缩,从而提高网络的传输效率。

总结

本文先是介绍了 HTTP 协议做了一个简单的概要。然后从特性这一方面对 HTTP/1.1 进行学习和认识。同时,我们也了解到 HTTP/1.1 目前存在的局限性。最后,我们也了解到对于 HTTP/1.1 的一些常用优化策略和技术,提供请求的效率和性能。

创作不易,喜欢的话请点赞收藏转载,您的支持是我更新的最大动力!!!

相关推荐
快乐巅峰6 分钟前
为什么选择Elysia.js - Node.js后端框架的最佳选择
前端·后端
A了LONE7 分钟前
自定义btn按钮
java·前端·javascript
梦想CAD控件14 分钟前
在线CAD实现形位公差标注(在线编辑DWG)
前端·javascript·node.js
掘金一周15 分钟前
写个vite插件自动处理系统权限,降低99%重复工作 | 掘金一周 7.17
前端·人工智能·后端
爱编程的喵37 分钟前
React Fragment 深度解析:告别多余的 DOM 节点
前端·react.js
多啦C梦a38 分钟前
《hash+history》你点“关于”,页面却没刷新?!——揭秘前端路由的“穿墙术”
前端·javascript·面试
HHW41 分钟前
大文件上传难题?前端优雅解决方案全解析!
前端·node.js
蓝倾41 分钟前
淘宝获取商品规格接口(item-sku)操作详解
前端·后端·fastapi
水纹42 分钟前
使用pdfjs_3.2.146 预览并本地存储批注demo
前端·javascript
血舞之境43 分钟前
Android Gradle Plugin 7x 升级到 8.1 实战问题总结
前端