【发布时间】:2018-05-05 12:10:08
【问题描述】:
我本来想在Software Recommendations上提问,但后来我发现这可能是一个太奇怪的请求,需要先澄清一下。
我的观点是:
- 每个响应都包含一个
etag- 这是内容的哈希
- 并且是全球唯一的(具有足够的概率)
- 内容(大部分)是动态的,并且可能随时更改(
expires和max-age标头在这里没有用处)。 - 内容部分取决于用户,由权限赋予(其本身有时会更改)。
基本上,代理应该包含一个将etag 映射到响应内容的缓存。 etag 是从服务器获取的,在最常见的情况下,服务器根本不处理响应内容。
应该如下所示:代理总是向服务器发送请求,然后
-
1 服务器只返回
etag并且代理根据它进行查找并-
1.1 缓存命中,
- 它从缓存中读取响应数据
- 并向客户端发送响应
-
1.2 缓存未命中,
- 它再次询问服务器,然后
- 服务器返回带有内容和
etag的响应, - 代理将其存储在其缓存中
- 并向客户端发送响应
-
1.1 缓存命中,
-
2 或者服务器返回带有内容和
etag的响应,- 代理将数据存储在其缓存中
- 并向客户端发送响应
为简单起见,我省略了if-none-match 标头的处理,这很明显。
我这样做的原因是最常见的情况1.1可以在服务器中非常有效地实现(使用它的缓存映射请求到etags;内容没有缓存在服务器中),因此大多数请求可以在没有服务器处理响应内容的情况下进行处理。这应该比首先从侧面缓存中获取内容然后提供它要好。
在案例 1.2 中,有两个请求到服务器,这听起来很糟糕,但并不比服务器请求一个侧缓存并获得未命中更糟糕。
Q1:我想知道,如何将第一个请求映射到 HTTP。在案例 1 中,它就像一个 HEAD 请求。在案例 2 中,它类似于 GET。两者之间的决定取决于服务器:如果它可以在不计算内容的情况下为etag 提供服务,则为情况 1,否则为情况 2。
Q2:是否有反向代理做这样的事情?我读过关于 nginx、HAProxy 和 Varnish 的文章,但似乎并非如此。这让我想到Q3:这是个坏主意吗?为什么?
Q4:如果不是,那么哪个现有代理最容易适应?
一个例子
来自用户 U1 的 GET 请求(如 /catalog/123/item/456)提供了一些内容 C1 和 etag: 777777。代理将 C1 存储在密钥 777777 下。
现在同样的请求来自用户U2。代理转发它,服务器只返回etag: 777777,代理很幸运,在其缓存中找到C1(案例1.1)并将其发送到U2。 在这个例子中,客户端和代理都不知道预期的结果。
有趣的部分是服务器如何在不计算答案的情况下知道etag。例如,它可以有一条规则,说明这种形式的请求为所有用户返回相同的结果,假设允许给定用户查看它。因此,当来自U1 的请求到来时,它计算C1 并将etag 存储在密钥/catalog/123/item/456 下。当同样的请求来自U2 时,它只是验证了U2 被允许查看结果。
【问题讨论】:
-
您描述的是HTTP中的条件GET。客户端使用一些特定的 HTTP 标头执行 GET,告诉服务器仅在特定条件匹配或不匹配时才回复内容,例如基于有效日期或 ETag 的条件。
-
@PatrickMevzek 然后我的描述令人困惑。我知道有条件的 GET,这是不同的。它假定发起者“猜测”响应的可能
etag(它甚至可能在if-none-match标头中发送more than one)。+++在这里,代理无需猜测即可查询服务器,服务器通常(案例 1)仅以etag响应,希望代理获得缓存命中(案例 1.1)。还有可能进行第二次查询(案例 1.2)。 -
不,它不假定客户端猜到任何东西,因为 ETag 值在设计上是不透明的。客户端发送它在缓存中的 ETag 值,与它查询的 URL 相关。
-
@PatrickMevzek “猜测”是指发送最近收到的
etag。从某种意义上说,它是“猜测”,它可能是对的,也可能是错的。 +++ 在我上面的例子中,两个客户端都没有发送etag,因为这是他们的第一次访问。代理可能已经看到很多etags,但它不知道哪个可以申请给定的请求,因为响应是特定于用户的并且它缺乏相应的逻辑。
标签: http caching reverse-proxy