使用靜態(tài)緩存提升網(wǎng)站性能的五種方法

上次寫了一篇數(shù)據(jù)庫緩存撬陵,由于快餐式的風(fēng)格,遭到了廣大讀友的吐槽网缝。上篇風(fēng)格有點“虛”巨税,我本身是一個技術(shù)控,偏向經(jīng)驗/干貨的分享粉臊,本文主要描述靜態(tài)緩存方面的一些心得及分享草添。作為系列二,有所不足之處扼仲,依舊希望大家勇于“亮磚”远寸。
說起靜態(tài)緩存技術(shù),CDN是金典代表之作屠凶。靜態(tài)緩存技術(shù)面非常廣驰后,涉及的開源技術(shù)包含apache、Lighttpd矗愧、nginx灶芝、varnish、squid等。
靜態(tài)緩存监署,一般指web類應(yīng)用中颤专,將圖片、js钠乏、css栖秕、視頻、html等靜態(tài)文件/資源通過磁盤/內(nèi)存等緩存方式晓避,提高資源響應(yīng)方式簇捍,減少服務(wù)器壓力/資源開銷的一門緩存技術(shù)。
本文中主要通過:瀏覽器緩存俏拱、磁盤緩存暑塑、內(nèi)存緩存、nginx的內(nèi)存緩存锅必、CDN五個方面圍繞靜態(tài)緩存而展開事格。

一、瀏覽器緩存

瀏覽器緩存搞隐,也稱為客戶端緩存驹愚,是靜態(tài)緩存中最常見最直接的表現(xiàn)形式,很多時候都往往被人忽略掉劣纲。
案例1:
我們經(jīng)常在nginx的配置文件中看到以下緩存配置:

location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
     expires 1d;
}
location ~ .*\.(js|css)?$
{
     expires 15d;
}

案例2:
在經(jīng)常寫jsp的時候逢捺,html標(biāo)簽中關(guān)于http頭信息也可以注意到“expires”的字樣:

<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="expires" content="60">    
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">

對于案例1和案例2中(nginx設(shè)置的expires優(yōu)先級大于代碼中設(shè)置的expires優(yōu)先級),expires是給一個資源設(shè)定一個過期時間癞季,也就是說無需去服務(wù)端驗證劫瞳,直接通過瀏覽器自身確認(rèn)是否過期即可,所以不會產(chǎn)生額外的流量绷柒。此種方法非常適合不經(jīng)常變動的資源志于。如果文件變動較頻繁,不要使用expires來緩存废睦。
比如對于常見類web網(wǎng)站來說伺绽,css樣式和js腳本基本已經(jīng)定型,所以最適合的方法是expires來緩存一些內(nèi)容到訪問者瀏覽器郊楣。

案例3:
通過chrome訪問服務(wù)器端的一張圖片憔恳,通過F12鍵打開開發(fā)者前端調(diào)試工具(如圖1):

圖1

第一次訪問瓤荔,響應(yīng)200狀態(tài)净蚤,當(dāng)?shù)诙渭昂罄m(xù)訪問的時候,變成304狀態(tài)(如圖2)输硝,客戶端已經(jīng)開始取瀏覽器緩存內(nèi)容今瀑,而不需要去服務(wù)器端獲取對應(yīng)的請求內(nèi)容,即nginx中expires參數(shù)設(shè)置已經(jīng)生效。等待客戶端緩存時間過期后橘荠,會再次請求服務(wù)器端內(nèi)容來更新本地緩存屿附。
圖2

介紹到這里,突然想起一個有意思的需求哥童。比如挺份,訪問一張靜態(tài)文件,不想客戶端緩存贮懈,需要每次都去服務(wù)器端取數(shù)據(jù)匀泊。我們可以用“l(fā)ast-modified”參數(shù)來實現(xiàn),即“l(fā)ast-modified”是根據(jù)文件更新時間來確定是否再次發(fā)送加載朵你。
Nginx核心配置如下:

location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
     add_header  Last-modified  10;
     expires 1d;
}

我們更改掉服務(wù)器傳回客戶端的“l(fā)ast-modified”文件修改時間參數(shù)的值各聘,這樣導(dǎo)致客戶端本地保存的文件時間每次跟服務(wù)器端傳回來的時間不一致,所以每次客戶端“誤認(rèn)為”服務(wù)器端有靜態(tài)文件更新抡医,所以每次都會去服務(wù)器端取“所謂的最新數(shù)據(jù)”躲因。這樣我們可以看到,不管在瀏覽器訪問多少次忌傻,返回的http狀態(tài)都是200大脉,再也找不到304狀態(tài)了。

