HTTP协议之进阶篇

本文深入解析HTTP协议的关键特性,包括实体数据类型、连接管理、重定向、Cookie机制、缓存控制及代理服务,揭示HTTP如何高效传输数据并保障用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HTTP的实体数据

HTTP 里经常遇到的几个数据类别

  • text:即文本格式的可读数据,我们最熟悉的应该就是 text/html 了,表示超文本文档,此外还有纯文本 text/plain、样式表 text/css 等。
  • image:即图像文件,有 image/gif、image/jpeg、image/png 等。
  • audio/video:音频和视频数据,例如 audio/mpeg、video/mp4 等。
  • application:数据格式不固定,可能是文本也可能是二进制,必须由上层应用程序来解释。常见的有 application/json,application/javascript、application/pdf 等,另外,如果实在是不知道数据是什么类型,像刚才说的“黑盒”,就会是 application/octet-stream,即不透明的二进制数据。

Encoding type 常用的只有下面三种:

  • gzip:GNU zip 压缩格式,也是互联网上最流行的压缩格式;
  • deflate:zlib(deflate)压缩格式,流行程度仅次于 gzip;
  • br:一种专门为 HTTP 优化的新压缩算法(Brotli)。

客户端用 Accept 头告诉服务器希望接收什么样的数据,而服务器用 Content 头告诉客户端实际发送了什么样的数据。

在这里插入图片描述

总结
在这里插入图片描述

  • 数据类型表示实体数据的内容是什么,使用的是 MIME type,相关的头字段是 AcceptContent-Type
  • 数据编码表示实体数据的压缩方式,相关的头字段是 Accept-EncodingContent-Encoding
  • 语言类型表示实体数据的自然语言,相关的头字段是 Accept-LanguageContent-Language
  • 字符集表示实体数据的编码方式,相关的头字段是 Accept-CharsetContent-Type
  • 客户端需要在请求头里使用 Accept 等头字段与服务器进行“内容协商”,要求服务器返回最合适的数据;
  • Accept 等头字段可以用“,”顺序列出多个可能的选项,还可以用“;q=”参数来精确指定权重。

HTTP 传输大文件相关

  • 压缩 HTML 等文本文件是传输大文件最基本的方法;
  • 分块传输可以流式收发数据,节约内存和带宽,使用响应头字段“Transfer-Encoding: chunked”来表示,分块的格式是 16 进制长度头 + 数据块;
  • 范围请求可以只获取部分数据,即“分块请求”,实现视频拖拽或者断点续传,使用请求头字段“Range”和响应头字段“Content-Range”,响应状态码必须是 206;
  • 也可以一次请求多个范围,这时候响应报文的数据类型是“multipart/byteranges”,body 里的多个部分会用 boundary 字符串分隔。
  • Transfer-Encoding: chunked”和“Content-Length”这两个字段是互斥的,也就是说响应报文里这两个字段不能同时出现,一个响应报文的传输要么是长度已知,要么是长度未知(chunked)。

在这里插入图片描述

HTTP的连接管理

短连接

  • 因为客户端与服务器的整个连接过程很短暂,它底层的数据传输基于 TCP/IP,每次发送请求前需要先与服务器建立连接,收到响应报文后会立即关闭连接不会与服务器保持长时间的连接状态,所以就被称为“短连接”(short-lived connections)。早期的 HTTP 协议也被称为是“无连接”的协议。
  • 短连接的缺点相当严重,因为在 TCP 协议里,建立连接和关闭连接都是非常“昂贵”的操作。短连接有三分之二的时间被浪费掉了,传输效率低得惊人。

长连接

  • 针对短连接暴露出的缺点,HTTP 协议就提出了“长连接”的通信方式,也叫“持久连接”(persistent connections)、“连接保活”(keep alive)、“连接复用”(connection reuse)。其实解决办法也很简单,用的就是“成本均摊”的思路,既然 TCP 的连接和关闭非常耗时间,那么就把这个时间成本由原来的一个“请求 - 应答”均摊到多个“请求 - 应答”上。这样虽然不能改善 TCP 的连接效率,但基于“分母效应”,每个“请求 - 应答”的无效时间就会降低不少,整体传输效率也就提高了。
  • 长连接的小缺点:因为 TCP 连接长时间不关闭,服务器必须在内存里保存它的状态,这就占用了服务器的资源。如果有大量的空闲长连接只连不发,就会很快耗尽服务器的资源,导致服务器无法为真正有需要的用户提供服务。所以,长连接也需要在恰当的时间关闭,不能永远保持与服务器的连接,这在客户端或者服务器都可以做到。

短连接与长连接的对比示意图

在这里插入图片描述

