知乎專欄 | 多維度架構 | 微信號 netkiller-ebook | QQ群:128659835 請註明“讀者” |
首先要說明,很多緩存技術依賴靜態化。下面展示了緩存可能出現的位置。
用戶user -> 瀏覽器緩存 IE/Firefox Cache -> 逆向代理緩存 Reverse proxy Cache -> WEB伺服器緩存 Apache cache -> 應用程序緩存 php cache -> 資料庫緩存 database cache
當然交換機,網絡適配器,硬碟上也有Cache 但這不是我們要討論的範圍。
緩存存儲方式主要是內存和檔案兩種,後者是存於硬碟中。
網站上使用的緩存主要包括五種:
瀏覽器 緩存
逆向代理/CDN緩存
WEB伺服器緩存
應用程序緩存
資料庫緩存
將上面的緩存合理地,有選擇性的使用可大大提高網站的訪問能力。
總之,想讓你的網站更快,更多並發,答案是cache,cache 再 cache
通過 Cache-Control 設置頁面緩存時間
max-age max-age 格式寫為:max-age=n,n是以秒為單位, 這個值是告知客戶端GMT + N 後頁面過期,緩存伺服器在s-maxage值為空的時候也會使用這個參數的值。 s-maxage s-maxage的格式跟max-age一樣,只不過他是給緩存伺服器使用的。 must-revalidate 這個參數用來告知客戶端和緩存伺服器,在GET請求的時候必須與源伺服器驗證實體是否為最新版本。 Cache-Control:max-age=1200,s-maxage=3600
Last-Modified 這個參數提供了實體最近一次被修改的時間。這個名字起得不錯,當實體被修改了之後,這個參數也就會被修改.
ETag
ETag ETag是根據內容生成的一段hash字元串,採用信息摘要算法,保證每一個頁面有一個唯一字串。
expires
expires 是HTTP 1.0 中定義的,已經不能滿足用戶的需要在 HTTP 1.1 加入了max-age,建議使用 max-age替代expires
指令 含義 public 可以在任何地方緩存 private 只能被瀏覽器緩存 no-cache 不能在任何地方緩存 must-revalidate 緩存必須檢查更新版本 proxy-revalidate 代理緩存必須檢查更新版本 max-age 內容能夠被緩存的時期,以秒錶示 s-maxage 覆蓋共享緩存的max-age設置
在Squid, Varnish, Apache, Lighttpd, Nginx 中都可是實現HTTP Cache-Control推送,每次修改都需要重新加載,不太靈活。
ExpiresActive On ExpiresByType image/gif "access plus 1 month" ExpiresByType image/png "access plus 1 month" ExpiresByType image/jpeg "access plus 1 month" ExpiresByType text/css "access plus 1 month" ExpiresByType text/javascript "access plus 1 month" ExpiresByType application/x-javascript "access plus 1 month" ExpiresByType application/x-shockwave-flash "access plus 1 month" server.modules = ( ... "mod_expire", ... ) $HTTP["url"] =~ "^/images/" { expire.url = ( "" => "access 30 days" ) }
我喜歡自己控制TTL時間,且每個頁面單獨設置,可以隨時調整設置。
在MVC框架中每個控製器下的方法都可以單獨操作Cache
Class blog extend Controller{ blog(){ header('Cache-Control: max-age=28800'); } list(){ header('Cache-Control: max-age=3600'); } details(){ header('Cache-Control: max-age=160'); } }
你還可以封裝到Controller中
Class blog extend Controller{ blog(){ this->cache('28800'); } list(){ this->cache('3600'); } details(){ this->cache('160'); } }
首先做一個Rewrite讓程序接管所有圖片請求
url.rewrite = ( "^/(.+)" => "/index.php/$1" )
然後程序通過PATHINFO取出圖片URL
http://images.example.com/your/dir/test.jpg => http://images.example.com/index.php/your/dir/test.jpg
程序取出 /your/dir/test.jpg 設置 Content-type 並輸出二進制流
詳細參考
<?php // Test image. $images = '/test/foo.png'; $headers = apache_request_headers(); if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == filemtime($images))) { header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($images)).' GMT', true, 304); } else { header('Content-Type: image/png'); print file_get_contents($fn); if (file_exists($images)) { header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($images)).' GMT', true, 200); header("Cache-Control: max-age=3600, must-revalidate"); header('Content-Length: '.filesize($images)); header('Content-type: ' .mime_content_type($images)); flush(); readfile($images); exit; } }
javascript 檔案也可以使用類似方法處理
private function js($file){ if (file_exists($file)) { header("Cache-Control: max-age=3600, must-revalidate"); header('Content-type: text/javascript'); flush(); readfile($file); exit; } }
只要向瀏覽器輸出過期時間HTTP協議頭,不論是html還是動態腳本,都能被緩存。
HTML META
<meta http-equive="Expires" content=" Mon, 10 Jan 2000 00:00:00 GMT"/> <meta http-equive="Cache-Control" content="max-age=300"/> <meta http-equive="Cache-Control" content="no-cache"/>
動態腳本
Expires: Mon, 10 Jan 2000 00:00:00 GMT Cache-Control: max-age=300 Cache-Control: no-cache header("Expires: " .gmdate ("D, d M Y H:i:s", time() + 3600 * 24 * 7). " GMT"); header("Cache-Control: max-age=300"); header("Cache-Control: no-cache");
很多web server都提供 Expires 模組
提示 | |
---|---|
有些瀏覽器可能不支持。 |
If-Modified-Since 小於 Last-Modified 返回 200
neo@neo-OptiPlex-780:/tmp$ curl -I http://www.163.com/ HTTP/1.1 200 OK Server: nginx Content-Type: text/html; charset=GBK Transfer-Encoding: chunked Vary: Accept-Encoding Expires: Mon, 16 May 2011 08:12:05 GMT Cache-Control: max-age=80 Vary: User-Agent Vary: Accept Age: 38 X-Via: 1.1 ls100:8106 (Cdn Cache Server V2.0), 1.1 lydx156:8106 (Cdn Cache Server V2.0) Connection: keep-alive Date: Mon, 16 May 2011 08:11:23 GMT
If-Modified-Since 大於 Last-Modified 返回 304
neo@neo-OptiPlex-780:/tmp$ curl -H "If-Modified-Since: Fri, 12 May 2012 18:53:33 GMT" -I http://www.163.com/ HTTP/1.0 304 Not Modified Content-Type: text/html; charset=GBK Cache-Control: max-age=80 Age: 41 X-Via: 1.0 ls119:80 (Cdn Cache Server V2.0), 1.0 lydx154:8106 (Cdn Cache Server V2.0) Connection: keep-alive Date: Mon, 16 May 2011 08:11:14 GMT Expires: Mon, 16 May 2011 08:11:14 GMT
neo@neo-OptiPlex-780:/tmp$ curl -I http://images.example.com/test/test.html HTTP/1.1 200 OK Cache-Control: s-maxage=7200, max-age=900 Expires: Mon, 16 May 2011 09:48:45 GMT Content-Type: text/html Accept-Ranges: bytes ETag: "1984705864" Last-Modified: Mon, 16 May 2011 09:01:07 GMT Content-Length: 22 Date: Mon, 16 May 2011 09:33:45 GMT Server: lighttpd/1.4.26
neo@neo-OptiPlex-780:/tmp$ curl -H 'If-None-Match: "1984705864"' -I http://images.example.com/test/test.html HTTP/1.1 304 Not Modified Cache-Control: s-maxage=7200, max-age=900 Expires: Mon, 16 May 2011 09:48:32 GMT Content-Type: text/html Accept-Ranges: bytes ETag: "1984705864" Last-Modified: Mon, 16 May 2011 09:01:07 GMT Date: Mon, 16 May 2011 09:33:32 GMT Server: lighttpd/1.4.26
具有代表性的逆向代理伺服器:
Squid
Nginx
Varnish
Apache cache module
其它逆向代理伺服器
一些提供cache的硬件設備
最近幾年出現了的 China Cache 服務商,也稱CDN
很多CDN廠商使用Squid 二次開發做為CDN節點,通過全球負載均衡使用分發
這些CDN廠商主要做了一下二次開發
logs 日誌集中
流量限制
push,pull操作
url 刷新
s-maxage 與 max-age用法類似,s-maxage針對代理伺服器緩存。同樣適用於CDN
s-maxage 與 max-age 組合使用可以提高CDN性能
與CDN有關的開發工作
CDN 內容更新,一般廠商會提供一個SOAP介面,你可以通過介面刷新你的內容。但介面有限制,不能隨意使用,一般是多少秒可以刷新一次,或者一天可以刷新幾次
方向代理一般都支持PURGE協議,Squid,Varnish等等向管理連接埠發送 PURGE 即可是使用頁面刷新
PURGE http://netkiller.github.net/index.html
有些方向代理如:Varnish 可以使用正則表達式
同時這些代理伺服器都承受管理命令
squid: squidclient
varnish: varnishadm
例如這樣的URL
http://images.example.com/logo.gif http://images.example.com/product.jpg
我們可以通過Rewrite或PATHINFO等技術做為靜態化。例如首次版本
http://images.example.com/logo.1.gif => logo.gif http://images.example.com/product.1.jpg => product.jpg
原圖發生變化後,版本遞增
http://images.example.com/logo.2.gif => logo.gif http://images.example.com/product.2.jpg => product.jpg
就的URL將丟棄
http://images.example.com/logo.1.gif http://images.example.com/product.1.jpg
CDN 就回源去下面的URL,並且取到的是新圖
http://images.example.com/logo.2.gif http://images.example.com/product.2.jpg
F5 Big-IP, Array 等設備都提供硬件加速,其原理與squid, apache提供的功能大同小異
其中Array 頁面壓縮採用硬件壓縮卡實現,SSL加速也採用硬件實現
在這個領域百花齊放,相信你一定能找到適合你的。這些cache會為你提供一些api,來訪問它。
代表性的 memcached 據我所是sina廣泛使用,騰訊也曾經使用過後來開發了TC(Tencent Cache),台灣雅虎則使用APC Cache。
另外模板引擎也有自己的緩存系統