48

我一直在读一本书,我对 ETag 章节有一个特殊的问题。作者说 ETag 可能会损害性能,您必须对它们进行微调或完全禁用它们。

我已经知道什么是 ETags 并了解其中的风险,但是让 ETags 正确有那么难吗?

我刚刚创建了一个应用程序,它发送一个 ETag,其值是响应正文的 MD5 哈希值。这是一个简单的解决方案,很容易用多种语言实现。

  • 使用响应正文的 MD5 哈希作为 ETag 是否错误?如果是这样,为什么?

  • 为什么作者(他显然比我聪明许多数量级)不提出这样一个简单的解决方案?

最后一个问题很难回答,除非你是作者 :),所以我试图找出使用 MD5 哈希作为 ETag 的弱点。

4

4 回答 4

52

ETag 类似于 Last-Modified 标头。这是一种由客户端确定更改的机制。

ETag 必须是表示资源状态和特定格式的唯一值(资源可以有多种格式,每种格式都需要自己的 ETag)。在整个资源域中不是唯一的,只是在资源内。

现在,从技术上讲,与 Last-Modified 标头相比,ETag 具有“无限”分辨率。Last-Modified 仅以 1 秒的粒度更改,而 ETag 可以是亚秒级。

您可以同时实现 ETag 和 Last-Modified,或者仅实现其中一个(当然也可以不实现)。如果您的 Last-Modified 还不够,请考虑使用 ETag。

请注意,我不会为“每个”资源设置 ETag。基本上,我不会为任何不希望被缓存的东西(特别是动态内容)设置它。在这种情况下没有意义,只是浪费了工作。

编辑:我看到你的编辑,并澄清。

MD5 没问题。唯一的缺点是一直在计算 MD5。例如,在 200K PDF 文件上运行 MD5 是很昂贵的。在不期望被缓存的资源上运行 MD5 简直是浪费(即动态内容)。

诀窍很简单,无论您使用什么机制,它都应该像 Last-Modified 通常一样便宜。Last-Modified 通常是资源的一个属性,而且访问起来通常非常便宜。

ETags 应该同样便宜。如果您使用的是 MD5,并且您可以缓存/存储资源和 MD5 哈希之间的关联,那么这是一个很好的解决方案。但是,每次需要 ETag 时都重新计算 MD5,这基本上与使用 ETag 来提高整体服务器性能的想法背道而驰。

于 2010-02-18T00:53:50.317 回答
8

我们在 instela 中将 etags 用于我们的动态内容。

我们的策略是在输出结束时生成要发送的内容的 md5 散列,如果存在 if-none-match 标头,我们将标头与生成的散列进行比较。如果两个值相同,我们发送 304 代码并中断请求而不返回任何内容。

确实,我们消耗了一点 CPU 来散列内容,但最终我们节省了很多带宽。

We have a facebook newsfeed style main page which has different content for every user. As the newsfeed content changes only 3-4 time per hour, the main page refreshes are so efficient for the client side. In the mobile era I think it's better to spend a bit more cpu time than spending bandwidth. Bandwidth is still more expensive than the CPU, and it's a better experience for the client.

于 2014-12-27T08:52:07.803 回答
2

没有读过这本书,我无法谈论作者的确切担忧。

但是,ETag 的生成应该使得 ETag 仅在页面更改时生成一次。生成网页的 MD5 散列会消耗服务器的处理能力和时间;如果您有许多客户端连接,它可能会开始导致性能问题。

因此,您需要一种很好的技术,仅在必要时生成 ETag并将它们缓存在服务器上,直到相关页面发生更改。

于 2010-02-18T00:42:15.010 回答
1

我认为perceived problem使用 ETAGS 可能是您的浏览器必须为页面上的每个资源发出并解析(简单和小型)请求/响应,以检查 etag 值是否已更改服务器端。

我个人发现这些到服务器的额外小往返对于经常更改图像、css、javascript(如果浏览器的 etag 是最新的,则服务器不需要重新发送内容)是可以接受的,因为这种机制可以很容易地标记“更新”的内容。

于 2010-02-18T00:32:53.193 回答