亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

HTTP Cache的實現(xiàn)介紹

系統(tǒng) 1808 0
我們都知道瀏覽器會緩存訪問過網(wǎng)站的網(wǎng)頁,瀏覽器通過URL地址訪問一個網(wǎng)頁,顯示網(wǎng)頁內(nèi)容的同時會在電腦上面緩存網(wǎng)頁內(nèi)容。如果網(wǎng)頁沒有更新的話,瀏覽器再次訪問這個URL地址的時候,就不會再次下載網(wǎng)頁,而是直接使用本地緩存的網(wǎng)頁。只有當網(wǎng)站明確標識資源已經(jīng)更新,瀏覽器才會再次下載網(wǎng)頁。

一、什么是HTTP Cache

對于瀏覽器的這種網(wǎng)頁緩存機制大家已經(jīng)耳熟能詳了,舉個例子來說,JavaEye的新聞訂閱地址:http://www.iteye.com/rss/news , 當瀏覽器或者訂閱程序訪問這個URL地址的時候,JavaEye的服務器在response的header里面會發(fā)送給瀏覽器如下狀態(tài)標識:

C代碼 收藏代碼
  1. Etag "427fe7b6442f2096dff4f92339305444"
  2. Last-ModifiedFri,04Sep200905:55:43GMT


這就是告訴瀏覽器,新聞訂閱這個網(wǎng)絡資源的最后修改時間和Etag。于是瀏覽器把這兩個狀態(tài)信息連同網(wǎng)頁內(nèi)容在本地進行緩存,當瀏覽器再次訪問JavaEye新聞訂閱地址的時候,瀏覽器會發(fā)送如下兩個狀態(tài)標識給JavaEye服務器:

C代碼 收藏代碼
  1. If-None-Match "427fe7b6442f2096dff4f92339305444"
  2. If-Modified-SinceFri,04Sep200905:55:43GMT


就是告訴服務器,我本地緩存的網(wǎng)頁最后修改時間和Etag是什么,請問你服務器的資源有沒有在我上次訪問之后有更新啊?于是JavaEye服務器會核對一下,如果該用戶上次訪問之后沒有更新過新聞,那么根本就不必生成這個RSS了,直接告訴瀏覽器:“沒什么新東西,你還是看自己緩存的網(wǎng)頁吧”,于是服務器就發(fā)送一個304 Not Modified的消息,其他什么都不用干了。

這就是HTTP層的Cache,使用這種基于資源的緩存機制,不但大大節(jié)省服務器程序資源,而且還減少了網(wǎng)頁下載次數(shù),節(jié)約了很多網(wǎng)絡帶寬。

二、HTTP Cache究竟有什么作用?

我們通常的動態(tài)網(wǎng)站編程,服務器端程序根本就不去處理瀏覽器發(fā)送過來的If-None-Match和If-Modified-Since狀態(tài)標識,只要有請求就生成網(wǎng)頁發(fā)送給瀏覽器。對于一般情況來說,用戶不會總是沒完沒了刷新一個頁面,所以大家并不認為這種基于資源的緩存有什么太大的作用,但實際情況并非如此:

1、像Google這種比較智能的網(wǎng)絡爬蟲可以有效識別資源的狀態(tài)信息,如果使用這種緩存機制,可以大大減少爬蟲的爬取次數(shù)。

比方說Google每天爬JavaEye網(wǎng)站大概15萬次左右,但實際上JavaEye每天有更新的內(nèi)容不會超過1萬個網(wǎng)頁。因為很多內(nèi)容更新比較快,因此Google就會反復不停的爬取,這樣本身就造成了很多資源的浪費。如果我們使用HTTP Cache,那么只有當網(wǎng)頁內(nèi)容發(fā)生改變的時候,才會真正進行爬取,其他時候我們直接告訴Google的爬蟲304 Not Modified就可以了。這樣不但降低了服務器本身的負載和爬蟲造成的網(wǎng)絡帶寬消耗,實際上也大大提高了Google爬蟲的工作效率,豈不是皆大歡喜?

2、很多內(nèi)容更新不頻繁的網(wǎng)頁,盡管用戶不會頻繁的刷新,但是從一個比較長的時間段來看使用HTTP Cache,仍然可以起到很大的緩存作用。

比方說一些歷史討論帖子,已經(jīng)過去了幾個月了,這些帖子內(nèi)容很少更新。用戶可能通過搜索,收藏鏈接,文章關聯(lián)等方式時不時訪問到這個頁面。那么只要用戶訪問過一次以后,后續(xù)所有訪問服務器直接發(fā)送304 Not Modified就可以了,不用真正生成頁面。

