HTTP协议-学习笔记(六)

本文介绍了HTTP协议处理大文件传输的策略,包括数据压缩、分块传输和范围请求,以及HTTP连接管理中的短链接、长连接和并发连接。同时,文章探讨了HTTP的Cookie机制、缓存控制和代理服务的作用,对于理解HTTP协议的性能优化和状态管理提供了深入见解。
摘要由CSDN通过智能技术生成

HTTP传输大文件的方法

数据压缩

  • 解决方法也有个缺点,gzip 等压缩算法通常只对文本文件有较好的压缩率,而图片、音频视频等多媒体数据本身就已经是高度压缩的,再用 gzip 处理也不会变小(甚至还有可能会增大一点),所以它就失效了
    分块传输
  • 大文件整体不能变小,那就把它“拆开”,分解成多个小块,把这些小块分批发给浏览器,浏览器收到后再组装复原
  • 浏览器和服务器都不用在内存里保存文件的全部,每次只收发一小部分,网络也不会被大文件长时间占用,内存、带宽等资源也就节省下来了
  • HTTP 协议里就是“chunked”分块传输编码,在响应报文里用头字段“Transfer-Encoding: chunked”来表示,意思是报文里的 body 部分不是一次性发过来的,而是分成了许多的块(chunk)逐个发送
    在这里插入图片描述
    范围请求
  • 看当下正热播的某穿越剧,想跳过片头,直接看正片,或者有段剧情很无聊,想拖动进度条快进几分钟,这实际上是想获取一个大文件其中的片段数据,而分块传输并没有这个能力
  • HTTP 协议为了满足这样的需求,提出了“范围请求”(range requests)的概念,允许客户端在请求头里使用专用字段来表示只获取文件的一部分,相当于是客户端的“化整为零”
  • 所以服务器必须在响应头里使用字段“Accept-Ranges: bytes”明确告知客户端:“我是支持范围请求的”
GET /16-2 HTTP/1.1
Host: www.chrono.com
Range: bytes=0-31
HTTP/1.1 206 Partial Content
Content-Length: 32
Accept-Ranges: bytes
Content-Range: bytes 0-31/96
  • Range 字段获取了文件的前 32 个字节

  • 有了范围请求之后,HTTP 处理大文件就更加轻松了,看视频时可以根据时间点计算出文件的 Range,不用下载整个文件,直接精确获取片段所在的数据内容

  • 不仅看视频的拖拽进度需要范围请求,常用的下载工具里的多段下载、断点续传也是基于它实现的

先发个 HEAD,看服务器是否支持范围请求,同时获取文件的大小
开 N 个线程,每个线程使用 Range 字段划分出各自负责下载的片段,发请求传输数据
下载意外中断也不怕,不必重头再来一遍,只要根据上次的下载记录,用 Range 请求剩下的那一部分就可以了

HTTP的连接管理

短链接

  • HTTP 协议最初(0.9/1.0)是个非常简单的协议,通信过程也采用了简单的“请求 - 应答”方式
  • 它底层的数据传输基于 TCP/IP,每次发送请求前需要先与服务器建立连接,收到响应报文后会立即关闭连接
    在这里插入图片描述
    长连接
  • TCP 的连接和关闭非常耗时间,那么就把这个时间成本由原来的一个“请求 - 应答”均摊到多个“请求 - 应答”上
    在这里插入图片描述

HTTP/1.1 中的连接都会默认启用长连接。不需要用什么特殊的头字段指定,只要向服务器发送了第一次请求,后续的请求都会重复利用第一次打开的 TCP 连接,也就是长连接,在这个连接上收发数据
我们也可以在请求头里明确地要求使用长连接机制,使用的字段是Connection,值是“keep-alive”

大量长链接会消耗大量服务器资源 所以应该在合适的时间将其关闭

  • 客户端
    • 可以在请求头里加上“Connection: close”字段
  • 服务端(Nginx)
    • 一般不会主动关闭 可以采取一些策略
    • keepalive_timeout 在一段时间内客户端没有发送数据 就断开
    • keepalive_requests 长连接上可发送的最大请求次数 如果超过上限后 也会主动断开

队头阻塞

  • 因为 HTTP 规定报文必须是“一发一收”,这就形成了一个先进先出的“串行”队列。队列里的请求没有轻重缓急的优先级,只有入队的先后顺序,排在最前面的请求被最优先处理
  • 解决
    • 并发链接
    • 域名分片
      在这里插入图片描述
      性能优化

