首页 > 解决方案 > Cache-Control 请求标头是否应该影响服务器端缓存?

问题描述

A 已经看到很多关于RFC7234和 Cache-Control 标头的代理的讨论,但我不太清楚请求标头是否应该影响服务器端缓存。

下图显示了我关注的标头所在的位置(向下箭头是请求标头,向上箭头是响应标头):

      ┌────────┐
      │ Client │
      └────────┘
        ↓    ↑
      ┌────────┐
      │ Cache  │
      └────────┘
        ↓    ↑
      ┌────────┐
      │ Cache  │
      └────────┘
        ↓    ↑
      ┌────────┐
      │ Server │
      └────────┘
  ??? → ↓    ↑
    ┌─────────────┐
    │ Server-side │
    │    Cache    │
    └─────────────┘

关于 Cache-Control 和服务器端缓存之间的交互,我有很多问题(例如,应该Cache-Control: no-cache,意味着服务器应该重新验证自己的缓存?)。但绝大多数归结为以下几点:

服务器端是否应该使用请求中的 Cache-Control 和其他相关标头来获取有关其服务器端缓存的逻辑?

以下面这个小(虽然很粗糙)的 Python Flask 应用程序为例:

@app.route('/app/<id>')
def endpoint(id):
    if 'no-store' not in request.headers['Cache-Control']:
        # If 'no-store' isn't specified, try cache first
        entry = entry_cache.get(id)
        if entry is None:
            entry = service.get_entry(id)
    else:
        # Otherwise, immediately talk to the service
        entry = service.get_entry(id)
    return entry

此外,这引发了另一个问题,根据答案,可能会使上述问题变得无关紧要:

服务器端应该做什么样的缓存?什么情况下我们应该依赖 HTTP 缓存并计算每个请求的响应(除了类似的情况If-None-Match)?

就上下文而言,我倾向于开发的大多数应用程序都设计为微服务,或者作为容器或作为具有缓存的无服务器功能,这些缓存往往是对外部服务(如 Redis)的调用。没有多少浏览器调用这些 HTTP 端点;大多数客户端是业务应用程序。

更新 (2021-08-17):感谢 Kevin 的反馈!我更新了图表和一些措辞,以澄清我专门指的是请求缓存标头而不是响应标头。此外,我添加了一个非常小(而且非常粗略)的 Python Flask 应用程序来帮助说明我所指的逻辑类型。

标签: httpcaching

解决方案


HTTP 缓存规范不绑定服务器的内部缓存行为。根据定义,服务器的响应是新鲜的,无论它是如何生成的。因此,虽然中间代理使用指令为请求提供缓存响应是违反协议的no-cache,但对于服务器本身却不是这样。

也就是说,协调两种缓存当然是可能的,无论是隐式(响应碰巧设置了缓存请求标头的请求)还是显式(定义您的 API 以使用 HTTP 缓存标头进行内部行为)。所以你的 Flask 例子对我来说很有意义。也就是说,我不熟悉在缓存代理之外使用这些请求标头的站点或框架,因此您可能是这方面的开拓者。


推荐阅读