3、對于歷史帖子使用HTTP Cache可以避免爬蟲反復的爬取。

比方說JavaEye的論壇帖子列表頁面,分頁到20頁后面的帖子已經(jīng)很少有人直接訪問了,但是從服務器日志去看,每天仍然有大量爬蟲反復爬取這些分頁到很后面的頁面。這些頁面由于用戶很少去點擊,所以基本上沒有被應用程序的memcached緩存住,每次訪問都會造成很高的資源消耗,爬蟲隔一段時間就爬一次,對服務器是很大的負擔。如果使用了HTTP Cache,那么只要爬蟲爬過一次以后,以后無論爬蟲爬多少次,都可以直接返回304 Not Modified了,極大的節(jié)省了服務器的負載。

三、如何在應用程序里面使用HTTP Cache

如果我們要在自己的程序里面實現(xiàn)HTTP Cache,是件非常簡單的事情,特別是對Rails來說只需要添加一點點代碼,以上面的JavaEye新聞訂閱來說,只要添加一行代碼:

Ruby代碼 收藏代碼
  1. def news
  2. fresh_when( :last_modified =>News.last.created_at, :etag =>News.last)
  3. end


用最新新聞文章作為Etag,該文章最后修改時間作為資源的最后修改時間,這樣就OK了。如果瀏覽器發(fā)送過來的標識和服務器標識一致,說明內(nèi)容沒有更新,直接發(fā)送304 Not Modified;如果不一致,說明內(nèi)容更新,瀏覽器本地的緩存太古老了,那么就需要服務器真正生成頁面了。

以上只是一個最簡單的例子,如果我們需要根據(jù)狀態(tài)做一些更多的工作也是很容易的。比方說JavaEye博客的RSS訂閱地址: http://robbin.iteye.com/rss

Ruby代碼 收藏代碼
  1. @blogs = @blog_owner .last_blogs
  2. @hash = @blogs .collect{|b|{b.id=>b.post.modified_at.to_i+b.posts_count}}.hash
  3. if stale?( :last_modified =>( @blog_owner .last_blog.post.modified_at|| @blog_owner .last_blog.post.created_at), :etag => @hash )
  4. render :template => "rss/blog"
  5. end


這個實現(xiàn)稍微復雜一些。我們需要判斷博客訂閱所有的輸出文章是否有更新,所以我們用博客文章內(nèi)容最后修改時間和博客的評論數(shù)量做一個hash,然后用這個hash值作為資源的Etag,那么只要這些博客文章當中任何文章內(nèi)容被修改,或者有新評論,都會改變Etag值,從而通知瀏覽器內(nèi)容有更新了。

除了RSS訂閱之外,JavaEye網(wǎng)站還有很多地方適合使用HTTP Cache,比方說JavaEye論壇的版面列表頁面,一些經(jīng)常喜歡泡論壇的用戶,可能時不時會上來刷新一下版面, 看看有沒有新的帖子,那么我們就不必每次用戶請求的時候都去執(zhí)行程序,生成頁面給他。我們判斷一下如果沒有新帖子的話,直接告訴他304 Not Modified就可以了,在沒有使用HTTP Cache之前的版面Action代碼:

Ruby代碼 收藏代碼
  1. def board
  2. @topics = @forum .topics.paginate...
  3. @announcements =(params[ :page ]||1).to_i==1?Topic.find :all , :conditions =>...
  4. render :action => 'show'
  5. end


添加HTTP Cache以后,代碼如下:

Ruby代碼 收藏代碼
  1. def board
  2. @topics = @forum .topics.paginate...
  3. if logged_in?||stale?( :last_modified => @topics [0].last_post.created_at, :etag => @topics .collect{|t|{t.id=>t.posts_count}}.hash)
  4. @announcements =(params[ :page ]||1).to_i==1?Topic.find :all , :conditions ...
  5. render :action => 'show'
  6. end
  7. end


對于登錄用戶,不使用HTTP Cache,這是因為登錄用戶需要實時接收站內(nèi)短信通知和訂閱通知,因此我們只能對匿名用戶使用HTTP Cache,然后我們使用當前所有帖子id和回帖數(shù)構造hash作Etag,這樣只要當前分頁列表頁面有任何帖子發(fā)生改變或者有了新回帖,就更新頁面,否則就不必重新生成頁面。

論壇帖子頁面實際上也可以使用HTTP Cache,只不過Etag的hash算法稍微復雜一些,需要保證帖子的任何改動都要引起hash值的改變,示例代碼如下:

Ruby代碼 收藏代碼
  1. def show
  2. @topic =Topic.findparams[ :id ]
  3. user_session.update_....... if logged_in?
  4. Topic.increment_counter(...) if ......
  5. @posts = @topic .post_by_pageparams[ :page ]
  6. posts_hash= @posts .collect{|p|{p.id=>p.modified_at}}.hash
  7. topic_hash= @topic .forum_id+ @topic .sys_tag_id.to_i+ @topic .title.hash+ @topic .status_flag.hash
  8. ad_hash=...(廣告的hash算法,略)
  9. if logged_in?||stale?( :etag =>[posts_hash,topic_hash,ad_hash])
  10. render
  11. end
  12. end


要分別根據(jù)主題貼,該分頁的所有回帖和帖子頁面的廣告內(nèi)容進行hash,計算出來一個唯一的Etag值,保證任何改動都會生成新的Etag,這樣就搞定了,是不是很簡單!這種帖子的緩存非常有效,可以避免Rails去render頁面和下載頁面,極大的減輕了服務器負載和帶寬。

再舉一個需求比較特殊的例子:對于知識庫搜索相關文章的推薦頁面,比方說:http://www.iteye.com/wiki/topic/462476,也就是本文的相關文章推薦內(nèi)容,我們并不希望用戶和爬蟲每次訪問這個頁面都實際執(zhí)行一遍全文檢索,然后構造頁面內(nèi)容,在一個相對不長的時間范圍內(nèi),這篇文章的相關推薦文章改變的概率不大,因此我們希望比方說5天之內(nèi),用戶重復訪問該頁面,就直接返回304 Not Modified,那么Rails沒有直接的設施給我們使用,需要我們稍微了解一些Rails的機制,自己編寫,代碼示例如下:

Ruby代碼 收藏代碼
  1. def topic
  2. @topic =Topic.find(params[ :id ])
  3. unless logged_in?
  4. if request.not_modified?(5.days.ago)
  5. head :not_modified
  6. else
  7. response.last_modified= Time .now
  8. end
  9. end
  10. end


每次用戶請求,我們判斷用戶是否5天之內(nèi)訪問過該頁面,如果訪問過,直接返回304 Not Modified,如果沒有訪問過,或者上次訪問已經(jīng)超過了5天,那么設置最近修改時間為當前時間,然后生成頁面給用戶。是不是很簡單?

在給JavaEye網(wǎng)站所有的RSS訂閱輸出添加了HTTP Cache以后,通過一天的觀察發(fā)現(xiàn),超過一半的RSS訂閱請求已經(jīng)被緩存了,直接返回304 Not Modified,所以效果非常明顯,由于JavaEye網(wǎng)站每天RSS訂閱的動態(tài)請求就超過了10萬次,因此添加HTTP Cache可以減輕不少服務器的負擔和帶寬消耗。除此之外,新聞文章頁面,整個論壇頻道,知識庫相關推薦文章頁面都可以添加HTTP Cache,粗粗計算下來,JavaEye這些頁面統(tǒng)統(tǒng)使用HTTP Cache以后,網(wǎng)站整體性能至少可以提高10%。

HTTP Cache的實現(xiàn)介紹


更多文章、技術交流、商務合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 久热这里只有精品在线 | 99热在线观看精品 | 天天弄天天模 | 国产不卡视频在线 | 国产日产欧美一区二区三区 | 日日射日日干 | 色综合久久一本首久久 | 国产中文字幕免费 | 欧美在线视频免费 | 国产网址在线观看 | 亚洲精品6久久久久中文字幕 | 五月婷婷视频在线 | 一级毛片aa高清免费观看 | 亚洲国产精品高清在线一区 | 中文字幕国产日韩 | 超级碰碰青草免费视频92 | 91精品国产综合久久婷婷 | 成人黄色网址 | 综合欧美日韩 | 成人性生交大片免费看午夜a | 最新香蕉97超级碰碰碰碰碰久 | 国产一级特黄高清免费大片 | 玖玖在线播放 | 亚洲精品综合一二三区在线 | 国内精品自在自线在免费 | 久草在线视频在线观看 | 国产区一区二 | 伊人婷婷色 | 久久久免费视频观看 | 狠狠色噜噜狠狠狠狠97影音先锋 | 亚洲在线网站 | 四虎永久免费最新在线 | 久久久99精品免费观看精品 | 久久青青草视频 | 毛片视频播放 | 一级午夜 | 天天综合天天做天天综合 | 亚洲精品第四页中文字幕 | 免费一区二区三区四区五区 | 欧美99热| 伊人狠狠丁香婷婷综合色 |