我们在前两篇的内容中分别学习了缓存和代理,大致了解了缓存有哪些头字段,代理是如何服务于服务器和客户端的,那么把两者结合起来,代理缓存,也就是说代理服务器也可以缓存,当客户端请求数据的时候,未必一定要追溯到源服务器上,代理服务器就可以直接把缓存的数据返回给客户端。并且,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. 系统整理K8S的配置管理实战-建议收藏系列

    目录 一.ConfigMap 1.1.创建 1.1.1.from-file 1.1.2.from-env-file 1.1.3.from-literal 1.1.4.基于yaml文件创建 1.2.Po ...

  2. JS数据结构与算法-数组结构

    数组结构 几乎所有的编程语言都原生支持数组类型,因为数组是最简单的内存数据结构. 数组通常情况下用于存储一系列同一种数据类型的值. 但在JavaScript里,也可以在数组中保存不同类型的值. 但我们 ...

  3. perl reverse函数

    转载至  Perl - 列表 - reverse 操作 reverse(逆转)操作将输入的一串列表(可能是数组)按相反的顺序返回. my @arr=("Head_PMA1",&qu ...

  4. springboot中使用mybatis_plus逆向工程

    创建springboot项目,选择图片中所示依赖 mybatis-plus生成的依赖 <!-- mybatis_plus --> <dependency> <groupI ...

  5. 学习ASP.NET Core Blazor编程系列十——路由(下)

    学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应用程序(上) 学习ASP.NET Core Blazor编程系 ...

  6. vue 3.0 常用api 的简介

    vue3.0 生命周期 写法一 和vue2.x 一致 区别在于(beforeUnmount.unmount)名称不一样 写法二 在setup 中使用, 需要引用 如: import { onBefor ...

  7. Velocity模板引擎的的使用示例(入门级)

    简单说下这个引擎的两个分支(虽然语言不同调用方法大同小异): 1.Java平台下的:org.apache.velocity 2..Net平台下的:NVelocity 注:本文章不涉及到后端只说模板的使 ...

  8. C# Panel动态添加滚动条

    /// <summary> /// panel控件的事件:在向该控件添加控件时发生 /// </summary> private void panel1_ControlAdde ...

  9. 关于linux上strongswan客户端的配置

    前言 这几天回家了,想连学校的vpn, 学校vpn用的是strongswan的EAP认证(不需要证书什么的),手机上直接用软件连接就可以了,windows也是内置了这个协议,无奈我用的是linux m ...

  10. GitHub上的一个笔记相关小项目

    就是一个笔记屑小项目, C++编写,有想一起开发的私信 AlgorithWeaver/V-note (github.com) 项目名V-note QVQ