【计算机网络笔记六】应用层(三)HTTP 的 Cookie、缓存控制、代理服务、短连接和长连接

HTTP 的 Cookie 机制要用到两个字段:响应头字段 Set-Cookie 和请求头字段 Cookie

Cookie 可以设置多个 key-value 对, 响应头中可以设置多个 Set-Cookie 字段,请求头Cookie后面可以设置多个键值对,用分号隔开:

ExpiresMax-Age

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

  • Expires 表示绝对有效时间 ,即截止时间 ,俗称"过期时间"
  • Max-Age 表示相对有效时间 ,单位是 ,浏览器用收到报文的时间点加上 Max-Age 就可以得到失效的绝对时间。

ExpiresMax-Age 可以同时出现,两者的失效时间可以一致,也可以不一致,但浏览器会优先采用 Max-Age 计算失效期。

DomainPath

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

"Domain " 和 "Path " 指定了 Cookie 所属的域名路径 ,浏览器在发送 Cookie 前会 从 URI 中提取出 hostpath 部分,对比 Cookie 的属性。如果不满足条件,就不会在请求头里发送 Cookie

HttpOnly

属性 "HttpOnly " 会告诉浏览器,此 Cookie 只能通过 HTTP 协议传输,禁止其他方式访问,浏览器的 JS 引擎就会禁用 document.cookie 等一切相关的API,防止脚本攻击。

SameSite

另一个属性 "SameSite " 可以防范"跨站请求伪造 " (XSRF )攻击,设置成 "SameSite=Strict " 可以严格限定 Cookie 不能随着跳转链接跨站发送,而 "SameSite=Lax " 则略宽松一点,允许 GET /HEAD 等安全方法,但禁止 POST 跨站发送。

HTTP 的缓存控制

一般的话,浏览器拿到响应内容后,会将响应内容缓存到磁盘文件中。

至于浏览器是不是直接使用本地磁盘缓存中的内容,取决于缓存策略。浏览器也会有缓存清理策略,定期的清理磁盘中的缓存页面。

缓存策略:no-store

不允许客户端使用缓存,用于某些变化非常频繁的数据,例如秒杀页面。

缓存策略:max-age

时间的计算起点是响应报文的创建时刻,而不是客户端收到报文的时刻,也就是说包含了在链路传输过程中所有节点所停留的时间。

服务器标记资源有效期使用的头字段是 "Cache-Control ",里面的值 "max-age=30 " 就是资源的有效时间 ,相当于告诉浏览器,"这个页面只能缓存30秒,之后就算是过期,不能用。"(max-age包括了路上的花费时间,真正的有效时间得减去路上的时间)

缓存策略:服务端 + 客户端一起协调

客户端发送 Cache-Control: max-age=0 ,是在告诉服务端,客户端不会使用缓存,但是浏览器的前进后退会用缓存,服务器看到 max-age=0,也就会用一个最新生成的报文回应浏览器。

缓存策略:no-cache

客户端发送 "Cache-Control:no-cache " 的含义和 "Cache-Control:max-age=0" 基本一样,就看后台的服务器怎么理解,通常两者的效果是相同的。

服务端发送 "Cache-Control:no-cache" 的意思并不是不允许缓存,而是可以缓存,但在使用之前必须要去服务器验证是否过期,是否有最新的版本。

如何验证缓存是否过期

可以让客户端发送一个 HEAD 请求,服务端通过 Last-Modified 返回修改时间:

然后客户端与缓存数据比较,如果没有改动就使用缓存,节省网络流量,否则就再发一个 GET 请求,获取最新的版本。但这样的两个请求网络成本太高了。

条件请求

服务器会将 If-Modified-Since 的值与 Last-Modified 段进行对比。如果相等,则表示未修改,响应 304

如果 If-Modified-Since 的值与 Last-Modified 不相等, 则表示修改了,响应 200 状态码,并返回数据。

