Http 響應頭中的 ETag 值是如何生成的
?關于 etag 的生成需要滿足幾個條件,至少是寬松滿足
- 當文件更改時,etag 值必須改變。
- 盡量便于計算,不會特別耗 CPU。這樣子利用摘要算法生成 (MD5, SHA128, SHA256) 需要慎重考慮,因為他們是 CPU 密集型運算
- 必須橫向擴展,分布式部署時多個服務器節(jié)點上生成的 etag 值保持一致。這樣子 inode 就排除了
以上幾個條件是理論上的成立條件,那在真正實踐中,應該如何處理?
我們來看一下 nginx 中是如何做的
nginx 中 ETag 的生成
我翻閱了 nginx 的源代碼,并翻譯成偽代碼如下:由 last_modified 與 content_length 拼接而成
可見源碼位置,并在以下貼出: ngx_http_core_modules.c
總結(jié):nginx 中 etag 由響應頭的 Last-Modified 與 Content-Length 表示為十六進制組合而成。
隨手在我的k8s集群里找個 nginx 服務測試一下
由 etag 計算 Last-Modified 與 Content-Length,使用 js 計算如下,結(jié)果相符
Nginx 中的 ETag 算法及其不足
協(xié)商緩存用來計算資源是否返回 304,我們知道協(xié)商緩存有兩種方式
- Last-Modified/if-Modified-Since
- ETag/If-None-Match
既然在 nginx 中 ETag 由 Last-Modified 和 Content-Length 組成,那它便算是一個加強版的 Last-Modified 了,那加強在什么地方呢?
Last-Modified 是由一個 unix timestamp 表示,則意味著它只能作用于秒級的改變,而 nginx 中的 ETag 添加了文件大小的附加條件
那下一個問題:如果 http 響應頭中 ETag 值改變了,是否意味著文件內(nèi)容一定已經(jīng)更改
答案:不能。
因此使用 nginx 計算 304 有一定局限性:在 1s 內(nèi)修改了文件并且保持文件大小不變。但這種情況出現(xiàn)的概率極低就是了,因此在正常情況下可以容忍一個不太完美但是高效的算法。
文章出自:??前端餐廳??,如有轉(zhuǎn)載本文請聯(lián)系前端餐廳ReTech今日頭條號。
github:https://github.com/zuopf769