我们在前两篇的内容中分别学习了缓存和代理,大致了解了缓存有哪些头字段,代理是如何服务于服务器和客户端的,那么把两者结合起来,代理缓存,也就是说代理服务器也可以缓存,当客户端请求数据的时候,未必一定要追溯到源服务器上,代理服务器就可以直接把缓存的数据返回给客户端。并且,HTTP的缓存,大多数其实都是由代理服务器来实现,虽然源服务器也有各种缓存,比如大家可能听过的Redis,还有Memcache、Varnish等等,但是基本上跟HTTP没啥关系。

  如果没有代理缓存,代理服务器仅仅只是一个中专作用,转发客户端和服务器的豹纹,中间不会存储任何数据。但是一旦给代理加上缓存后,事情就有些变化了。它在转发报文的同时,还要把报文存入自己的Cache里。下一次再有同样的请求,代理服务器就可以自己决断,从自己的缓存中取出数据返回给客户端,就无需再去源服务器获取。这样就降低了用户的等待时间,同时也节约了源服务器的网络带宽。

  在HTTP的缓存体系中,缓存代理的身份十分特殊,它既是客户端,又是服务器,同时呢,它也既不是客户端,又不是服务器。因为代理面向客户端,就是服务器,面向服务器就表现为客户端,但是实际上代理又只是个中转,并不是真正的数据消费者和生产者,所以我们需要学一些新的Cache-Control属性来对它做些额外的约束。

  嗯,这些新的属性就是本篇的重点了。建议大家对比着缓存那篇文章来看~

一、源服务器的缓存控制

  源服务器的缓存控制,额……原谅我重复了一遍标题,在有代理服务器的场景下,它控制了哪些设备或者说终端或者说客户端呢?首先源服务器链路前的所有设备,包括代理服务器,对于源服务器来说都是客户端。那么问题来了,当有多个同样角色的时候,我们要怎么区分它们,针对不同的角色,设置不同的头字段属性呢?

  我们在缓存那一章所学的Cache-Control的四个属性,对于代理服务器来说也是可以使用的,但是客户端和代理服务器肯定是不一样的,客户端只是自己使用,但是代理服务器,可能会分发给很多客户端使用。所以,第一,我们要做的就是对代理服务器和源服务器的HTTP数据做不同的标识。

  首先,我们可以使用“private”和“public”来区分代理服务器和客户端上的缓存。比如像cookie这种私有性很强的数据,只能存储在客户端,不然被黑进了代理获取了用户的私有数据那可是很严重的问题了。

  还有相对于“must-revalidate”是只要缓存过期,就要去源服务器验证,而“proxy-revalidate”只要求代理的缓存过期后必须验证,不必回溯到源服务器,只验证代理的缓存就可以了。

  再次,缓存的生存时间可以使用“s-maxage”,其实就是share-maxage的简写,用它来限定在代理上能够存活多久,而客户端扔就使用“max-age”。

  还有一个代理专用的属性,“no-transform”。代理有的时候会对缓存下来的数据做一些优化,比如把图片生成如png、webp等各种格式,方便今后的请求,而“no-transform”就会禁止这样的转换。

  最后,大家一定要注意,源服务器在设置完Cache-Control字段后,必须要为报文加上“Last-Modified”或者“ETag”属性,否则客户端和代理后面就无法使用条件请求来验证缓存是否有效。

  最后的最后我们基于缓存那一章的流程图,把代理服务器的验证逻辑也加进去。

  我们仔细来看一下这张图,在缓存失效后的验证节点,如果需要验证的话,会额外的去查看是否是代理缓存,并决定后续是查询代理还是查询源服务器。继而判断中间代理的缓存逻辑,是private还是public。然后继续判断各自路径的maxage。

  仔细看完这张图后,我们发现,整个验证的核心节点和关键步骤其实是没有什么变化的,只是在判断的节点中额外的加入了是否需要代理的逻辑罢了。大家好好消化,仔细区分。