誤區(qū):在nginx中設(shè)置expires芯勘,并不是指把靜態(tài)內(nèi)容緩存在nginx中箱靴,而是設(shè)置客戶端瀏覽器緩存的時間,這是很多人誤區(qū)所在荷愕。

二衡怀、磁盤緩存

除了存儲在客戶端的靜態(tài)緩存(瀏覽器靜態(tài))技術(shù)外,在服務(wù)器端的靜態(tài)緩存技術(shù)主要分為磁盤緩存類和內(nèi)存緩存類兩大類安疗。單純圍繞nginx的squid抛杨、varnish等一類中間件,處理靜態(tài)數(shù)據(jù)的性能十分優(yōu)秀荐类。核心是nginx基于epoll網(wǎng)絡(luò)模型怖现,而相比apache基于select網(wǎng)絡(luò)模型。所以apache的優(yōu)勢在于密計算型玉罐,穩(wěn)定性好屈嗤。而nginx偏向靜態(tài)處理,反向代理吊输,高并發(fā)饶号。比如apache+php的穩(wěn)定性比nginx+php要好,而性能是明顯nginx要優(yōu)秀許多季蚂。

以上僅單純是對磁盤中靜態(tài)數(shù)據(jù)處理的能力茫船,所謂磁盤緩存琅束,指另外的一種緩存靜態(tài)文件的技術(shù)。以nginx配置為例:

#levels設(shè)置目錄層次 
#keys_zone設(shè)置緩存名字和共享內(nèi)存大小 
#inactive在指定時間內(nèi)沒人訪問則被刪除在這里是1天 
#max_size最大緩存空間
proxy_cache_path /alidata/www/default/cache_dir/ levels=1:2  keys_zone=cache_one:200m inactive=1d max_size=30g;

server {
    listen       82;
    server_name  _;
    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|html)$
    {
        proxy_cache cache_one;                    # keys_zone后的內(nèi)容對應(yīng)
        proxy_cache_valid  200 304 301 302 10d;   #哪些狀態(tài)緩存多長時間  
        proxy_cache_valid  any 1d;                #其他的緩存多長時間  
        proxy_cache_key $host$uri$is_args$args;   #通過key來hash算谈,定義KEY的值

        proxy_pass http://10.168.247.180:81;
        proxy_set_header   Host             $host;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    }

   access_log  /alidata/nginx/logs/default-cache.log;

可以看出nginx主要通過proxy_cache來實現(xiàn)web cache涩禀,熟悉nginx的同學(xué),不難看出然眼,以上配置在location這里艾船,不僅可以實現(xiàn)靜態(tài)文件的緩存,還可以實現(xiàn)動態(tài)文件的緩存(這里放在下章節(jié)詳細(xì)介紹)高每。我們編寫個test.html測試文件丽声,然后并訪問。test.html源碼如下:

<html>
<head>
<title>test cache</title>
<meta http-equiv="expires" content="-1">  
</head>
<body>
<br>
![](eg_tulip.jpg)
</body>
</html>

我們發(fā)現(xiàn)服務(wù)器的cache目錄里面觉义,多了兩個緩存文件:

/alidata/www/default/cache_dir/c/68/b0ad5d3e7f099bfff9e4fc6a159d868c
/alidata/www/default/cache_dir/f/fa/53edc39ed253e14415a29412cfc01faf

有意思的雁社,這兩個文件里面的內(nèi)容分別為(通過less命令查看):


圖3:b0ad5d3e7f099bfff9e4fc6a159d868c
圖4:53edc39ed253e14415a29412cfc01faf

所以不難看出,nginx把html內(nèi)容和圖片二進(jìn)制全部緩存到本地磁盤上了晒骇。下次用戶再次來訪問test.html的時候霉撵,nginx直接將緩存在本地磁盤的文件返回給用戶。特別是后端如若是部署的tomcat洪囤、iis等徒坡,nginx強(qiáng)大的靜態(tài)緩存能力,有效減少了服務(wù)器壓力瘤缩。

三喇完、內(nèi)存緩存

緊接上面描述的磁盤緩存,內(nèi)存緩存顧名思義剥啤,就是把靜態(tài)文件緩存在服務(wù)器端的內(nèi)存中锦溪。所以這種緩存,如若命中緩存的話府怯,取內(nèi)存中的緩存數(shù)據(jù)返回比取磁盤中的緩存數(shù)據(jù)返回刻诊,性能要高很多。以varnish為例牺丙,varnish核心配置如下:
啟動命令:

varnishd -f default.vcl -s malloc,2G -a 0.0.0.0:80 -w 1024,51200,10 -t 3600 -T 192.168.100.2:3500

參數(shù)簡介:

-a  address:port 監(jiān)聽端口
-f  指定配置文件
-s 指定緩存類型 malloc為內(nèi)存则涯, file 文件緩存
-t 默認(rèn)TTL
-T address:port 管理端口
-w 最小線程,最大線程冲簿,超時時間

default.vcl核心配置如下:

sub vcl_fetch {
if (req.request == "GET" && req.url ~ "\.(gif|jpg|jpeg|png|bmp|swf|html)$") {
set obj.ttl = 3600s;
}
}

Varnish對.gif粟判、.jpg、.jpeg峦剔、.png等結(jié)尾的URL緩存時間設(shè)置1小時档礁。varnish設(shè)置完畢后,我們用命令行方式羊异,通過查看網(wǎng)頁頭來查看命中情況:

[root@test-varnish ~]# curl -I http://***.***.***.***/test.html  
HTTP/1.1 200 OK  
Server: Apache/2.2.27 (Unix) PHP/5.3.18 mod_perl/2.0.4 Perl/v5.10.1  
Last-Modified: Sat, 10 Jul 2016 11:25:15 GMT  
ETag: "55dh9-233f-33d23c3758dg2"  
Content-Type: text/html  
Content-Length: 23423  
Date: Fri, 18 May 2016 21:29:16 GMT  
X-Varnish: 1364285597  
Age: 0  
Via: 1.1 varnish  
Connection: keep-alive  
X-Cache: MISS from ***.***.***.***  #這里的“MISS”表示此次訪問沒有從緩存讀取
[root@test-varnish ~]# curl -I http://***.***.***.***/test.html 
HTTP/1.1 200 OK  
Server: Apache/2.2.27 (Unix) PHP/5.3.18 mod_perl/2.0.4 Perl/v5.10.1  
Last-Modified: Sat, 10 Jul 2010 11:25:15 GMT  
ETag: "55dh9-233f-33d23c3758dg2"  
Content-Type: text/html  
Content-Length: 23423
Date: Fri, 18 May 2016 21:40:23 GMT  
X-Varnish: 1364398612 1364285597  
Age: 79  
Via: 1.1 varnish  
Connection: keep-alive  
X-Cache: HIT from ***.***.***.***     #由“HIT”可知事秀,第二次訪問此頁面時,從緩存中讀取內(nèi)容野舶,也就是緩存命中

最后易迹,我們可以通過varnishadm命令來清理緩存,也可以通過varnishstat命令來查看varnish系統(tǒng)緩存狀態(tài)平道。

四睹欲、Nginx的內(nèi)存緩存

以上主要以Varnish為例,介紹了內(nèi)存緩存靜態(tài)資源的方法一屋。其實nginx也有內(nèi)存緩存窘疮,相比squid、varnish而言冀墨,nginx的內(nèi)存緩存需要通過編碼實現(xiàn)闸衫。如下配置:

location /images/ {
                set $memcached_key $request_uri;
                add_header X-mem-key  $memcached_key;
                memcached_pass  127.0.0.1:11211;
                default_type text/html;
                error_page 404 502 504 = @app;
}

memcached_pass指定服務(wù)器地址,使用變量$memcache_key為key查詢值诽嘉,去memcache查詢對應(yīng)value值蔚出。

如我們訪問:http://.../image/test.jpg ,則nginx去memcache中查詢key為“test.jpg”的value值并返回。如果沒有相應(yīng)的值虫腋,則返回error_page 404骄酗。介紹到這里,關(guān)鍵在于存儲在memcache中的靜態(tài)文件悦冀,需要通過代碼寫入memcache中趋翻。怎么樣通過php/java等代碼把靜態(tài)資源的數(shù)據(jù)寫入memcache中,關(guān)于這塊的示例就不再過多介紹盒蟆。

Nginx的內(nèi)存緩存因為需要通過編碼實現(xiàn)踏烙,所以靈活性特別高。這塊可以結(jié)合自身業(yè)務(wù)系統(tǒng)的特點历等,讓靜態(tài)緩存的靈活性和效率都能得到保障宙帝。可能唯一的缺陷就是募闲,通過編碼實現(xiàn)的方式步脓,給我們維護(hù)管理帶來了負(fù)擔(dān)。在之前我曾參與的一個電商系統(tǒng)浩螺,就是把客戶的訂單照片通過php代碼寫入memcache靴患,客戶訪問取圖的時候,從memcache中獲取要出,速度效率特別高鸳君。Nginx作為一款在七層無所不能且輕量級高性能的中間件,能夠直接去memcache中取數(shù)據(jù)患蹂,來實現(xiàn)靜態(tài)緩存的效果或颊,這塊相應(yīng)的功能是其他軟件無法相媲美的砸紊。

五、CDN

