你知道 http 响应头中的 ETag 是如何生成的吗

关于 etag 的生成须要知足几个条件html

  1. 当文件不会更改时,etag 值保持不变。因此不能单纯使用 inode
  2. 便于计算,不会特别耗 CPU。这样子 hash 不是特别合适
  3. 便于横向扩展,多个 node 上生成的 etag 值一致。这样子 inode 就排除了

关于服务器中 etag 如何生成能够参考 HTTP: Generating ETag Header前端

那么在 nginx 中的 etag 是如何生成的?node

nginx 中 ETag 的生成

我在网上找到一些资料与源代码了解到了 etag 的计算方法。由 python 伪代码表示计算方法以下python

etag = '{:x}-{:x}'.format(header.last_modified, header.content_lenth)复制代码

源码: ngx_http_core_modules.cnginx

etag->value.len = ngx_sprintf(etag->value.data, "\"%xT-%xO\"",
                                  r->headers_out.last_modified_time,
                                  r->headers_out.content_length_n)
                      - etag->value.data;复制代码

总结:nginxetag 由响应头的 Last-ModifiedContent-Length 表示为十六进制组合而成。git

随手在个人k8s集群里找个 nginx 服务测试一下github

$ curl --head 10.97.109.49
HTTP/1.1 200 OK
Server: nginx/1.16.0
Date: Tue, 10 Dec 2019 06:45:24 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 23 Apr 2019 10:18:21 GMT
Connection: keep-alive
ETag: "5cbee66d-264"
Accept-Ranges: bytes复制代码

etag 计算 Last-ModifiedContent-Length,使用 js 计算以下,结果相符面试

> new Date(parseInt('5cbee66d', 16) * 1000).toJSON()
"2019-04-23T10:18:21.000Z"
> parseInt('264', 16)
612复制代码

Last-Modified,ETag 与协商缓存

咱们知道协商缓存有两种方式c#

  • Last-Modified/if-Modified-Since
  • ETag/If-None-Match

既然在 nginxETagLast-ModifiedContent-Length 组成,那它便算是一个增强版的 Last-Modified 了,那增强在什么地方呢?前端工程化

Last-Modified 是由一个 unix timestamp 表示,则意味着它只能做用于秒级的改变

那下一个问题:若是 http 响应头中 ETag 值改变了,是否意味着文件内容必定已经更改


我是山月,你能够添加我微信 shanyue94 与我交流

若是你对全栈面试,前端工程化,graphql,devops,我的服务器运维以及微服务感兴趣的话,能够关注我

相关文章
相关标签/搜索