二、客户端的缓存控制。

  客户端的缓存控制相比于源服务器的缓存控制,在加入了代理的场景下要相对简单一些。对于客户端来说,代理服务器就是服务器,所以max-age、no-store、no-cache这三个属性,跟面向源服务器时是一样的。

  但是关于缓存的生存时间,在代理服务器上的约束和条件则多了两个新的属性“max-stale”和“min-fresh”。

  “max-stale”的意思是如果代理上的缓存过期了也可以接受,但不能过期太多,超过 x 秒也会不要。“min-fresh”的意思是缓存必须有效,而且必须在 x 秒后依然有效。

  有的时候客户端还会发出一个特别的“only-if-cached”属性,表示只接受代理缓存的数据,不接受源服务器的响应。如果代理上没有缓存或者缓存过期,就应该给客户端返回一个 504(Gateway Timeout)。

  我们还是来看张图巩固下、串联一下这些知识:

  这张图就是完整的客户端设置缓存约束的判定流程,大家一定要对比着有代理和没代理有啥区别来对照着学习。

三、小结

  代理服务器可能会在响应报文中加入X-Cache、X-Hit等自定义的头字段,标识缓存是否命中和命中率,方便观察缓存代理的工作情况。

  另外,大家还记得Vary这个头字段么,我们在之前的章节中学到过,它是内容协商后的结果,相当于报文的一个版本标记,缓存代理必须要存储这些不同的版本,当再收到相同的请求时,代理就会读取缓存里的Vary,对比请求头里的字段判断是否一致,是否可以返回缓存的数据。

  还有一个“Purge”问题,也就是“缓存清理”,他对于代理也是非常重要的功能,比如:过期的数据、版本老旧、缓存危险数据等等。通常情况下,会使用一个自定义的PURGE方法,来删除对应连接的缓存数据。

  好啦~到这里,我们学完了缓存代理的相关头字段,其实并不怎么复杂,只是在原有的缓存的头字段的基础上,加上了一些源服务器和客户端设置的头字段属性,让我们得控制缓存的细粒度更精细一些。

  最后,我再次强调,大家要对比着和缓存那一章节来看图学习。

  有关于HTTP/1.1的内容基本上就告一段落了。下一篇我们一起去领略一下HTTP/2的风采。