HTTP/1.1 中的连接都会默认启用长连接。不需要用什么特殊的头字段指定,只要向服务器发送了第一次请求,后续的请求都会重复利用第一次打开的 TCP 连接,也就是长连接,在这个连接上收发数据。

队头阻塞

  • 队头阻塞”与短连接和长连接无关,而是由 HTTP 基本的“请求 - 应答”模型所导致的。因为 HTTP 规定报文必须是“一发一收”,这就形成了一个先进先出的“串行”队列。队列里的请求没有轻重缓急的优先级,只有入队的先后顺序,排在最前面的请求被最优先处理。如果队首的请求因为处理的太慢耽误了时间,那么队列里后面的所有请求也不得不跟着一起等待,结果就是其他的请求承担了不应有的时间成本。
  • “队头阻塞”问题会导致性能下降,可以用“并发连接”和“域名分片”技术缓解。

HTTP的重定向和跳转

  • 跳转动作是由浏览器的使用者主动发起的,可以称为“主动跳转”,但还有一类跳转是由服务器来发起的,浏览器使用者无法控制,相对地就可以称为“被动跳转”,这在 HTTP 协议里有个专门的名词,叫做“重定向”(Redirection)。
  • Location”字段属于响应字段,必须出现在响应报文里。但只有配合 301/302 状态码才有意义,它标记了服务器要求重定向的 URI,这里就是要求浏览器跳转到“index.html”。浏览器收到 301/302 报文,会检查响应头里有没有“Location”。如果有,就从字段值里提取出 URI,发出新的 HTTP 请求,相当于自动替我们点击了这个链接。

重定向状态码

  • 301俗称“永久重定向”(Moved Permanently),意思是原 URI 已经“永久”性地不存在了,今后的所有请求都必须改用新的 URI。
  • 302俗称“临时重定向”(“Moved Temporarily”),意思是原 URI 处于“临时维护”状态,新的 URI 是起“顶包”作用的“临时工”。
  • 303 See Other:类似 302,但要求重定向后的请求改为 GET 方法,访问一个结果页面,避免 POST/PUT 重复操作;
  • 307 Temporary Redirect:类似 302,但重定向后请求里的方法和实体不允许变动,含义比 302 更明确;
  • 308 Permanent Redirect:类似 307,不允许重定向后的请求变动,但它是 301“永久重定向”的含义。

HTTP的Cookie机制

Cookie 的工作过程

  • 这要用到两个字段:响应头字段Set-Cookie和请求头字段Cookie
  • 当用户通过浏览器第一次访问服务器的时候,服务器肯定是不知道他的身份的。所以,就要创建一个独特的身份标识数据,格式是“key=value”,然后放进 Set-Cookie 字段里,随着响应报文一同发给浏览器。
  • 浏览器收到响应报文,看到里面有 Set-Cookie,知道这是服务器给的身份标识,于是就保存起来,下次再请求的时候就自动把这个值放进 Cookie 字段里发给服务器。
  • 因为第二次请求里面有了 Cookie 字段,服务器就知道这个用户不是新人,之前来过,就可以拿出 Cookie 里的值,识别出用户的身份,然后提供个性化的服务。
    在这里插入图片描述
  • Cookie 是由浏览器负责存储的,而不是操作系统。所以,它是“浏览器绑定”的,只能在本浏览器内生效

Cookie 的属性

设置 Cookie 的生存周期,也就是它的有效期,让它只能在一段时间内可用,就像是食品的“保鲜期”,一旦超过这个期限浏览器就认为是 Cookie 失效,在存储里删除,也不会发送给服务器。

Cookie 的有效期可以使用 ExpiresMax-Age 两个属性来设置。

  • “Expires”俗称“过期时间”,用的是绝对时间点,可以理解为“截止日期”(deadline)。“Max-Age”用的是相对时间,单位是秒,浏览器用收到报文的时间点再加上 Max-Age,就可以得到失效的绝对时间。
  • Expires 和 Max-Age 可以同时出现,两者的失效时间可以一致,也可以不一致,但浏览器会优先采用 Max-Age 计算失效期。

设置 Cookie 的作用域,让浏览器仅发送给特定的服务器和 URI,避免被其他网站盗用。

  • 作用域的设置比较简单,“Domain”和“Path”指定了 Cookie 所属的域名和路径,浏览器在发送 Cookie 前会从 URI 中提取出 host 和 path 部分,对比 Cookie 的属性。如果不满足条件,就不会在请求头里发送 Cookie。

Chrome 开发者工具是查看 Cookie 的有力工具,在“Network-Cookies”里可以看到单个页面 Cookie 的各种属性,另一个“Application”面板里则能够方便地看到全站的所有 Cookie。

