【问题标题】:What's the most efficient ETag generation given the following possibilities?考虑到以下可能性,最有效的 ETag 生成是什么?
【发布时间】:2013-02-02 00:43:22
【问题描述】:

我最近在 Go 中一直在玩弄缓存 http 响应,我正在尝试找出最有效的方法来生成正确的 ETag。

现在我有以下可用数据:

  1. 当我渲染模板时要渲染的模板的名称。
  2. 动态数据被传递到模板或 json 响应的响应中。
  3. 整个响应正文。
  4. 身体的长度。
  5. 我可能遗漏了什么?

经过一番思考,我得出的结论是,如果我将模板的名称和正在生成的动态数据结合起来,理论上这应该以最少的开销创建一个合法的唯一 ETag,但我不知道这有多讨厌如果我开始想要返回 30kb 的 html 值的数据库结果,将会得到。

我正在使用 Go 的 stdlib 中的 crc32 例程从我传递给它的数据生成 ETag。

有没有更好的方法来生成 ETag,甚至缓存动态数据?我不能只监控文件的最后修改时间,因为数据可以在不改变文件的情况下改变。

【问题讨论】:

    标签: http caching http-headers go


    【解决方案1】:

    一般来说,您希望使用计算成本低的东西作为 ETag。这样做的原因是,如果客户端发送一个条件请求(例如通过If-None-Match HTTP 请求头),您可以决定是否适合发送304 Not Modified 响应,而无需对页面进行所有处理。

    例如,如果您有某种页面内容的修订标识符,那么这可能是一个很好的 ETag。

    如果您需要完成所有必要的工作来渲染页面以生成 ETag,那么您也可以只使用渲染页面内容的哈希值,或者根本不使用 ETag。

    【讨论】:

    • 是的,我没有修订 ID,我不想让 URL 与校验和或其他一些元数据变得复杂。这就是为什么我试图找出生成它的最佳方法。绝对愿意接受建议。
    • 好吧,如果您希望充分利用 HTTP 缓存,那么值得研究一下您是否可以构建数据来促进它。如果您无法使您的数据适合该模型(例如搜索结果页面),那么可能不值得提供 ETag。
    • 大型网站如何处理这个问题?对于搜索结果,他们只是在每个响应中发送回 50kb 的 html,并使用动态呈现的新服务器模板,还是约 30kb 的 json?缓存每一个搜索查询,然后根据模板名称和 url 查询字符串的组合在缓存映射中进行查找似乎不太合理。
    • 您到底想通过 ETags 实现什么?如果您不能廉价地验证您生成的 ETag,那么可能不值得费心。我提到搜索结果是一个难以为其生成 etag 的数据示例,并且由于其高波动性(例如 Google 搜索结果不提供 ETag)而可能不值得打扰。
    • 尝试减少服务器上的传出带宽,并在某些情况下改善用户的响应时间。
    【解决方案2】:

    如果您正在寻找一种高效的ETag 机制并且不需要强大的加密功能,我建议您使用 CRC-32。为了帮助防止冲突,您可以结合模板名称、数据长度和 crc 等内容:

    func etag(name string, data []byte) string {
        crc := crc32.ChecksumIEEE(data)
        return fmt.Sprintf(`W/"%s-%d-%08X"`, name, len(data), crc)
    }
    

    This 会产生一个类似W/"tpl-17-3074C885" 的etag。

    【讨论】:

    • 这基本上就是我现在正在做的事情。问题是从“数据”计算 crc32 是一个严重的瓶颈,当数据大小很容易达到 25kb+ 时(从数据库返回结果等)。我也看不到使用 last-modified 的可行方法,因为模板数据可能会在不更改文件的修改时间的情况下更改。想想:搜索结果,甚至像在每个页面的顶部输出 hello [user] 这样简单的东西。
    • 输出所特有的最小的东西是什么?这就是你必须散列的内容。没有办法绕过它,CRC-32 将成为你拥有的最便宜的哈希值之一。如果相同的查询总是产生相同的输出,那么您可以改为对输入进行哈希处理(可能使用更耐碰撞的东西,如 SHA-1)。如果没有,您可能需要进行一些重组,以便您知道修改时间,并且可以走这条路。
    • 我想最小的东西是用户名,类似于 stackoverflow 它如何在每个页面的顶部显示您的用户名。如果我渲染一个服务器端模板并将用户名放入模板中,那么每个用户都会有所不同。此时整个模板结果无法缓存对吗?如果你和我都查看/foo,我们的结果是不同的,因为我们的用户名不一样。这只是一个例子。
    猜你喜欢
    • 2020-11-18
    • 2014-01-28
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-24
    相关资源
    最近更新 更多