Http 缓存动态内容的反向代理

Http 缓存动态内容的反向代理,http,caching,reverse-proxy,Http,Caching,Reverse Proxy,我想继续问,但后来我发现这可能是一个太奇怪的请求,需要先澄清一下 我的观点是: 每个响应都包含一个etag 这是内容的散列 并且是全局唯一的(具有足够的概率) 内容(大部分)是动态的,并且可能随时更改(expires和max age标题在这里是无用的) 内容部分依赖于用户,如权限所示(权限本身有时会更改) 基本上,代理应该包含一个将etag映射到响应内容的缓存。etag从服务器获取,在最常见的情况下,服务器根本不处理响应内容 它应该是这样的:代理总是向服务器发送一个请求,然后 1服务器

我想继续问,但后来我发现这可能是一个太奇怪的请求,需要先澄清一下

我的观点是:

  • 每个响应都包含一个
    etag
    • 这是内容的散列
    • 并且是全局唯一的(具有足够的概率)
  • 内容(大部分)是动态的,并且可能随时更改(
    expires
    max age
    标题在这里是无用的)
  • 内容部分依赖于用户,如权限所示(权限本身有时会更改)
基本上,代理应该包含一个将
etag
映射到响应内容的缓存。
etag
从服务器获取,在最常见的情况下,服务器根本不处理响应内容

它应该是这样的:代理总是向服务器发送一个请求,然后

  • 1服务器只返回
    etag
    ,代理根据它进行查找,然后
    • 1.1缓存命中时,
      • 它从缓存中读取响应数据
      • 并向客户端发送响应
    • 1.2缓存未命中,
      • 它会再次询问服务器,然后
      • 服务器返回带有内容和
        etag
        的响应
      • 代理将其存储在缓存中
      • 并向客户端发送响应
  • 2或服务器返回带有内容的响应和
    etag
    • 代理将数据存储在其缓存中
    • 并向客户端发送响应
为简单起见,我省略了
if none match
头的处理,这一点非常明显

我这样做的原因是,最常见的案例1.1可以在服务器中非常有效地实现(使用其缓存映射请求到
etag
;内容不会缓存在服务器中),因此大多数请求都可以在服务器不处理响应内容的情况下处理。这应该比首先从侧缓存获取内容,然后为其提供服务要好

在案例1.2中,有两个对服务器的请求,这听起来很糟糕,但并不比服务器请求侧缓存并得到未命中更糟糕

Q1:我想知道,如何将第一个请求映射到HTTP。在案例1中,它就像一个头部请求。在案例2中,它就像GET。这两者之间的决定取决于服务器:如果它可以在不计算内容的情况下提供
etag
,则为案例1,否则为案例2

Q2:是否有反向代理执行类似操作?我读过关于nginx、HAProxy和Varnish的文章,但事实似乎并非如此。这让我想到了第三个问题:这是个坏主意吗?为什么?

Q4:如果不是,那么哪个现有代理最容易适应

一个例子 来自用户
U1
的GET请求,如
/catalog/123/item/456
,被提供了一些内容
C1
etag:777777
。代理存储在键
777777
下的
C1

现在同样的请求来自用户
U2
。代理将其转发,服务器仅返回
etag:777777
,代理很幸运,在其缓存中找到了
C1
(case1.1),并将其发送到
U2
。在本例中,客户机和代理都不知道预期结果


有趣的是,服务器如何在不计算答案的情况下知道
etag
。例如,它可以有一条规则,规定此表单的请求为所有用户返回相同的结果,前提是允许给定用户查看该结果。因此,当来自
U1
的请求到来时,它计算
C1
,并将
etag
存储在
/catalog/123/item/456
键下。当相同的请求来自
U2
时,它只是验证
U2
是否允许查看结果。

Q1:这是一个GET请求。服务器可以在没有正文的情况下回答“304未修改”

Q2:(带有一些附加模块的nginx)可以做到这一点,但您需要自己实现一些逻辑(请参阅下面更详细的描述)

Q3:考虑到你问题中的信息,这听起来是个合理的想法。只是一些值得思考的东西:

  • 您还可以将页面拆分为用户特定部分和通用部分,这些部分可以单独缓存

  • 您不应该期望缓存永远保存计算出的响应。因此,如果服务器返回带有
    etag:777777
    (根据您的示例)的
    304 not modified
    ,但缓存不知道,您应该可以选择强制重新构建答案,例如使用另一个带有自定义头的请求
    X-force-recreaculate:true

  • 这不完全是问题的一部分,但是:确保设置适当的
    Vary
    标题以防止缓存问题

  • 如果这只是关于权限的,您还可以在签名cookie中使用权限信息。缓存可以在不询问服务器的情况下从cookie获得权限,并且由于签名,cookie是防篡改的


Q4:我会使用openresty来实现这一点,特别是在。将缓存的内容放入redis键值存储,并将
etag
作为键。您需要在Lua中编写查找逻辑,但它不应该超过几行。

您描述的是HTTP中的条件GET。客户端使用一些特定的HTTP头执行GET,告诉服务器只有在特定条件匹配或不匹配时才回复内容,例如基于有效期或ETag的条件。@PatrickMevzek那么我的描述就令人困惑了。我知道有条件的GET,这很重要