在这里插入图片描述
在这里插入图片描述

HTTP的缓存控制

  • 缓存是优化系统性能的重要手段,HTTP 传输的每一个环节中都可以有缓存

缓存的运行机制

  1. 浏览器发现缓存无数据,于是发送请求,向服务器获取资源;
  2. 服务器响应请求,返回资源,同时标记资源的有效期;
  3. 浏览器缓存资源,等待下次重用。

在这里插入图片描述

  • 服务器使用“Cache-Control”设置缓存策略,常用的是“max-age”,表示资源的有效期;
  • max-age 是“生存时间”(又叫“新鲜度”“缓存寿命”,类似 TTL,Time-To-Live),时间的计算起点是响应报文的创建时刻(即 Date 字段,也就是离开服务器的时刻),而不是客户端收到报文的时刻,也就是说包含了在链路传输过程中所有节点所停留的时间。

服务器的缓存控制策略流程图

在这里插入图片描述

  • 浏览器收到数据就会存入缓存,如果没过期就可以直接使用,过期就要去服务器验证是否仍然可用;
  • 验证资源是否失效需要使用“条件请求”,常用的是“if-Modified-Since”和“If-None-Match”,收到 304 就可以复用缓存里的资源;
  • 验证资源是否被修改的条件有两个:“Last-modified”和“ETag”,需要服务器预先在响应报文里设置,搭配条件请求使用;
  • 浏览器也可以发送“Cache-Control”字段,使用“max-age=0”或“no_cache”刷新数据。

HTTP的代理服务

  • 代理服务”就是指服务本身不生产内容,而是处于中间位置转发上下游的请求和响应,具有双重身份:面向下游的用户时,表现为服务器,代表源服务器响应客户端的请求;而面向上游的源服务器时,又表现为客户端,代表客户端发送请求。

  • 代理中常用的负载均衡算法你应该也有所耳闻吧,比如轮询一致性哈希等等,这些算法的目标都是尽量把外部的流量合理地分散到多台源服务器,提高系统的整体资源利用率和性能。

在这里插入图片描述
在负载均衡的同时,代理服务还可以执行更多的功能,比如:

  • 健康检查:使用“心跳”等机制监控后端服务器,发现有故障就及时“踢出”集群,保证服务高可用;
  • 安全防护:保护被代理的后端服务器,限制 IP 地址或流量,抵御网络攻击和过载;
  • 加密卸载:对外网使用 SSL/TLS 加密通信认证,而在安全的内网不加密,消除加解密成本;
  • 数据过滤:拦截上下行的数据,任意指定策略修改请求或者响应;
  • 内容缓存:暂存、复用服务器响应。

计算机科学领域里的任何问题,都可以通过引入一个中间层来解决。

  • HTTP 代理就是客户端和服务器通信链路中的一个中间环节,为两端提供“代理服务”;
  • 代理处于中间层,为 HTTP 处理增加了更多的灵活性,可以实现负载均衡、安全防护、数据过滤等功能;
  • 代理服务器需要使用字段“Via”标记自己的身份,多个代理会形成一个列表;
  • 如果想要知道客户端的真实 IP 地址,可以使用字段“X-Forwarded-For”和“X-Real-IP”;
  • 专门的“代理协议”可以在不改动原始报文的情况下传递客户端的真实 IP。

HTTP的缓存代理

  • HTTP 的服务器缓存功能主要由代理服务器来实现(即缓存代理),而源服务器系统内部虽然也经常有各种缓存(如 Memcache、Redis、Varnish 等),但与 HTTP 没有太多关系。

在 HTTP 的缓存体系中,缓存代理的身份十分特殊,它“既是客户端,又是服务器”,同时也“既不是客户端,又不是服务器”。

服务器端缓存控制策略,可以同时控制客户端和代理
在这里插入图片描述
客户端缓存控制策略
在这里插入图片描述

  • 计算机领域里最常用的性能优化手段是“时空转换”,也就是“时间换空间”或者“空间换时间”,HTTP 缓存属于后者;
  • 缓存代理是增加了缓存功能的代理服务,缓存源服务器的数据,分发给下游的客户端;
  • “Cache-Control”字段也可以控制缓存代理,常用的有“private”“s-maxage”“no-transform”等,同样必须配合“Last-modified”“ETag”等字段才能使用;
  • 缓存代理有时候也会带来负面影响,缓存不良数据,需要及时刷新或删除。

你知道的越多,你不知道的越多。
有道无术,术尚可求,有术无道,止于术。
如有其它问题,欢迎大家留言,我们一起讨论,一起学习,一起进步

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值