若是你曾在商場買過牛奶,那麼你將會很好地理解服務端及瀏覽器端的緩存機制。javascript
若是你是一個忠實的因特網用戶,你時時刻刻都在享受緩存所帶來的好處。可是,你可能並不清楚它是在什麼時候,以何種方式施展它的「魔法」。css
從一個開發者的角度來講,緩存機制使得建立一個高性能web應用或者web服務器變得更爲容易。開發者經過運用緩存協議,就沒必要頻繁地去優化服務器以應對大量請求而可能致使的服務器崩潰。html
雖然說緩存帶來的可能只是加載頁面時,兩秒變成一秒的差別,這種影響看上去彷佛有一點...無關緊要。可是,若是你的站點想要支持大量用戶使用,那麼這點變化是必要的。java
在以前的web應用中使用了緩存策略之後,我意識到能夠用一些更爲合適的方式去解釋緩存機制,而不只僅是經過一大堆術語。我注意到這個過程和牛奶從農場到你家冰箱這段路程很相似,因此我以爲這是一個不錯的解釋方式。web
爲了更好的理解本篇文章,你須要瞭解一下一些web服務器的一些基本概念。如今咱們開始吧!windows
在咱們深刻了解緩存以前,咱們先來思考一下沒有緩存的話,互聯網會是什麼樣?想象一下,假如你生活在18世紀至19世紀的某一個農村。你擁有一個農場,那時並無可用的冷藏設備。你的農場飼養了幾頭奶牛,可是它們產的牛奶並無想象的有價值,由於很快牛奶就會變質。瀏覽器
讓咱們把思緒拉回,即使是如今,也有不少地區和文明仍然沒有製冷技術。這些地方的人們會選擇直接從奶牛的奶頭中喝到新鮮的牛奶,或者把牛奶和穀物混合併發酵,以此來保存。頗有趣不是嗎?緩存
不論如何,你確定想把自家的牛奶出售給村裏的其餘人。可是他們能喝牛奶的時間頗有限。假設你的一頭奶牛一天能產出一加侖的牛奶。可是,若是太多的人來你家裏購買牛奶,你可能不得不讓一部分人先回家,等次日再來購買。安全
同時,因爲你分發有限,你甚至不能經過養殖更多奶牛來擴大你的生意。只有村裏的其餘人才能購買你的牛奶,你受到一些明顯的限制。服務器
相應的,若是沒有緩存機制,你會受限於你的服務器的計算力。緩存就是用來加載一些靜態的資源,好比:
默認狀況下,服務器必須對每個請求作出響應。可是,一個頁面的請求可能包含四個獨立的請求——以上的四種類可能都有一個。當你想要請求一個較大的圖像文件時,服務器可能會由於全球的大量用戶(同時請求這個圖片文件)而崩潰。而後,用戶將會經歷漫長的加載時間。
理想狀況下,你但願經過存儲對常見請求的響應來緩解服務器的壓力。你的服務器沒必要處理每一個獨立請求,相反,緩存將會代替服務器當即作出響應。你固然能夠爲更多服務器買單,可是這比費用但是愈來愈可怕的。
回到咱們農場的設定中,知道如何能讓經營一家牛奶農場變得容易嗎?
一家帶有冰箱的超市!
如此一來,人們沒必要去你的農場就能馬上買到牛奶。你也能夠把牛奶安全地保存幾個星期。
超市緩解了大量你農場的壓力,由於你的奶牛不須要實時生產。超市將會處理這些需求。你只須要保證奶牛天天的生產效率便可。更好的是,附近村莊的村民均可以購買你的牛奶,由於人們老是能夠在超市的冰箱裏購買到你的牛奶。
就像超市同樣,服務端緩存將會處理一些經常使用的請求,而且更快更可靠地作出響應。
在上圖中我使用了一個術語——緩存代理(caching proxy),緩存代理是一個服務器,它存儲用於響應公共請求的靜態文件。緩存代理將攔截常見的請求並快速響應。它能夠防止這些請求對主web服務器形成壓力。
如今你可能有一大堆問題,好比:
這須要在如何設置緩存上學習更多,可是如今,你應該瞭解的一個概念是新鮮度。緩存代理將具備在不一樣時間緩存的不一樣文件,它須要決定是否該繼續提供這些文件的服務。這取決於你的緩存策略。
這也和超市售賣牛奶很相似。超市經理須要決定你的牛奶上架售賣多久。緩存代理經過緩存命中率(經過緩存服務器提供的內容的百分比)來衡量其成功。
至此,如今已經有一家商店在售賣你的牛奶了。雖然這是一個巨大的進步,可是你仍然沒辦法把你的牛奶賣給該商店覆蓋範圍以外的人。若是你想擴大你的生意,你得增長更多的商店和你合做。
假設你開始向更多的超市提供牛奶,你能夠在更大範圍內知足客戶的須要。這有點相似於一個內容交付網絡,或者稱爲CDN。CDN是一系列位於全球各地的代理服務器(就像咱們以前介紹的)。
做爲最終的用戶,你可能以爲高速的互聯網讓大多數站點加載都很快。然而,這僅僅是由於這些站點使用了CDN,從而可以快速地交付靜態文件。
若是你正在英格蘭,而且你正在請求一個緩存在弗吉尼亞服務器上的文件,你會體會到一些延遲,由於初始信號只能沿着幾千千米的電纜傳輸。在英國的本地緩存代理可以讓這個站點加載更快。
因此,你的服務器能夠向CDN網絡中的每一個代理服務器發送靜態資源副本,它們能夠處理本地請求,直到資源再也不「新鮮」。一些常見的CDN提供者包括Rackspace、Akamai和Amazon Web服務。
如今,全國(甚至全世界)的人們均可以買到你家生產的牛奶了。但如今還有一個小小的問題——顧客無法在本身家保存買來的牛奶。購買牛奶之後,顧客仍然須要儘快飲用,而後再去商店買更多。所以,這個系統仍然不能很好的服務顧客。
那有什麼解決辦法嗎?你須要一臺冰箱!
有了一臺冰箱,你能夠在本身家中保存牛奶,就沒必要反覆去商場購買了。在緩存方面,咱們談論的是徹底獨立的存儲靜態資源的地方,由於它僅僅做用於客戶端,或者與瀏覽器位於同一臺計算機上。咱們的代理服務器可不是在本地的。
這對於facebook或者Amazon這類你可能常常瀏覽的站點來講是很是好的。這對他們的服務端成本也頗有好處,由於他們能夠減小必須處理的請求。
有一個關鍵的點——咱們並非說牛奶可以「變魔術」似的直接到達你的冰箱裏,你仍是須要發起一個初始請求到你的服務器或者代理服務器。在這以後,你能夠緩存一些文件到本地。
瀏覽器是怎麼知道何時該從服務器中獲取新的文件呢?若是沒有這個功能,你講永遠不會得到這個文件的更新版本。
emmm,就像廠家在他們生產的牛奶包裝盒上印刷上生產日期同樣,服務器也會在http響應報文的頭部添加某種標識符。實際上咱們有4個獨立的HTTP緩存系統。上面顯示的場景很是相似於「保質期」的形式。在發送緩存文件以前,其餘一些方法仍然須要瀏覽器檢查服務器。
假設你正在開發你的第一個web應用。在你擁有大量用戶以前,你可能不須要去擔憂緩存協議,由於服務器成本是很是低的。然而,隨着你擴大規模,若是你想要快速加載你的應用,你須要使用緩存技術。
以Heroku爲例,這是一個快速部署應用的平臺。可是,它要求你使用單獨的服務來實現緩存,就像亞馬遜的CloudFront或者CloudFlare。學習這些將會花費更多時間。
在瀏覽器端,在你嘗試更新靜態資源並從新加載頁面時,你可能已經體驗過緩存的做用了,頁面可能並無什麼變化。不論你如何刷新頁面,都不會有什麼變化。
這其實經常是由於瀏覽器端的一些緩存協議。若是你想繞過瀏覽器的緩存,強行從服務端從新請求資源,你可使用Cmd+Shift+R(適用Mac)或者Ctrl+Shift+R(適用windows)。
假如你喜歡這篇教程,你能夠在CodeAnalogies blog上查看本文做者的更多教程。