HTTP 里就是“并发连接”(concurrent connections),也就是同时对一个域名发起多个长连接,用数量来解决质量的问题
缺陷 如果每个客户端都建立过多的链接 用户数*并发数 就会变成一个天文数字 服务器资源根本扛不住

小插曲

RFC2616 里明确限制每个客户端最多并发 2 个连接。不过实践证明这个数字实在是太小了,众多浏览器都“无视”标准,把这个上限提高到了 6~8。后来修订的 RFC7230 也就“顺水推舟”,取消了这个“2”的限制

上有政策 下有对策

  • 多开几个域名指向同一台服务器(域名分片)
补充

RTT(Round-Trip Time): 往返时延。 在计算机网络中它是一个重要的性能指标,表示从发送端发送数据开始,到发送端收到来自接收端的确认(接收端收到数据后便立即发送确认),总共经历的时延

HTTP的Cookie机制

意义

  • 由于 http 协议是无状态的
  • 引入 cookie 记录用户状态

传递

  • 响应头字段Set-Cookie和请求头字段Cookie
    在这里插入图片描述
    Cookie 的属性
  • Expires
    • 绝对时间 某年某月某日失效
  • Max-Age
    • 相对时间 单位是秒 报文时间点加上 Max-Age

Expires 和 Max-Age 可以同时出现,两者的失效时间可以一致,也可以不一致,但浏览器会优先采用 Max-Age 计算失效期
在不设置过期时间的情况下 将会一直存在直到关闭浏览器

  • HttpOnly
    • Cookie 只能通过浏览器 HTTP 协议传输,禁止其他方式访问,浏览器的 JS 引擎就会禁用 document.cookie 等一切相关的 API,脚本攻击也就无从谈起了
  • SameSite
    • 可以防范“跨站请求伪造”(XSRF)攻击,设置成“SameSite=Strict”可以严格限定 Cookie 不能随着跳转链接跨站发送,而“SameSite=Lax”则略宽松一点,允许 GET/HEAD 等安全方法,但禁止 POST 跨站发送
  • Domain
    • 指定了 cookie 将要被发送至哪个或哪些域中。默认情况下,domain 会被设置为创建该 cookie 的页面所在的域名,所以当给相同域名发送请求时该 cookie 会被发送至服务器
    • 设置 .example.com
    • fvt.example.com
      www.example.com
      m.example.com
      …example.com 都可以使用
document.cookie = "expires=Mon, 11 Nov 2026 07:34:46 GMT; domain=test.com;path=/"
  • Path
    • path 选项值会与 /test,/test2 等等相匹配;任何以 /test 开头的选项都是合法的。需要注意的是,只有在 domain 选项核实完毕之后才会对 path 属性进行比较。path 属性的默认值是发送 Set-Cookie 消息头所对应的 URL 中的 path 部分

所以domain和path 2个选项共同决定了cookie何时被浏览器自动添加到请求头部中发送出去。如果没有设置这两个选项,则会使用默认值。domain的默认值为设置该cookie的网页所在的域名,path默认值为设置该cookie的网页所在的目录
在这里插入图片描述

补充
  • Cookie 的另一个常见用途是广告跟踪

你上网的时候肯定看过很多的广告图片,这些图片背后都是广告商网站(例如 Google),它会“偷偷地”给你贴上 Cookie 小纸条,这样你上其他的网站,别的广告就能用 Cookie 读出你的身份,然后做行为分析,再推给你广告。
这种 Cookie 不是由访问的主站存储的,所以又叫“第三方 Cookie”(third-party cookie)。如果广告商势力很大,广告到处都是,那么就比较“恐怖”了,无论你走到哪里它都会通过 Cookie 认出你来,实现广告“精准打击”。
为了防止滥用 Cookie 搜集用户隐私,互联网组织相继提出了 DNT(Do Not Track)和 P3P(Platform for Privacy Preferences Project),但实际作用不大。

HTTP 缓存控制