使用 If-Modified-Since 与 Last-Modified 的缺陷:

  1. 最低时间单位是秒,如果资源更新的速度是秒以下单位,那么该缓存是不能被使用的

  2. 如果文件是通过服务器动态生成的,那么该方法的更新时间永远是生成的时间,尽管文件可能没有变化,所以起不到缓存的作用。

解决方案:Etag & If-None-Match

Etag & If-None-Match

ETag 是"实体标签"(Entity Tag)的缩写,表示资源的一个唯一标识。

服务端发送响应头中包含 ETag 字段,客户端拿到 ETag 字段值下次请求时,在请求头中用 If-None-Match 字段发送该值,服务端拿到该值和 ETag 进行比较,如果和 ETag 相等,说明资源没有变化,服务端会返回状态码 304,则客户端使用本地磁盘缓存文件。

如果服务端判断和 Etag 不相等,说明资源发生变化,服务端会返回状态码 200 ,并在 body 中返回新的资源文件内容。

服务端缓存控制策略和客户端缓存控制策略详细流程图:https://www.processon.com/view/link/62bec42a6376897b9fcfdb47

HTTP 的代理服务

代理(Proxy)是 HTTP 协议中请求方和应答方中间的一个环节,作为"中转站",既可以转发客户端的请求,也可以转发服务器的应答。

正向代理

正向代理:靠近客户端,代替客户端向服务器发送请求。


代理服务器如何进行客户访问控制:

反向代理

反向代理:靠近服务器端,代替服务器响应客户端的请求。

反向代理的负载均衡:

反向代理最基本的一个功能是负载均衡。因为在面向客户端时屏蔽了源服务器,客户端看到的只是代理服务器,源服务器究竟有多少台、是哪些 IP 地址都不知道。

于是代理服务器就可以掌握请求分发的"大权",决定由后面的哪台服务器来响应请求。

反向代理的其他功能:

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

代理相关的头字段

代理服务器需要用字段 "Via " 标明代理的身份。"Via" 追加的是代理主机名(或者域名)。

Via 字段只解决了客户端和源服务器判断是否存在代理的问题,还不能知道对方真实信息。

  • "X-Forwarded-For " 的字面意思是"为谁而转发",每经过一个代理节点就会在字段里追加一个 IP 地址,所以,在字段里最左边的 IP 地址就是客户端的地址
  • "X-Real-IP" 是另一种获取客户端真实 IP 的手段,它的作用很简单,就是记录客户端 IP 地址,没有中间的代理信息

HTTP 的缓存代理

为了减少服务器的压力,服务端也会有相应的缓存,HTTP 的服务器缓存功能主要由反向代理服务器来实现(即缓存代理)。



CDN

CDN内容分发网络 ,是一种网络应用服务,全称 Content Delivery Network 或 Content Distribution Network,它的主要作用是解决"长距离"上网络访问速度慢的问题。

  • ① 边缘节点作为缓存代理
  • ② 就近访问

CDN 主要缓存静态资源 。"静态资源 ":比如图片、音频。"动态资源" 是指数据内容是"动态变化"的,也就是由后台服务计算生成的,每次访问都不一样,比如商品的库存、微博的粉丝数等。