說起CDN囱挑,大家都不陌生醉顽,它是靜態(tài)緩存加速最典型的代表。CDN技術(shù)并不是一門新的技術(shù)平挑,它是基于傳統(tǒng)nginx游添、squid、varnish等web 緩存技術(shù)通熄,結(jié)合DNS智能解析的靜態(tài)緩存加速技術(shù)唆涝。值得注意的是,他對動態(tài)鏈接訪問并沒有加速效果唇辨。架構(gòu)原理圖如下圖5:


圖5

所以CDN的靜態(tài)緩存技術(shù)核心主要在于兩點:
節(jié)點緩存:對需要加速的網(wǎng)站應(yīng)用廊酣,相應(yīng)的靜態(tài)資源通過內(nèi)存緩存+磁盤緩存的方式緩存在服務(wù)器端。

精準(zhǔn)調(diào)度:對訪問的用戶ip進(jìn)行智能解析調(diào)度赏枚,實現(xiàn)就近緩存節(jié)點訪問啰扛。比如以上圖例中,北京用戶訪問www.a.com嗡贺。通過dns解析的時候隐解,分析用戶ip,發(fā)現(xiàn)是北京用戶诫睬。則dns返回對應(yīng)北京緩存節(jié)點的ip地址給到用戶煞茫,則用戶www.a.com,則默認(rèn)訪問北京服務(wù)器上面的緩存數(shù)據(jù)摄凡,實現(xiàn)就近訪問的策略续徽,大大提升了訪問速度。

我為自己帶鹽亲澡,原創(chuàng)作者:喬銳杰

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末钦扭,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子床绪,更是在濱河造成了極大的恐慌客情,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件癞己,死亡現(xiàn)場離奇詭異膀斋,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)痹雅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門仰担,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人绩社,你說我怎么就攤上這事摔蓝÷该纾” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵贮尉,是天一觀的道長拌滋。 經(jīng)常有香客問我,道長绘盟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任悯仙,我火速辦了婚禮龄毡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘锡垄。我一直安慰自己沦零,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布货岭。 她就那樣靜靜地躺著路操,像睡著了一般。 火紅的嫁衣襯著肌膚如雪千贯。 梳的紋絲不亂的頭發(fā)上屯仗,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機(jī)與錄音搔谴,去河邊找鬼魁袜。 笑死,一個胖子當(dāng)著我的面吹牛敦第,可吹牛的內(nèi)容都是我干的峰弹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼芜果,長吁一口氣:“原來是場噩夢啊……” “哼鞠呈!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起右钾,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蚁吝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后舀射,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灭将,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年后控,在試婚紗的時候發(fā)現(xiàn)自己被綠了庙曙。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡浩淘,死狀恐怖捌朴,靈堂內(nèi)的尸體忽然破棺而出吴攒,到底是詐尸還是另有隱情,我是刑警寧澤砂蔽,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布洼怔,位于F島的核電站,受9級特大地震影響左驾,放射性物質(zhì)發(fā)生泄漏镣隶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一诡右、第九天 我趴在偏房一處隱蔽的房頂上張望安岂。 院中可真熱鬧,春花似錦帆吻、人聲如沸域那。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽次员。三九已至,卻和暖如春王带,著一層夾襖步出監(jiān)牢的瞬間淑蔚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工愕撰, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留束倍,地道東北人。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓盟戏,卻偏偏與公主長得像绪妹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子柿究,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 【轉(zhuǎn)】緩存在分布式系統(tǒng)中的應(yīng)用 緩存在分布式系統(tǒng)中的應(yīng)用 摘要 緩存是分布式系統(tǒng)中的重要組件邮旷,主要解決高并發(fā),大數(shù)...
    武漢蘇乞兒閱讀 862評論 0 10
  • 一蝇摸、MemCache簡介 session MemCache是一個自由婶肩、源碼開放、高性能貌夕、分布式的分布式內(nèi)存對象緩存...
    李偉銘MIng閱讀 3,810評論 2 13
  • 緩存在分布式系統(tǒng)中的應(yīng)用 摘要 緩存是分布式系統(tǒng)中的重要組件律歼,主要解決高并發(fā),大數(shù)據(jù)場景下啡专,熱點數(shù)據(jù)訪問的性能問題...
    garyond閱讀 1,617評論 0 12
  • 緩存的基礎(chǔ)知識 1险毁、程序本身具有局部性 時間局部性過去訪問到的數(shù)據(jù),也有可能被兩次訪問 空間局部性一個數(shù)據(jù)被訪問到...
    魏鎮(zhèn)坪閱讀 2,030評論 1 3
  • 第一章 Nginx簡介 Nginx是什么 沒有聽過Nginx?那么一定聽過它的“同行”Apache吧畔况!Ngi...
    JokerW閱讀 32,679評論 24 1,002