因最近客戶端慢的問題,系統分析了下http協議緩存問題。本文主要記錄總結http緩存相關知識。javascript
訪問返回類html
> 訪問返回200 OKjava
> 訪問返回200 (from memory cache)nginx
> 訪問返回200 (from disk cache)web
> 訪問返回304 Not Modifiedchrome
頭設置類ubuntu
> Cache-Control: max-age=604800 後端
> Expires: Thu, 05 Jan 2017 12:24:24 GMT 瀏覽器
機器A做爲客戶端,IP: 10.0.0.2 chrome 版本 55.0.2883.87 m 緩存
機器B做爲服務斷, IP: 10.0.0.102 nginx 1.1.19 ubuntu 12.04
1) 修改nginx的配置文件
location / { # First attempt to serve request as file, then # as directory, then fall back to index.html try_files $uri $uri/ /index.html; # Uncomment to enable naxsi on this location # include /etc/nginx/naxsi.rules expires 7d; }
增長了expires 7d;
2) 修改index.html
<html> <head> <title>Welcome to nginx!</title> <script type="text/javascript" src="1.js"></script> </head> <body bgcolor="white" text="black"> <center><h1>Welcome to nginx!123456</h1></center> <a href="1.txt">1.txt</a> </body> </html>
增長一個引入js 1.js
增長一個超連接1.tx
上圖爲index.html請求包
上圖爲index.html響應包
上圖爲1.js請求包
上圖爲1.js響應包
這是index.html和1.js都返回200 ok的狀況
上圖爲index.html請求包
上圖爲index.html響應包,此時 回 304 Not Modified ,而且服務器僅僅是回了狀態碼,沒有將index.html數據寫回客戶端。
從整個抓包來看,沒有看到1.js的請求包,證實此時針對1.js這個文件 連http請求都沒有發。
再經過那個超連接作實驗發現和1.js同樣的結論,第一次回200 OK 第二次以後就會200 from xxx cache
cache有memory和disk之分,這個很好理解。
在已經緩存了的狀況下:
在地址欄敲回車,是回304 。 被別人引用或者點擊超連接時,回 200 form xxx cache
參考 http://guojianxiang.com/posts/2015-09-01-About_HttpStatus200_FromCache_And_304_NotModified.html 彎路2
nginx默認不支持etag, 能夠使用插件完成。
nginx做者對其解釋,參考 http://blog.csdn.net/21aspnet/article/details/6604805
「
Nginx中默認沒有添加對Etag標識.Igor Sysoev的觀點」在對靜態文件處理上看不出如何Etag好於Last-Modified標識。」
Note:
Yes, it's addition,and it's easy to add, however, I do not see howETag is better than Last-Modified for static files. -Igor Sysoev
A nice short description is here:
http://www.mnot.net/cache_docs/#WORK
」
nginx是在後臺指定expires的間隔(好比7天后超期),而後nginx會自動在http頭中轉換成max-gae的時間,和頭中Expires會變換成具體的超期時刻(不是間隔了)
參考 https://www.bokeyy.com/post/high-performance-web-sites-rule3.html
「
Max-age:在 HTTP 頭中按秒指定失效的時間,以下圖。好處是不像方法 1(expries) 同樣須要定時檢查是否過時,一旦過時就須要指定新的時間,壞處是隻有 HTTP/1.1 支持
」
分析了tomcat6 閱讀其代碼 一目瞭然
protected boolean checkIfModifiedSince(HttpServletRequest request, HttpServletResponse response, ResourceAttributes resourceAttributes) throws IOException { try { long headerValue = request.getDateHeader("If-Modified-Since"); long lastModified = resourceAttributes.getLastModified(); if (headerValue != -1) { // If an If-None-Match header has been specified, if modified since // is ignored. if ((request.getHeader("If-None-Match") == null) && (lastModified < headerValue + 1000)) { // The entity has not been modified since the date // specified by the client. This is not an error case. response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); response.setHeader("ETag", resourceAttributes.getETag()); return false; } } } catch (IllegalArgumentException illegalArgument) { return true; } return true; }
HttpServletResponse.SC_NOT_MODIFIED 就是304狀態
resourceAttributes.getLastModified(); 讀取文件上次修改時間。
有興趣的話能夠繼續分析tomcat對etag的處理。
--EOF--