CDN 的原理:

  • ① 当用户点击网站页面上的内容 URL,经过本地 DNS 系统解析,DNS 系统会最终将域名的解析权交给 CNAME 指向的 CDN 专用 DNS 服务器。

  • ② CDN 的 DNS 服务器将 CDN 的全局负载均衡设备 IP 地址返回本地域名服务器。

  • ③ 本地域名服务器将 CDN 全局负载均衡设备 IP 地址返回给客户端

  • ④ CDN 全局负载均衡设备根据用户 IP 地址,以及用户请求的内容 URL,选择一台用户所属区域的区域负载均衡设备,告诉用户向这台设备发起请求。

  • ⑤ 区域负载均衡设备会为用户选择一台合适的缓存服务器提供服务,选择的依据包括:

    根据用户 IP 地址,判断哪一台服务器距用户最近;

    根据用户所请求的 URL 中携带的内容名称,判断哪一台服务器上有用户所需内容;

    查询各个服务器当前的负载情况,判断哪一台服务器尚有服务能力

  • ⑥ 基于以上这些条件的综合分析之后,区域负载均衡设备会向全局负载均衡设备返回一台缓存服务器的 IP 地址

  • ⑦ 全局负载均衡设备把服务器的 IP 地址返回给用户。

  • ⑧ 用户向缓存服务器发起请求,缓存服务器响应用户请求,将用户所需内容传送到用户终端。如果这台缓存服务器上并没有用户想要的内容,而区域均衡设备依然将它分配给了用户,那么这台服务器就要向它的上一级缓存服务器请求内容,直至追溯到网站的源服务器将内容拉到本地。

简单总结一下就是由 CDN 负载均衡设备返回一台离用户最近的缓存服务器的 IP 地址给用户,如果这台缓存服务器上没有用户需要的内容,则向上一级缓存服务器请求,直到追溯至源服务器将内容拉到本地

HTTP 的短连接和长连接

短连接

因为客户端与服务器的整个连接过程很短暂,不会与服务器保持长时间的连接状态,所以就被称为短连接

短连接的缺点相当严重,因为在 TCP 协议里,建立连接和关闭连接都是非常"昂贵"的操作。

TCP 建立连接要有"三次握手",发送 3 个数据包,需要 1 个RTT;关闭连接是"四次挥手",4 个数据包需要 2 个RTT。

长连接

客户端和服务端保持长时间的连接,所以称为长连接

成本均摊:既然 TCP 的连接和关闭非常耗时间,那么就把这个时间成本由原来的一个"请求 - 应答"均摊到多个"请求 - 应答"上。

长连接的实现方式:心跳 。即在⼀定间隔时间内,使用 TCP 连接发送超短无意义消息来让网关不能将自己定义为「空闲连接」,从而防止网关将自己的连接关闭。

由于长连接对性能的改善效果非常显著,所以在 HTTP/1.1 中的连接都会默认启用长连接

连接相关的头字段

我们也可以在请求头里明确地要求使用长连接机制,使用的字段是 Connection ,值是 "keep-alive" 。

不过不管客户端是否显式要求长连接,如果服务器支持长连接,它总会在响应报文里放一个 "Connection:keep-alive" 字段,告诉客户端:"我是支持长连接的,接下来就用这个TCP 一直收发数据"。

长连接的缺点

TCP 连接长时间不关闭,服务器必须在内存里保存它的状态,这就占用了服务器的资源。如果有大量的空闲长连接只连不发,就会很快耗尽服务器的资源,导致服务器无法为真正有需要的用户提供服务。

所以,长连接也需要在恰当的时间关闭,不能永远保持与服务器的连接。客户端和服务端都可以使用恰当的方式关闭连接。

客户端主动关闭长连接

在客户端,可以在请求头里加上 "Connection:close" 字段,告诉服务器: "这次通信后就关闭连接"

服务器看到这个字段,就知道客户端要主动关闭连接,于是在响应报文里也加上这个字段,发送之后就关闭 TCP 连接。

服务端端主动关闭长连接

服务器端通常不会主动关闭连接,但也可以使用一些策略。拿 Nginx 来举例,它有两种方式:

  • ① 使用 "keepalive_timeout" 指令,设置长连接的超时时间,如果在一段时间内连接上没有任何数据收发就主动断开连接,避免空闲连接占用系统资源。

  • ② 使用 "keepalive_requests" 指令,设置长连接上可发送的最大请求次数。比如设置成 1000,那么当 Nginx 在这个连接上处理了 1000 个请求后,也会主动断开连接。

队头阻塞