使用HTTP缓存,是设置适当的缓存策略,从而可以避免浏览器重复地向服务端请求资源。 HTTP缓存主要是服务端设置正确的响应头信息
缓存分为两种:强缓存 和 协商缓存

  • 强缓存

    • 强缓存是指浏览器直接使用存在本地的资源,而不再向服务端进行请求。涉及到的响应头有两个: Expires 和 Cache-control
      • no-cache :表明浏览器可以对内容进行缓存,但是必须先向服务器确认,资源未改变的情况下,可以直接使用浏览器的缓存。与 no-stort 互斥
        no-store : 表明内容不允许缓存,包括浏览器以及中间设备,如代理服务器等,与no-cache 互斥( 秒杀页面 )
        public : 表明缓存可以存在于浏览器和中间设备,与 private 互斥
        private :表明缓存只能存在于客户的浏览器中
        max-age: 以秒为单位的时间范围,表明经过多长时间之后,缓存内容将过期。过期之后,浏览器必须重新下载资源
        must-revalidate:又是一个和 no_cache 相似的词,它的意思是如果缓存不过期就可以继续使用,但过期了如果还想用就必须去服务器验证
    • 设置强缓存之后,浏览器每次请求就会使用本地缓存的内容或者根据返回的头部信息去浏览器验证
  • 协商缓存

    • Last-Modified 与 If-Modified-Since
      • 服务端设置 Last-Modified 响应头, 表明资源最后修改的时间,这个值是一个时间点。浏览器请求时,会带上一个头信息 If-Modified-Since,其值为Last-Modified 的值。 服务器对比资源的上一次修改时间和 If-Modified-Since 所表示的时间,如果不曾改变,就返回304。
    • Etag 与 If-None-Match
      • 服务端设置 Etag 响应头, 表明资源的的唯一标识字符串,只要资源被修改过,就会重新生成一个Etag。浏览器请求时,会带上一个头信息 If-None-Match,其值为Etag 的值。 服务器对比资源当前的Etag和 If-None-Match 的值,如果一致,就返回304

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

ETag 还有“强”“弱”之分
强 ETag 要求资源在字节级别必须完全相符,弱 ETag 在值前有个“W/”标记,只要求资源在语义上没有变化,但内部可能会有部分发生了改变(例如 HTML 里的标签顺序调整,或者多了几个空格)

HTTP 代理服务

计算机科学领域里的任何问题,都可以通过引入一个中间层来解决, 如果一个中间层解决不了问题,那就再加一个中间层

面向下游的用户时,表现为服务器,代表源服务器响应客户端的请求;而面向上游的源服务器时,又表现为客户端,代表客户端发送请求

作用

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

使用

  • 代理服务器需要用字段“Via”标明代理的身份
    在这里插入图片描述

服务器的 IP 地址应该是保密的,关系到企业的内网安全,所以一般不会让客户端知道。不过反过来,通常服务器需要知道客户端的真实 IP 地址,方便做访问控制、用户画像、统计分析

  • X-Forwarded-For
    • 每经过一个代理节点就会在字段里追加请求方IP 在字段里最左边的 IP 地址就客户端的地址
  • X-Real-IP
    • 记录客户端 IP 地址,没有中间的代理信息

通过“X-Forwarded-For”操作代理信息必须要解析 HTTP 报文头,这对于代理来说成本比较高,原本只需要简单地转发消息就好,而现在却必须要费力解析数据再修改数据,会降低代理的转发性能
所以就出现了一个专门的“代理协议”(The PROXY protocol),它由知名的代理软件 HAProxy 所定义,也是一个“事实标准”,被广泛采用(注意并不是 RFC)

PROXY TCP4 1.1.1.1 2.2.2.2 55555 80\r\n
GET / HTTP/1.1\r\n
Host: www.xxx.com\r\n
\r\n

这一行文本其实非常简单,开头必须是“PROXY”五个大写字母,然后是“TCP4”或者“TCP6”,表示客户端的 IP 地址类型,再后面是请求方地址、应答方地址、请求方端口号、应答方端口号,最后用一个回车换行(\r\n)结束
服务器看到这样的报文,只要解析第一行就可以拿到客户端地址,不需要再去理会后面的 HTTP 数据,省了很多事情

缺点

  • 代理会增加链路长度,在代理上做一些复杂的处理。会很耗费性能,增加响应时间

缓存代理服务

  • 将一些静态资源 缓存到代理服务器上
  • Cache-Control
    • private 表示缓存只能在客户端保存,是用户“私有”的,不能放在代理上与别人共享
    • public 的意思就是缓存完全开放,谁都可以存,谁都可以用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值