真正“搞”懂HTTP协议12之缓存代理的更多相关文章

  1. 搞懂分布式技术12:分布式ID生成方案

    搞懂分布式技术12:分布式ID生成方案 ## 转自: 58沈剑 架构师之路 2017-06-25 一.需求缘起 几乎所有的业务系统,都有生成一个唯一记录标识的需求,例如: 消息标识:message-i ...

  2. 真正“搞”懂HTTP协议02之空间穿梭

    时隔四年,这个系列鸽了四年,我终于觉得我可以按照自己的思路和想法把这个系列完整的表达出来了. 想起四年前,那时候还是2018年的六月份,那时候我还工作不到两年,那时候我翻译了RFC2616的部分内容, ...

  3. 真正“搞”懂http协议01—背景故事

    去年读了<图解HTTP>.<图解TCP/IP>以及<图解网络硬件>但是读了之后并没有什么深刻的印象,只是有了一层模糊的脉络,刚好最近又接触了一些有关http的相关内 ...

  4. 真正“搞”懂HTTP协议03之时间穿梭

    上一篇我们简单的介绍了一下DoD模型和OSI模型,还着重的讲解了TCP的三次握手和四次挥手,让我们在空间层面,稍稍宏观的了解了HTTP所依赖的底层模型,那么这一篇,我们来追溯一下HTTP的历史,看一看 ...

  5. 搞懂Redis协议RESP

    RESP (REdis Serialization Protocal) Redis客户端和服务端之间通信的协议.它很简单,建立在TCP协议上,提供简单.高性能.可读性强的数据序列化的规范和语义. 5种 ...

  6. 搞懂分布式技术4:ZAB协议概述与选主流程详解

    搞懂分布式技术4:ZAB协议概述与选主流程详解 ZAB协议 ZAB(Zookeeper Atomic Broadcast)协议是专门为zookeeper实现分布式协调功能而设计.zookeeper主要 ...

  7. 搞懂分布式技术2:分布式一致性协议与Paxos,Raft算法

    搞懂分布式技术2:分布式一致性协议与Paxos,Raft算法 2PC 由于BASE理论需要在一致性和可用性方面做出权衡,因此涌现了很多关于一致性的算法和协议.其中比较著名的有二阶提交协议(2 Phas ...

  8. [转帖]USB-C和Thunderbolt 3连接线你搞懂了吗?---没搞明白.

    USB-C和Thunderbolt 3连接线你搞懂了吗? 2018年11月25日 07:30 6318 次阅读 稿源:威锋网 3 条评论 按照计算行业的风潮,USB Type-C 将会是下一代主流的接 ...

  9. 搞懂分布式技术28:微服务(Microservice)那点事

    搞懂分布式技术28:微服务(Microservice)那点事 微服务(Microservice)那点事 肥侠 2016-01-13 09:46:53 浏览58371 评论15 分布式系统与计算 微服务 ...

  10. 搞懂分布式技术11:分布式session解决方案与一致性hash

    搞懂分布式技术11:分布式session解决方案与一致性hash session一致性架构设计实践 原创: 58沈剑 架构师之路 2017-05-18 一.缘起 什么是session? 服务器为每个用 ...

随机推荐

  1. 聊聊FASTER和进程内混合缓存

    最近有一个朋友问我这样一个问题: 我的业务依赖一些数据,因为数据库访问慢,我把它放在Redis里面,不过还是太慢了,有什么其它的方案吗? 其实这个问题比较简单的是吧?Redis其实属于网络存储,我对照 ...

  2. Kubernetes_Deployment全解析(无状态的Pod)

    前言 一.创建Deployment 1.1 创建Deployment apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deploy ...

  3. C++编程笔记(智能指针学习)

    目录 scoped_ptr unique_ptr shared_ptr 智能指针简单应用 智能指针简单应用 scoped_ptr 拷贝构造和 =赋值操作均为私有,不允许 内部重载了解引用(*)操作符和 ...

  4. Java面试多线程/JUC等知识

    2021年6月30日完成此部分内容整理

  5. 【大数据面试】【数仓项目】分层:ODS层、DWD层、DWS层、ADS层构成、操作

    一.ODS层 1.保持数据原貌,不做任何修改 2.数据压缩:LZO压缩,减少磁盘空间 3.创建的是分区表:可以防止后续的全表扫描 包括 用户行为:string line dt    ods_start ...

  6. 详记apache-poi的使用,将word,excel,ppt转换为html

    原文:https://blog.51cto.com/yunyaniu/5210961 java:Java的jar包之POI的简介.安装.使用方法(基于POI的转换-Word.Excel.Ppt等转ht ...

  7. uniapp onLoad里面拿不到reject的参数

    在onLoad中直接调用自己用promise封装的请求 reject居然会收不到参数.. onLoad(){ this.$fetch(xxxx) .catch(err=>{ }) // 这里获取 ...

  8. vulnhub靶场渗透实战13-driftingblues3

    ​靶机下载地址:https://download.vulnhub.com/driftingblues/driftingblues3.ova vbox导入,网络模式桥接,靶机模式为简单. 一:信息收集 ...

  9. Linux 系统用户文件缺失造成“bash-4.2$”错误的解决办法

    一.问题出现的原因 造成这个现象的原因是因为用户文件夹下的bash_logout.bash_profile和bashrc这三个隐藏文件缺失 二.问题复现 现在删除这三个文件 此时问题出现了 三.问题解 ...

  10. 定制.NET 6.0的Middleware中间件

    大家好,我是张飞洪,感谢您的阅读,我会不定期和你分享学习心得,希望我的文章能成为你成长路上的垫脚石,让我们一起精进. 在本文中,我们将学习中间件,以及如何使用它进一步定制应用程序.我们将快速学习中间件 ...