如果队首的请求因为处理的太慢耽误了时间,那么队列里后面的所有请求也不得不跟着一起等待,这个问题就是队首阻塞

如何解决队头阻塞问题?
  • 并发连接 + 域名分片

  • "并发连接" (concurrent connections) :也就是一个浏览器进程同时对一个域名发起多个长连接


    注:HTTP 协议和浏览器限制对一个域名的并发连接数量为 6 ~ 8 个。

  • 域名分片:服务端使用多个不同的域名指向同一个 IP,可以减少服务器压力。

    一般公司使用多个不同的域名可以指向同一个 IP,每个域名可以支持 6 ~ 8 个长连接,那么 3 个域名可以支持 18 ~ 24 个长连接了。

HTTP 1.1 和 HTTP 1.0 的一些区别

HTTP 1.0 最早在网页中使用是在 1996 年,那个时候只是使用一些较为简单的网页上和网络请求上,而 HTTP 1.1 则在 1999 年才开始广泛应用于现在的各大浏览器网络请求中,同时 HTTP 1.1 也是当前使用最为广泛的 HTTP 协议。 主要区别主要体现在:

  1. 缓存处理 ,在 HTTP 1.0 中主要使用 header 里的 If-Modified-SinceExpires 来做为缓存判断的标准,HTTP 1.1 则引入了更多的缓存控制策略例如 Entity tagIf-Unmodified-SinceIf-MatchIf-None-Match 等更多可供选择的缓存头来控制缓存策略。
  2. 带宽优化及网络连接的使用 ,HTTP 1.0 中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP 1.1 则在请求头引入了 range 头域,它允许只请求资源的某个部分,即返回码是 206Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
  3. 错误通知的管理 ,在 HTTP 1.1 中新增了 24 个错误状态响应码,如 409Conflict )表示请求的资源与资源的当前状态发生冲突;410Gone)表示服务器上的某个资源被永久性的删除。
  4. Host头必填 ,在 HTTP 1.0 中认为每台服务器都绑定一个唯一的 IP 地址,因此,请求消息中的 URL 并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个 IP 地址。HTTP 1.1 的请求消息和响应消息都应支持 Host 头域,且请求消息中如果没有 Host 头域会报告一个错误(400 Bad Request)。
  5. 默认开启长连接 ,HTTP 1.1 支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个 TCP 连接上可以传送多个 HTTP 请求和响应,减少了建立和关闭连接的消耗和延迟,在 HTTP 1.1 中默认开启 Connection:keep-alive,一定程度上弥补了 HTTP 1.0 每次请求都要创建连接的缺点。

HTTP 1.0 和 HTTP 1.1 的最大区别就是 HTTP 1.1 可以支持长连接,减少 TCP 的建立和关闭次数,在一个 TCP 连接上可以进行多个 HTTP 请求。

相关推荐
小突突突17 分钟前
总结 HTTP 协议的基本格式, 相关知识以及抓包工具fiddler的使用
网络协议·http·fiddler
咖啡星人k3 小时前
雷池WAF 处理 HTTP 请求的流程
网络·网络协议·http
Antonio9153 小时前
【网络编程】HTTP网络编程
网络·网络协议·http
Master_清欢5 小时前
vue3实现跨页面缓存
缓存·vue
椰椰椰耶7 小时前
【redis】set 类型:基本命令
数据库·redis·缓存
小突突突7 小时前
总结 HTTPS 的加密流程
网络协议·http·https
小二·7 小时前
Redis的缓存雪崩、缓存击穿、缓存穿透与缓存预热、缓存降级
redis·缓存·mybatis
网安-轩逸7 小时前
HTTP与HTTPS的深度解析:技术差异、安全机制及应用场景
安全·http·https
道法自然,人法天9 小时前
SpringDataRedis存储Redis的数据序列化
数据库·redis·缓存
李少兄11 小时前
redis工具类
数据库·redis·缓存