『壹』 APP中緩存、載入與刷新機制設計【轉載】
1、為什麼要加緩存?
場景一:【等待】,在向伺服器請求新的數據時。我們讓用戶看到什麼?第一種是漂亮的等待載入頁面;第二種是緩存的內容。對於第二種,用戶可以對頁面進行操作,等待新數據時可以查看舊數據,更具有「可操作性」與「可用性」,從而減輕了從伺服器獲取數據這一動作的大小和時間長短,增強了用戶體驗。另一方面,如果內容更新的間隔較長或者用戶刷新的間隔較短,在沒有緩存的情況下,很多數據我們會多次重復的向伺服器獲取,增加了成本。
場景二:【結果】沒有聯網,或者在地鐵上網路太差無法載入數據時,如果留給用戶一個空白頁面,實在是感覺有點不負責任啊。並且很多功能在沒有聯網的情況下也有使用的可能性,比如:APP中的通訊錄,查看一些聊天記錄,通知信息,文章列表等。因為用戶打開APP不一定是要看新信息,說不定是回顧老信息(或許老信息里也有用戶之前沒看的),所以恰當的緩存可以滿足更多的用戶場景。
場景三:【金錢】有一天,一個用戶發現自己裝了某個APP後流量用的特別快,Ta可能永遠將這個APP打入冷宮了,而增加緩存正是節省流量的一個方法。雖然節省的不多或者用戶也察覺不到,但是作為一個有態度的產品經理,應該多做一些思考。
2、什麼是緩存?
緩存可分為如下幾類:
(1)app緩存。
(2)固定緩存。
(3)可手動清理的緩存。
(4)不可手動清理的緩存。
(5)臨時緩存。
其中,臨時緩存常用於一個功能頁面內,保存各欄目的緩存。同一個功能里會把子功能分為多個欄目進行劃分,每個標簽欄目下的內容在本次使用中都可保存為臨時緩存,在該功能里切換欄目,不需要重新載入數據,使用緩存顯示。
對於用戶來說,使用時達到了無縫切換瀏覽,對於伺服器來說,在短時間內數據很少會有更新,所以在一般情況下能滿足用戶的正常需求,並達到體驗優秀。
臨時緩存的清理機制是:退出該功能模塊就清除之前的緩存。也就是說下次進入該功能模塊,需要重新獲取一次數據。
很多時候我們都會用到臨時緩存,因為那些信息真的不是那麼重要,而且不需要經常反復查看,那對於那些我們經常使用而且經常需要反復查看的信息,馬海祥建議採取固定緩存,保存在本地,方便下次翻閱時不需要再一次向伺服器請求數據了。
對於固定緩存又會細分為可手動清理的緩存和不可手動清理的緩存。
第一種是我們最常見的緩存,幾乎所有產品都採用這種緩存方式。平時用戶瀏覽文章、圖集載入的數據就以這種形式緩存在本地,下次看回這篇文章、圖集時就不需要載入了。用戶也可以手動把這些緩存清理了,釋放空間。
而對於某些特殊場景,例如一些相對固定的數據,我們不願意一開始就打包進App里,這樣會占太大容量,造成產品包很大,也不願意每次進入頁面都向伺服器載入這些信息,那怎麼辦?建議的解決方法就是我們可以只載入一次就永遠存在本地了,這樣安裝包也不會大,以後也不用載入了。
3、如何清理緩存?
一般App都會在「設置」里提供一個清理緩存的功能,一鍵把空間釋放。除此之外,App最好要設計自動清理機制,可以通過兩個維度來設計這個機制。
(1)、時間
通過設定一個固定的時間,或者根據用戶使用周期靈活設定時間來清理緩存。每個產品的場景不一,用戶使用頻率不一,設定這個機制的時候就需要結合實際情況考慮了。
(2)、容量
一般是設定一個容量上限,採用堆棧的設計原理進行緩存清理,溢出堆棧的舊數據將自動清除。
1、頁面載入
方案1:單頁面整體載入
這種載入比較簡單,一般運用在頁面內容比較單一的情況下,所以直接一次性載入完所有數據後再顯示內容。其單頁面載入失敗的狀態相對來說也比較好處理。
方案2:單頁面分塊載入
這種方案的特點是,能讓用戶逐步看到內容,在這個漸進的過程中降低用戶的焦慮心理。
其中又可以分為,模塊間有關聯性的,先載入父內容,再載入子內容。如優酷,先把欄目載入出來,再載入各欄目的內容。
模塊間沒有絕對關聯性的,可獨自載入各自模塊內容,根據請求的速度不同分別顯示。這樣處理有一定幾率讓用戶在沒完全刷出數據的情況下就能找到自己需要的功能,如大眾點評、淘寶客戶端等。
框架固定,內容更新的,可先把框架顯示出來,再把各模塊的數據各自載入顯示,如各種iOS自帶應用。
這種分模塊載入的需要特別注意載入失敗的狀態,畢竟每個模塊都提示載入失敗,點擊重試是很挫的一件事,可以根據信息的優先順序來決定哪些數據失敗了採用默認狀態,哪些數據採用失敗提示。
方案3:跨頁面載入
父頁面&子頁面 or 同一app內,頁面間欄位可以復用的,在載入子頁面時不需要重新載入新數據。
方案4:預載入
這種載入方式的特點是,在載入一個頁面內容的同時,預測用戶的下一步行為,並為他下一步需要使用的頁面載入內容,使得他在下一步的操作中能立刻獲取信息而不需要載入等待。
預載入提供給用戶無縫的產品使用體驗,使得用戶在使用產品的過程中更直接流暢,沒有被打斷的感覺。
具體的例子有:
在瀏覽圖集的時候,當看到第一張的圖片時,就自動後台載入第二第三第四張圖片,用戶瀏覽完第一張圖片切換到第二張時就不會有載入等待的過程。
在瀏覽新聞列表時,就把每篇新聞的內容在後台進行預載入,用戶選擇看某篇新聞時,能立刻閱讀到內容。
但是這種方案也需要面臨很多的問題,馬海祥覺得最直接的就是流量問題,因為會自動跑掉很多用戶可能根本用不上的數據流量,所以,一般情況下馬海祥建議可以設定在wifi環境才採用這種載入模式。又或者設定載入規則,只把主要內容預載入,而部分次要內容可以在用戶真的用到的時候才載入,例如預載入新聞正文的情況,可以只載入文本信息,圖片信息等到用戶進入內頁才載入。這種預載入與分塊載入結合的方式也普遍運用在各個場景。
另外,預載入也需要時間的,他只是不在客戶端顯示給用戶,默默在後台運作而已,需要特殊考慮未載入完用戶就使用到那些信息的情況,所以在做預載入設計時需要同時考慮另一種適合該情況的普通載入方式。
預載入需要根據具體的場景來進行設計,設定好信息優先順序,綜合考慮各種類型信息的具體大小流量,整體考慮預載入的方式,這些都是需要經過精心分析思考的。
隨著網路環境的發展,預載入將成為以後產品普遍的載入方式,他提供給用戶的無縫使用體驗**地提升了產品的可用性。
2、操作載入
除了頁面的信息需要載入,頁面內的操作也是需要通過給伺服器發送請求記錄的。
方案1:載入層
進行一個操作後,彈出模態的提示層,告知用戶正在載入。採用模態的提示主要是防止用戶在該過程中進行其他操作,導致當前載入出錯。由於採用模態的提示,並且有可能因為網路原因導致長時間處於載入狀態,建議提供一個「關閉」的操作,中止本次載入,恢復App可用狀態。載入失敗時可在當前浮層變換為失敗提示。模態提示層是最穩妥的方式,但他會使用戶在使用過程中有打斷的感覺。
方案2:控制項自身載入狀態
這種方式是把操作載入的狀態與控制項的樣式結合起來了,對某個控制項進行操作後,控制項變換為載入狀態,此時控制項不能重復操作。由於這種載入方式是控制項的自身狀態,不影響其他操作,所以用戶也可以對頁面進行其他操作,可能會導致同時有多個請求的情況,增加了載入失敗的風險,這也算是這種方式的弊端,不過這種極端情況很少出現。請求失敗後,可配合Toast提示告知用戶失敗的原因。
方案3:後台載入
用戶在操作後,客戶端立刻反饋操作成功,然後把請求放到後台與伺服器交互,這一過程用戶不需要了解,不需要等待,在正常情況**驗是非常棒的。
但是在極端情況下會出現一些莫名其妙的狀況,由於是後台記錄請求並與伺服器交互,所以實際請求是否成功客戶端是不說明的,全部以操作成功來顯示,這就會導致用戶誤以為操作成功了,但實際上下次來看發現沒有成功。
所以,這種載入方式是需要根據具體使用場景來權衡使用的,對於一些重要的操作,建議還是使用模態的方式載入,對於一些小操作,如點贊、訂閱、關注,可採用後台載入的方式。
3、下一頁載入還是當前也載入
用戶進入首頁,正式邁出體驗的第一步,接下來迎接的就是基於用戶目標的界面間跳轉。完成界面的跳轉,會有各種載入策略,但無論形式如何,我們都可以將其歸為兩大類:「下一頁載入」、「當前頁載入」。
(1)「下一頁載入」滿足了用戶提前窺視的需求
我們把頁面看成「點」,頁面流是連接這些點的「線」,我們以「用戶想買一條牛仔褲」這一場景作為案例做了簡單的眼動研究,從應用啟動到商品瀏覽再到商品確定最後進入下單頁,用戶所呈現的瞳孔梯次增大,即E>D>C>B>A,為了解釋這一現象,通過與被試交流,我們發現相比於各種瀏覽,用戶更期待看到他們想看到的東西。因此此時的」下一頁載入「正好,滿足了用戶提前窺視的需求。
(2) Wait!I Need Think Think
我們以同樣的方式又對「使用支付寶對手機充值」這一場景做了研究,從開始支付到二次確認支付,用戶所呈現的瞳孔都比較大,即A與B近似相等,通過訪談,我們發現與「遞增體驗流」不同的是,當用戶遇到判斷邏輯的界面時,用戶並非急於想看下一頁面到底包含怎樣的內容,而是非0即1的驗證心態,即我的操作效成功了嗎?因此在判斷邏輯界面中,用戶的內容窺視需求並不強,當然也沒什麼內容,要麼僅是一個小小的Toast,再大一點就是一個簡單的信息反饋界面(意味著「下一頁載入」在這里就是個雞肋),用戶反而對非0即1的驗證需求較為強烈,其中還伴隨著等待結果過程中的緊張感、激動感,因此界面通過 當前頁載入 表明系統正在努力地處理用戶交代的指令**了用戶的緊張感、激動感,直到結果顯現——「處理成功」,完成了非0即1驗證的滿足感。
4、先載入還是先展示
當需載入的是功能時,可以先展示再載入,當需載入的是內容時,則反過來。
淘寶
打開APP的第一個頁面是功能,所以先展示再載入的:
隨便點擊一個模塊(不要點菜單),下面要展示的將要是內容(商品),所以是先載入再展示的,沒有載入完都不展示:
京東
同樣的,功能模塊先展示後載入:
內容先載入,沒載入完不展示:
兩種方式各有利弊:
先展示,後載入:
優點:給用戶0等待的錯覺
缺點:當前數據有可能是錯的,而且得等用戶操作到最後一步才會發現
先載入,後展示:
優點:保證數據的質量和准確
缺點:網路不好時,造成等待
顯然,功能模塊對於一個產品來說是既有固定的,在短時間內幾乎不會更新,所以這種數據出現錯誤或與當前狀態不同的幾率小得多,因此,可以使用先展示後載入的方式。
另一方面,內容(特別是商品數據)是最容易產生變動的,為了保證每一個消費者看到的數據都是最真實,最准確的,所以務必要先載入再展示。
1、空白頁面刷新失敗有提示
現在的應用都標榜以內容為中心,所以都會極力避免空白頁面的出現。對於大部分的應用,最好的方法就是使用緩存,進入頁面之後,先顯示之前的緩存,然後再進行內容的刷新。其次,消滅空白頁面的第二種方法就是提供系統推薦項進行替代。但是對於一些頁面,頁面內容跟用戶的使用狀態關系密切,無法避免會出現空白頁面,這時候會使用一些引導類的提示,使得頁面變得更加豐富,同時可以促進用戶產生內容。
但是一些資訊類應用,比如讀讀日報,打開默認是空白頁面,然後再載入內容(我不是很明白這種設定)。其他一些應用,比如:豆瓣一刻和MONO,每天第一次進入應用的時候也會出現空白頁面。我猜想第二類應用的展示方式的原因是這樣的。他們的內容**都是嚴格以天為單位的,每天固定時段**精選內容。他們會希望你每天只看並且看完當天的東西,所以一旦到了第二天,昨天的內容就是累贅了。所以每天第一次進入應用的時候會出現空白頁面,象徵著每天都是從新開始。此時就會對應一個「空白刷新」邏輯。
空白刷新對應的場景是這樣子的:用戶想要刷新出內容,並且用戶知道這里可以刷出新內容,但是沒有刷新成功,這時候需要給用戶一個交待。所以需要提示用戶。同時,提示完用戶之後需要給用戶一個解決方法,這就是「點擊後重試」。
2、緩存頁面刷新失敗無提示
常見的應用比如知乎、網易新聞、好奇心日報、微信朋友圈等,這些應用都會採用緩存的形式,打開之後顯示的是緩存內容,然後系統會給伺服器發送請求,如果有內容更新的話就會自動更新一次內容,更新之後的內容直接覆蓋當前的內容。更新失敗之後是沒有提示的。但是有一些應用,比如有道詞典、企鵝FM、網易雲音樂等,他們更新失敗之後是有提示的。
我覺得這兩種應用的區分點在於
應用的使用頻率;
內容的時間連續性;
界面之間的關系緊密度。
比如說網易新聞,作為一個打發時間的工具,每天使用頻率就會比較高,所以用戶進來之後是想看看有沒有更新。其次,網易新聞的內容是連續不斷更新的,所以用戶會知道當前顯示的內容是我看看過並且處理過的。最後,新聞列表頁面顯示的是摘要,用戶可以通過摘要快速進行判斷是否要進入詳情頁,摘要有助於幫助用戶回憶上一次的使用場景。
所以這就對應著一個這樣的場景:用戶只是想看看有沒有更新,所以他們已經做好了「沒有新內容」的心理預期,所以即使是更新不了內容,用戶也不會想太多。反倒是,如果進行了錯誤提示,用戶可能會有一種挫敗感。因為他知道現在有內容,只是因為網路的原因而沒有更新,他要進行的任務受到了外界因素的阻礙,由此產生一種細微的挫敗感。
3、緩存頁面刷新失敗有提示
另一類應用,使用頻率沒那麼高,或者內容不具備時間連續性的,又或者說當前界面無法喚起用戶上一次的使用場景。那麼就有必要進行率先你失敗提示了。
比如說企鵝FM,音頻類的應用註定使用不會那麼頻繁,因為通過視覺接收的信息會比通過聽覺接收的信息更快更多,同時音頻類對環境的要求較高(比如用耳機時要求環境不那麼嘈雜,外放時要求在私人場所)。其次,此類應用都是實時推薦的,不存在時間連續性的問題,用戶無法通過時間來判斷內容是否被閱讀過。再者,標題也無法幫你快速做出判斷,你還是要進去聽過才知道內容是什麼。最後如果不提醒,用戶進入到詳情頁再收到提醒,就會覺得應用浪費了用戶的時間。所以,對於此類內容,刷新失敗是有必要進行提醒的。
『貳』 北大青鳥設計培訓:如何提高web頁面的載入速度
在進行web前端網站設計的過程中,網站網頁的載入速度是非常關鍵的,每1秒的頁面載入時間,它將頁面瀏覽量減少11%,客戶滿意度降低16%,轉換率降低7%。
打開網頁的速度與網站的直接收入息息相關,所以說時間就是金錢,減少網站的載入速渣虛閉度是非常關鍵的。
下面佳音電腦培訓為大家介紹提高網站載入速度的方法。
1、圖片優化一般情況下,用戶傾向於放棄在3秒內未載入的網頁。
因為載入圖像佔用了網頁上可供下載的大部分位元組空間,因此影響網頁下載時間的關鍵來自圖像優化。
佳音IT培訓發現確保正確圖像優化的最佳方法之一是使用正確的大小和格式,如JPEG,GIF或PNG格式。
我們的目標是在不影響圖像質量的情況下盡可能減小文件大小。
2、緩存緩存是一種臨時存儲網頁的機制,可以減少帶寬並提高性能。
當訪問者到達您的站點時,緩存模式譽掘開始。
這節省了伺服器時間並提高了效率。
啟用瀏覽器緩存後,訪問者可以更快地訪問網站。
3、壓縮Gzip是一個文件壓縮軟體的應用程序,就像把你的網站變成一個zip文件。
大多數伺服器和客戶都支持Gzip。
佳音IT培訓發現當兼容Gzip的瀏覽器請求伺服器向瀏覽器資源發送響應時,它可以很快的減少網站的時間延遲。
4、簡潔的代碼代碼的簡潔性是非常關鍵的,這樣能夠很好的將HTML,JavaScipt和CSS文件打包並壓縮為較小的文件以運行。
在進行網站運行的過程中,佳音電腦培訓發現如果移動網站有五個JavaScript文件,瀏覽器將發出五個單獨的HTTP請求來獲取它們。
為了減少如裂擁塞和延遲,還有一種方法就是將五個文件縮小並連接在一起。
『叄』 java web 項目啟動時載入資料庫的數據到緩存中,如何實現求思路和實例。謝謝高峰相送
可以使用servlet的init方法訪問資料庫載入數據到java集合中,java集合相當於一塊緩存,適用於一般的數據。
『肆』 瀏覽器緩存機制
有dns的地方,就有緩存。瀏覽器、操作系統、Local DNS、根域名伺服器,它們都會對DNS結果做一定程度的緩存。
DNS查詢過程如下:
首先搜索瀏覽器自身的DNS緩存,如果存在,則域名解析到此完成。
如果瀏覽器自身的緩存裡面沒有找到對應的條目,那麼會嘗試讀取操作系統的hosts文件看是否存在對應的映射關系,如果存在,則域名解析到此完成。
如果本地hosts文件不存在映射關系,則查找本地DNS伺服器(ISP伺服器,或者自己手動設置的DNS伺服器),如果存在,域名到此解析完成。
如果本地DNS伺服器還沒找到的話,它就會向根伺服器發出請求,進行遞歸查詢。
瀏覽器本地緩存失效後,瀏覽器會向CDN邊緣節點發起請求。類似瀏覽器緩存,CDN邊緣節點也存在著一套緩存機制。CDN邊緣節點緩存策略因服務商不同而不同,但一般都會遵循http標准協議,通過http響應頭中的
Cache-control: max-age 的欄位來設置CDN邊緣節點數據緩存時間。
當瀏覽器向CDN節點請求數據時,CDN節點會判斷緩存數據是否過期,若緩存數據並沒有過期,則直接將緩存數據返回給客戶端;否則,CDN節點就會向伺服器發出回源請求,從伺服器拉取最新數據,更新本地緩存,並將最新數據返回給客戶端。 CDN服務商一般會提供基於文件後綴、目錄多個維度來指定CDN緩存時間,為用戶提供更精細化的緩存管理。
CDN 優勢
CDN節點解決了跨運營商和跨地域訪問的問題,訪問延時大大降低。
大部分請求在CDN邊緣節點完成,CDN起到了分流作用,減輕了源伺服器的負載。
http請求報文(request)
請求行
請求方法 空格 URL 空格 協議版本 回車符 換行符
請求頭(通用信息頭、請求頭、實體頭)
頭部欄位名 冒號 值 回車鍵 換行符
...
頭部欄位名 冒號 值 回車鍵 換行符
空行
回車符 換行符
實體主體(只有post請求有)
主體
http響應報文(response)
狀態行
協議版本 空格 狀態碼 空格 狀態碼描述 回車符 換行符
響應頭部
頭部欄位名 冒號 值 回車符 換行符
...
頭部欄位名 冒號 值 回車符 換行符
空行
回車符 換行符
響應正文
正文
瀏覽器初次向伺服器發起請求後拿到請求結果,會根據響應報文中HTTP頭的緩存標識,決定是否緩存返回的結果,是則將請求結果和緩存標識存入瀏覽器緩存中
瀏覽器每次發起請求,都會現在瀏覽器緩存中查找該請求的結果以及緩存標識
瀏覽器 瀏覽器緩存 伺服器
——————第一次發起http請求——————>
<——沒有該請求的緩存結果和緩存標識————
——————————————發起http請求——————————————>
<——————————返回該請求結果和緩存規則————————————
——將請求結果和緩存標識存入瀏覽器緩存——>
強制緩存就是向瀏覽器緩存查找結果,並根據該結果的緩存規則來決定是否使用該緩存結果的過程
強制緩存的情況分為三種:
1、不存在該緩存結果和緩存標識,強制緩存失效,直接向伺服器發起請求
2、存在該緩存結果和緩存標識,但結果已經失效,強制緩存失效,使用協商緩存
3、存在該緩存結果和緩存標識,且該結果沒有失效,強制緩存生效,直接返回該結果
控制強制緩存的欄位:Expires,Cache-Control
Expires 是 HTTP/1.0 控制緩存的欄位,值為伺服器返回該請求的結果緩存時間
即再次發送請求是,客戶端時間 小於 Expires的值,直接使用緩存結果
Cache-Control 是HTTP/1.1的規則,主要用於控制網頁緩存,主要取值為:
public:所有的內容都緩存(客戶端和代理伺服器都可以緩存)
private:所有內容只有客戶端可以緩存(默認值)
no-cache:客戶端緩存內容,但是是否使用緩存則需要經過協商緩存來驗證決定
no-store:即不使用強制緩存,也不使用協商緩存
max-age=xxx:緩存內容將在xxx秒後失效
Expires 是一個絕對值
Cache-Control 中 max-age 是相對值,解決了 Expires時期 服務端與客戶端 可能出現時間差的問題
註:Expires和Cache-Control同時存在時,只有Cache-Control生效
協商緩存就是強制緩存失效後,瀏覽器攜帶緩存標識向伺服器發起請求,由伺服器根據緩存標識決定是否使用緩存的過程
協商緩存的兩種情況:
1、協商緩存生效,返回304,繼續使用緩存
過程:
瀏覽器 瀏覽器緩存 伺服器
————————發起http請求————————>
<——該請求的緩存結果失效,只返回緩存標識——
————————攜帶該資源的緩存標識,發起http請求————————>
<—————————————304,該資源無更新————————————
——————獲取該請求的緩存結果——————>
<——————返回該請求的緩存結果——————
2、協商緩存失敗,返回200和請求結果
過程:
瀏覽器 瀏覽器緩存 伺服器
————————發起http請求————————>
<——該請求的緩存結果失效,只返回緩存標識——
————————攜帶該資源的緩存標識,發起http請求————————>
<————————200,資源已更新,重新返回請求和結果———————
——將該請求結果和緩存標識存入瀏覽器緩存中—>
協商緩存的標識也是在響應報文的HTTP頭中和請求結果一起返回給瀏覽器的
控制協商緩存的欄位:
(1) Last-Modified/If-Modified-Since:Last-Modified是伺服器響應請求是,返回該資源文件在伺服器最後被修改的時間;If-Modified-Since再次發起請求時,攜帶上次返回的Last-Modified的值,伺服器將該欄位值與該資源最後修改時間對比,決定是否用緩存
(2)Etag/If-None-Match:Etag伺服器響應請求時,返回當前資源文件的一個唯一標識,由伺服器生成之;If-None-Match是再次發起請求時,攜帶上次返回的唯一標識Etag的值,伺服器收到後,將該欄位值與該資源在伺服器上的Etag對比,一致 則返回304,否則返回200
註:Etag/If-None-Match優先順序高於Last-Modified/If-Modified-Since,同時存在時只有Etag/If-None-Match生效
瀏覽器緩存分為:內存緩存 和 硬碟緩存
內存緩存特性:
(1)快速讀取:內存緩存會將編譯解析後的文件,存入該進程的內存中,便於下次運行時快速讀取
(2)時效性:一旦關閉進程,進程內存清空
硬碟緩存特性:
永久性:直接寫入硬碟文件中
復雜、緩慢:讀取緩存對該緩存存放的硬碟文件進行I/O操作,重新解析
from memory cache:使用內存中的緩存
from disk cache:使用硬碟中的緩存
瀏覽器讀取順序:memory ——> disk
瀏覽器將js和圖片等文件解析執行後直接存入內存緩存中,F5刷新頁面時,from memory cache(使用內存中的緩存)
css文件存入硬碟中,F5刷新頁面時,from disk cache(使用硬碟中的緩存)
參考文章
https://segmentfault.com/a/1190000017962411
https://www.cnblogs.com/chengxs/p/10396066.html
『伍』 認識HTTP----緩存篇
本文內容大多參考 《圖解HTTP》一書
所以講緩存為什麼要先扯代理伺服器?別急,讓我們看一下一個請求的簡單示意圖。
我們看到客戶端(用戶)發送了一個請求並不是直接發給源伺服器的而是經過了代理伺服器,然後經由代理伺服器再發送給源伺服器,響應也同樣遵循這個順序。
那麼代理伺服器在這中間擔任了什麼角色?
緩存是指代理伺服器或客戶端本地磁碟內保存的資源副本。利用緩存可減少對源伺服器的訪問,因此也就節省了通信流量和通信時間。
緩存伺服器是代理伺服器的一種,並歸類在緩存代理類型中。換句話說,當代理轉發從伺服器返回的響應時,代理伺服器將會保存一份資源的副本。
緩存伺服器的優勢在於利用緩存可避免多次從源伺服器轉發資源。因此客戶端可就近從緩存伺服器上獲取資源,而源伺服器也不必多次處理相同的請求了。
即便緩存伺服器和客戶端內有緩存,也不能每次都給我返回緩存吧,如果是這樣,源伺服器更新了我也不知道,因為我每次都是看緩存的資源。
為了解決這個問題,針對緩存設計了時效性的概念:
即使存在緩存,也會因為客戶端的要求、緩存的有效期等因素,向源伺服器確認資源的有效性。若判斷緩存失效,緩存伺服器將會再次從源伺服器上獲取「新」資源。
緩存不僅可以存在於緩存伺服器內,還可以存在客戶端瀏覽器中。以Internet Explorer 程序為例,把客戶端緩存稱為臨時網路文件(Temporary Internet File)。
瀏覽器緩存如果有效,就不必再向伺服器請求相同的資源了,可以直接從本地磁碟內讀取。
另外,和緩存伺服器相同的一點是,當判定緩存過期後,會向源伺服器確認資源的有效性。若判斷瀏覽器緩存失效,瀏覽器會再次請求新資源。
Pragma 是HTTP/1.1 之前版本的歷史遺留欄位,僅作為與HTTP/1.0的向後兼容而定義。
規范定義的形式唯一,如下所示。
Pragma: no-cache
該首部欄位屬於通用首部欄位,但只用在客戶端發送的請求中。客戶端會要求所有的中間伺服器不返回緩存的資源。
通過指定首部欄位Cache-Control 的指令,就能操作緩存的工作機制。
可用的指令按請求和響應分類如下所示:
public指令
Cache-Control: public
當指定使用public 指令時,則明確表明其他用戶也可利用緩存。
private指令
no-store指令
Cache-Control: no-store
當使用no-store 指令時,暗示請求(和對應的響應)或響應中包含機密信息。
因此,該指令規定緩存不能在本地存儲請求或響應的任一部分。
ps:從字面意思上很容易把no-cache誤解成為不緩存,但事實上no-cache代表不緩存過期的資源,緩存會向源伺服器進行有效期確認後處理資源,也許稱為do-not-serve-from-cache-without-revalidation更合適。no-store 才是真正地不進行緩存,請讀者注意區別理解。
s-maxage指令
Cache-Control: s-maxage=604800 //(單位:秒)
s-maxage 指令的功能和max-age 指令的功能相同, 它們的不同點是s-maxage 指令只適用於供多位用戶使用的公共緩存伺服器(這里指代理伺服器)。也就是說,對於向同一用戶重復返回響應的伺服器來說,這個指令沒有任何作用。
另外,當使用s-maxage 指令後,則直接忽略對Expires 首部欄位及max-age 指令的處理。
max-age指令
cache-extension token
Cache-Control: private, community="UCI"
通過 cache-extension 標記(token),可以擴展Cache-Control 首部欄位內的指令。
如上例,Cache-Control 首部欄位本身沒有community 這個指令。藉助extension tokens 實現了該指令的添加。如果緩存伺服器不能理community 這個新指令,就會直接忽略。因此,extension tokens 僅對能理解它的緩存伺服器來說是有意義的。
If-Unmodified-Since: Thu, 03 Jul 2012 00:00:00 GMT
首部欄位If-Unmodified-Since 和首部欄位If-Modified-Since 的作用相反。它的作用的是告知伺服器,指定的請求資源只有在欄位值內指定的日期時間之後,未發生更新的情況下,才能處理請求。如果在指定日期時間後發生了更新,則以狀態碼412 Precondition Failed 作為響應返回。
ps:Last-Modified 存在一定問題,如果在伺服器上,一個資源被修改了,但其實際內容根本沒發生改變,會因為Last-Modified時間匹配不上而返回了整個實體給客戶端(即使客戶端緩存里有個一模一樣的資源)。
首部欄位If-None-Match 屬於附帶條件之一。它和首部欄位If-Match 作用相反。用於指定If-None-Match 欄位值的實體標記(ETag)值與請求資源的ETag 不一致時,它就告知伺服器處理該請求。
在GET 或HEAD 方法中使用首部欄位If-None-Match 可獲取最新的資源。因此,這與使用首部欄位If-Modified-Since 時有些類似。
不與伺服器確認,而是直接使用瀏覽器緩存的內容。其中響應內容和之前的響應內容一模一樣,例如其中的Date時間是上一次響應的時間。
F5的作用和直接在URI輸入欄中輸入然後回車是不一樣的,F5會讓瀏覽器無論如何都發一個HTTP Request給Server,即使先前的響應中有Expires頭部。
Ctrl+F5要的是徹底的從Server拿一份新的資源過來,所以不光要發送HTTP request給Server,而且這個請求裡面連If-Modified-Since/If-None-Match都沒有,這樣就逼著Server不能返回304,而是把整個資源原原本本地返回一份,這樣,Ctrl+F5引發的傳輸時間變長了,自然網頁Refresh的也慢一些。
Cache-Control 是 HTTP1.1 才有的,不適用於 HTTP1.0,而 Expires 既適用於 HTTP1.0,也適用於 HTTP1.1,所以說在大多數情況下同時發送這兩個頭會是一個更好的選擇,當客戶端兩種頭都能解析的時候,會優先使用 Cache-Control。
二者都是通過某個標識值來請求資源, 如果伺服器端的資源沒有變化,則自動返回 HTTP 304 (Not Changed)狀態碼,內容為空,這樣就節省了傳輸數據量。當資源變化後則返回新資源。從而保證不向客戶端重復發出資源,也保證當伺服器有變化時,客戶端能夠得到最新的資源。
其中Last-Modified使用文件最後修改作為文件標識值,它無法處理文件一秒內多次修改的情況,而且只要文件修改了哪怕文件實質內容沒有修改,也會重新返回資源內容;ETag作為「被請求變數的實體值」,其完全可以解決Last-Modified頭部的問題,但是其計算過程需要耗費伺服器資源。
Expires和Cache-Control都有一個問題就是服務端的修改,如果還在緩存時效里,那麼客戶端是不會去請求服務端資源的(非刷新),這就存在一個資源版本不符的問題,而強制刷新一定會發起HTTP請求並返回資源內容,無論該內容在這段時間內是否修改過;而Last-Modified和Etag每次請求資源都會發起請求,哪怕是很久都不會有修改的資源,都至少有一次請求響應的消耗。
對於所有可緩存資源,指定一個Expires或Cache-Control max-age以及一個Last-Modified或ETag至關重要。同時使用前者和後者可以很好的相互適應。
前者不需要每次都發起一次請求來校驗資源時效性,後者保證當資源未出現修改的時候不需要重新發送該資源。而在用戶的不同刷新頁面行為中,二者的結合也能很好的利用HTTP緩存控制特性,無論是在地址欄輸入URI然後輸入回車進行訪問,還是點擊刷新按鈕,瀏覽器都能充分利用緩存內容,避免進行不必要的請求與數據傳輸。
做法很簡單,就是把可能會更新的資源以版本形式發布,常用的方法是在文件名或參數帶上一串md5或時間標記符:
可以看到上面的例子中有不同的做法,有的在URI後面加上了md5參數,有的將md5值作為文件名的一部分,有的將資源放在特性版本的目錄中。
那麼在文件沒有變動的時候,瀏覽器不用發起請求直接可以使用緩存文件;而在文件有變化的時候,由於文件版本號的變更,導致文件名變化,請求的url變了,自然文件就更新了。這樣能確保客戶端能及時從伺服器收取到新修改的文件。通過這樣的處理,增長了靜態資源,特別是圖片資源的緩存時間,避免該資源很快過期,客戶端頻繁向服務端發起資源請求,伺服器再返回304響應的情況(有Last-Modified/Etag)。
『陸』 網站緩存功能什麼意思
1.減少 HTTP 請求數:一個頁面中包含的圖片,JS,CSS等每一個資源都會生成一個 HTTP 下載請求,由瀏覽器發向網站伺服器,如果減少這個請求數,會縮短網路傳輸的時間。
另外圖片盡量採用壓縮格式的,例如 jpg 就屬於一種壓縮圖片格式,bmp屬於無壓縮無失真圖片。這個需要網頁/網站設計人員綜合考慮這個因素。
優點:縮短網路傳輸事件,網路傳輸量小,減少伺服器端負載;
缺點:減少HTTP請求,有時候無法滿足網站發布信息的需求,盜鏈的出現也會增加HTTP請求;
2、採用緩存技術(webcache):這個是目前網站加速最主要的方式。如果利用代理/緩存加速伺服器去實現的話,網站在不需要做任何改動的情況下,就可實現大跨度的實現加速效果。實現的基本方式為:將指定的網站頁面周期性的緩存起來,緩存時間可從幾秒到幾天,在緩存時間內,頁面只需要生成一次,以後有用戶訪問這個頁面的時候,網站伺服器和資料庫就不再需要重新生成相同的頁面了,極大的減少了網站伺服器和資料庫負荷。我們做個簡單的對比,假設一個新聞熱點頁面,在一個小時可被訪問1萬次,如果這個新聞頁面每次被訪問的時候,都會通過讀取資料庫後再一遍一遍的編譯生成,在一個小時內將會重復性的生成1萬次;如果這個頁面被周期性的緩存10分鍾,也就是每間隔10分鍾才會被生成一次,一個小時內只會被生成6次,如果兩種方式一對比,效果就超級明顯,兩種比較下伺服器負荷的壓力比差別1000倍以上,緩存技術將使得網站負載在高峰期游刃有餘。Fikker網站加速軟體實際上是一款代理伺服器軟體,通過Fikker網站加速伺服器提供的頁面緩存(webcache)功能,將需要緩存的網站URL配置到頁面緩存中(支持正則表達式,通配符和精確地址匹配),並設定一定的緩存時間(幾秒到幾天),不需要重啟Fikker立即生效,如果有重要頁面變動,可通過清理緩存將指定的緩存頁面清理出去。
優點:網站不需要做任何改動,大幅減少伺服器和資料庫的負荷。
3、使用gzip壓縮:頁面壓縮主要是降低傳輸尺寸,提高傳輸效率。常用的 html,asp,php,jsp,txt,css,js等文本頁面,通過gzip壓縮可降低75%左右尺寸,也就是原來需要傳輸 100KB 的頁面,gzip壓縮後只需要 25KB 的傳輸數據了,加速的效果是非常明顯的。Fikker內置了gzip模塊,自動對壓縮的文件壓面進行壓縮傳輸。
4、使用非阻塞網路技術(non-block):提高網路響應速度,Linux 從 2.6 內核開始,專門引入 epoll 事件機制,相對於傳統的 select 事件機制,效率大大的增強,尤其在高並發情況下越發的明顯,幾個線程即可並發支持上萬並發連接,使用盡量少的線程除了減少內存開支還可減少頻繁的線程切換的開銷。Fikker軟體的Linux版本全面支持epoll事件機制,支持從連接建立到連接結束,從域名解析開始到結束的全非阻塞網路設計。
5、提高帶寬,加速頁面傳輸:利用帶寬加速方式常用是CDN,通過CDN運營商的網路將頁面分發出去,用戶訪問時可就從最近的節點獲取,達到加速目的。但這裡面有一個前提,就是需要頁面是靜態的,或動態頁面首先需要被生成出來,然後才能利用 CDN 的高速網路傳輸出去,從這個角度理解,CDN 與 緩存加速具有很強的互補性,即利用緩存技術加快頁面生成,利用CDN加快傳輸,缺一不可。
希望對你有事幫助。
『柒』 北大青鳥設計培訓:web伺服器緩存基本定義
為了能夠給用戶一個良好的上網體驗,大部分的網頁和瀏覽器都配置了預載入以及緩存功能。
今天蘭州電腦培訓http://www.kmbdqn.cn/就通過案例分析來了解一下,關於web緩存的基本定義與類型介紹。
Web緩存是什麼?為什麼要使用緩存?Web緩存處於伺服器(也稱為源伺服器)和客戶端之間,監視請求並保存響應的副本,比如HTML頁面,圖片和文件等(統稱為表述)。
如果之後有對同一個URL的新請求,它會使用自己保存的內容來響應,而不是再次請求源伺服器來獲取內容。
使用Web緩存主要有下面兩個原因:減少延遲——因為響應請求的內容來自緩存(距客戶端較近)而不是源伺服器,它會花較少的時間來獲得表述並將他們呈現出來。
這使得Web看起來具有良好的響應速度。
減少網路傳輸——由於復用了表述,它可以減少客戶端使用的帶寬總量。
如果客戶需要為流量付費,這就意味著省錢。
緩存會降低對帶寬的要求,也降低處理難度。
Web緩存的種類瀏覽器緩存你在查看現代Web瀏覽器(比如IE、Safari或Mazilla)選項的時候,可能會看到「緩存」設置。
這個選項讓你配置一部分硬碟空間來保存你看過的表述。
瀏覽器緩存的規則相當簡單。
它通常會在一次會話(即當前瀏覽器中一次調用)中檢查表述是否新。
這個緩存在用戶使用「回退」按鈕或者點擊一個瀏覽過的鏈接時會特別有用。
而且,如果你在網站緩悔數的各個頁面中瀏覽相同的圖片,他們幾乎能馬上從緩存中載入出來。
代理緩存Web代理緩存的工作原理相同,但規模更大。
代理以同樣的方式為成百上千的用戶服務;大公司和ISP常常把代碼緩存建立在防火牆之上,也可能是以獨立設備的形式存在(也稱為中間設備)。
代理緩存即不是客戶端的一部分,也不是伺服器的一部分,而是在網路之外,必須以某種方式把請求路由過去。
其中一種方式是手工修改瀏覽器代理設備,指定要使用的代碼;另一種方式是攔截。
攔截式代理會根據其自身的基礎網路重定向Web請求,不需要前襪在客戶端配置,客戶端甚至不知道它們的存在。
代理緩存是一種共享緩存,通常不只是一個用戶,而是大量用擾首戶在使用代理緩存。
正因為如此,他們特別擅長降低延遲和網路傳輸量。
這是因為眾人都需要的表述會被多次重復使用。
網關緩存網關緩存又名「反向代理緩存」或「替代緩存」。
網關緩存也是一種中介,它他們不是由網路管理員部署以節約帶寬,而是由網站管理員自己部署,使其站點更具伸縮性、可靠性以及擁有更好的性能。
很多方法都可以把請求路由到網關緩存,但常見的方法是使用負載均衡器讓他們對於客戶來說,看起來就跟源伺服器一樣。
內容分發網路(CDN)在整個Internet(或它的一部分)中分發網關緩存,並將其出售給對此感興趣的網站。
Web緩存對我有壞處么?我為什麼要幫助它們?Web緩存是互聯網中誤解深的技術之一。
因為代理緩存可以隱藏使用網站的用戶,所以網站管理員特別害怕失去對他們的站點的控制,這會使得他們很難去知道是誰在使用他們的站點。
然而不幸的是,即使沒有Web緩存,網路上也有非常多的因素可以保證管理員精確的知道一個用戶如何使用他們的站點。
如果這是你非常關注的問題的話,這篇手冊將會指導你如何在站點沒有不友好的緩存機制的情況下獲取你需要的統計信息。
『捌』 Glide ② — 緩存機制
閱讀本文需要先了解 Glide載入流程
首先介紹一下Glide中對圖片資源的封裝類: EngineResource
在活動緩存中,使用了一個map用來存放EngineResource對象,這里需要注意一個操作,就是這個EngineResource對象是用WeakReference包裹的,並且通過ReferenceQueue監聽了EngineResource的回收,在回收的時候會清理當前的活動緩存內容;
下面分析一下源碼是如果實現的:
首先,自定義一個WeakReference類,將key和resource傳進入(用於在WeakReference回收的時候釋放),傳入一個ReferenceQueue對象,用於監聽WeakReference回收
開啟一個子線程,在循環中監聽ReferenceQueue的返回值,通過這個返回值,判斷WeakReference有沒有回收,監聽的方法是ReferenceQueue.remove(),這是一個阻塞方法;所以要開子線程;
LruResourceCache繼承了LruCache類,關於LruCache類,簡單提一下,具體的可以參考我之前的博客 LruCache實現 ,LruCache繼承了LinkedHashMap,LinkedHashMap有一個特點,就get後的數據會移動到隊列,這就是Lru思想:固定一個容量,put的時候如果超過容量了,將最後一個節點刪除,get的時候將get的這個節點移動到隊列的頭部;
onItemEvicted()方法是LruCache的一個空方法,調用的時機是在put的時候判斷是否超過容量,如果超過容量了,就淘汰最後一個節點,並調用這個方法;
活動緩存和內存緩存都是緩存在內存中的,活動緩存緩存的是正在使用的圖片資源,當圖片不使用時會放到內存緩存中,提出活動緩存的目的:單一的內存緩存由於Lru的淘汰機制會導致圖片載入不穩定
首先介紹一個磁碟緩存方案DiskLruCache(非Google官方編寫,但獲得官方認證),關於這個磁碟緩存方案的理解可以看郭林的這片文章:
Android DiskLruCache完全解析,硬碟緩存的最佳方案
從上一篇文章知道,Glide載入操作是通過 Engine 來驅動的
Engine的load()中,首先嘗試從 活動緩存 和 內存緩存 獲取緩存,如果沒有緩存再啟動EngineJob和DecodeJob; 上面介紹了緩存的獲取,下面看一下緩存的存放,肯定是在獲取到圖片後的回調中存放的
在DecodeJob獲取到圖片數據後,會回調很多介面,在回調中會將其放入 活動緩存 ,當圖片不在使用的時候,就會放入內存緩存,根據上面介紹的活動緩存規則,當 EngineResource 計數為0時就應該放入內存緩存;
當資源引用為0,回調onResourceReleased(),從活動緩存移除,放入內存緩存;
上面介紹了活動緩存和內存緩存的存放和獲取,下面看一看磁碟緩存的存取;
還記得 DataFetcherGenerator 介面嗎?這個介面是DecodeJob用於獲取數據的,有三個具體的實現:
我們在上一篇具體介紹的是網路文件的獲取,這里的磁碟緩存使用的就是 DataCacheGenerator(緩存文件) 這個Generator了
上篇文章知道DecodeJob是一個Runnable任務,在run()會調用runWrapped(),在runWrapped()中會做三種事情:
在runWrapped()的解碼操作中會執行decode(),在decode()中,會disk put操作;
Glide的磁碟緩存是基於DiskLruCache 實現的,Glide直接使用的是DiskLruCacheWrapper對象對DiskLruCache 的封裝;