响应报文中的 Vary 头字段的作用

简介: 前端西瓜哥

Vary 字段主要用于 代理服务器实现缓存服务

不同客户端对内容格式的支持程度不同(比如有些支持数据压缩,有些不支持),所以即便请求URL 和请求方法都相同,服务器返回的数据也会不同(称为内容协商)。

Vary 字段记录了代理服务器返回特定数据参考了哪些请求字段。

代理服务器拿到源服务器的响应报文,会根据 Vary 里的字段列表,缓存不同版本的数据。当客户端再次访问时,代理服务器会分析请求字段,返回正确的版本。

在叙述 Vary 的工作原理前,我们先简单了解一下什么是代理服务器。

代理服务器

客户端访问网站会发起请求,请求会被发送到所请求资源所在的服务器,服务器会将对应的资源返回给客户端。如果并发访问量很小,服务器并没有什么压力。

但如果并发量很大,我们就得考虑缓存了。缓存分为客户端缓存和服务器缓存。服务器缓存的方案,可以将数据直接缓存缓存到内存中,也可以将数据缓存到代理服务器中。

我们在客户端到服务器中间添加一些 代理服务器,它们的其中一个功能是 内容缓存。另外,为了进行区分,我们将真正提供数据的服务器称为 源服务器

配合 DNS,我们可以将访问分配到离客户端最近的代理服务器,从里面获取数据。如果没有数据,该代理服务器会再发送和客户端相同的请求给源服务器,并将从源服务器返回的数据缓存起来,并返回数据给客户端。

这样,下次客户端再次请求相同的资源时,代理服务器就可以直接返回数据而不需要再转发给源服务器。

代理服务器除了可以提供 内存缓存,还有以下几个作用:

  1. 健康检查
  2. 安全防护
  3. 加密卸载
  4. 数据过滤

下面我们就通过一个例子,来说明 Vary 在服务端缓存中发挥的作用。

举例说明 Vary 的工作原理

假设客户端 A 请求了一个数据,且该客户端支持 gzip 压缩,于是请求头字段中带有 Accept-Encoding: gzip

请求来到了代理服务器,但是里面没有缓存,所以代理服务器把请求又发送给了源服务器。源服务器拿到了请求报文,分析了一波,决定返回一个进行了 gzip 压缩的数据。

另外,源服务器还希望介于它和客户端之间的代理服务器,也能够像它一样优秀,可以根据 Accept-Encoding 返回正确的数据,于是在响应头字段中加上了 Vary: Accept-Encoding,并返回了数据A 给代理服务器。

数据A 来到了代理服务器,代理服务器取出了 Vary 字段,发现里面有个 Accept-Encoding,于是它明白了,它需要将当前响应报文的 Accept-Encoding 作为一个标志,映射到当前这个缓存数据A。即:

URL + 请求方法 + "Accept-Encoding: gzip" -> 数据A

代理服务器缓存好了源服务器的数据后,并保存了映射关系,就把数据返回给了客户端 A。

很快,客户端 A 又发送相同请求,代理服务器接收了请求且缓存还没过期,且发现请求头依旧有 Accept-Encoding: gzip,于是缓存命中了数据A,数据A被返回给了客户端A。

在缓存未过期的期间,只要任何一个客户端的请求头里有 Accept-Encoding: gzip且请求url,代理服务器返回的数据都是数据A。

不久后,不支持解压功能的客户端B 发送一个没有 Accept-Encoding 字段的请求。代理服务器拿到了数据,缓存没有命中,于是和上面一样,拿到一个新的缓存数据B,得到了一个新的映射关系:

URL + 请求方法 + 无 Accept-Encoding 的头字段 -> 数据B

如果代理服务器不使用 Vary,纯粹只是根据 请求URL和请求方法 来判断是否缓存命中,那不支持解压功能的 客户端B 就可能会错误拿到代理服务器中的被压缩过的 数据A。

通过 Vary 头字段,我们可以避免客户端B拿到一个无法解压的数据A。

总结

这便是 Vary 头字段的作用:增加代理服务器的是否缓存命中的变量,而不是仅根据 请求URL 和 请求方法 来决定是否命中。

相关文章
|
存储 JavaScript
vue页面跳转取消上一个页面请求
本文介绍了在Vue中如何取消上一个页面的请求,以避免页面跳转时请求未完成导致的数据错误。核心方法是使用axios的请求拦截器设置请求的取消令牌(cancelToken),并在vuex中存储这些取消令牌的引用。当进行路由跳转时,通过路由守卫清除这些请求,达到取消上一个页面请求的目的。
487 2
SpringBoot——SpringBoot中使用过滤器Filter的两种方式
SpringBoot——SpringBoot中使用过滤器Filter的两种方式
2733 0
SpringBoot——SpringBoot中使用过滤器Filter的两种方式
|
存储 安全 JavaScript
XSS跨站脚本攻击详解(包括攻击方式和防御方式)
这篇文章详细解释了XSS跨站脚本攻击的概念、原理、特点、类型,并提供了攻击方式和防御方法。
4602 2
|
安全 Docker 容器
Docker中运行容器时Operation not permitted报错问题解决
【10月更文挑战第2天】Docker中运行容器时Operation not permitted报错问题解决
4830 3
|
存储 网络安全 API
|
缓存 JavaScript C++
计算属性及计算属性与methods的使用区别
本文解释了Vue.js中的计算属性(computed properties)的概念和使用方法,并与methods方法进行了对比。计算属性基于现有数据自动重新计算,具有缓存效果,适用于数据的处理和结果展示。而methods方法每次调用都会执行,适合处理业务逻辑。通过示例代码,展示了计算属性和methods方法的区别。
计算属性及计算属性与methods的使用区别
|
12月前
|
IDE Java 编译器
Java:如何确定编译和运行时类路径是否一致
类路径(Classpath)是JVM用于查找类文件的路径列表,对编译和运行Java程序至关重要。编译时通过`javac -classpath`指定,运行时通过`java -classpath`指定。IDE如Eclipse和IntelliJ IDEA也提供界面管理类路径。确保编译和运行时类路径一致,特别是外部库和项目内部类的路径设置。
664 5
|
Kubernetes Java Docker
多阶段构建:精妙优化Docker镜像大小和性能
在容器化应用的世界中,Docker镜像大小和性能优化是至关重要的。多阶段构建是一项强大的技术,通过精心设计Dockerfile,可以在构建镜像时去除不必要的组件,从而显著减小镜像大小,提高性能。本文章将深入讨论多阶段构建的各个方面,并通过更为丰富和实际的示例代码,帮助大家全面了解和掌握这一重要技术。
|
机器学习/深度学习 搜索推荐 数据挖掘
【深度解析】超越RMSE和MSE:揭秘更多机器学习模型性能指标,助你成为数据分析高手!
【8月更文挑战第17天】本文探讨机器学习模型评估中的关键性能指标。从均方误差(MSE)和均方根误差(RMSE)入手,这两种指标对较大预测偏差敏感,适用于回归任务。通过示例代码展示如何计算这些指标及其它如平均绝对误差(MAE)和决定系数(R²)。此外,文章还介绍了分类任务中的准确率、精确率、召回率和F1分数,并通过实例说明这些指标的计算方法。最后,强调根据应用场景选择合适的性能指标的重要性。
1409 0
|
存储 缓存 监控
一文搞懂绍Servlet规范。
Servlet规范是JavaEE规范中的一种。在servlet规范中,指定【动态资源文件】开发步骤,在servlet规范中,指定Http服务器调用动态资源文件的规则,在servlet规范中,指定Http服务器管理动态资源文件实例对象规则。