CSDN助手源碼剖析(一)--緩存優化

一、引言

1、爲什麼,csdn的帖子後面要加個temp查詢字符串。
2、爲什麼,同一個帖子,“temp”查詢字符串會經常發生變化。
3、爲什麼,Internet緩存目錄會過度膨脹。

二、背景

  CSDN帖子採用xml文件進行存儲,下載時也直接下載xml文件。這樣做有許多好處。比如,1、實現數據與顯示的分離:數據的更新與顯示頁面的維護都非常方便;2、減少網絡傳輸:顯示頁面(xsl文件)只需要下載一次,數據文件(xml文件)也非常的短小,因此帖子打開顯示的速度很快。

  但使用xml文件同時要考慮一個緩存的問題。由於xml文件是一個靜態文件,當瀏覽器第一次訪問之後,會將其緩存至臨時目錄,下一次訪問時,可能不會再訪問服務器,而直接從緩存讀取。如果在真實的URL地址後面加上臨時的、隨機的查詢字串,那麼瀏覽器通過這個URL在緩存中找不到,就會訪問服務器,讀取最新的數據。

  大家可以測試一下,隨便在“temp=”後面輸入任何數字,或直接將“temp=”刪除,都會訪問到xml文件。爲了保證用戶總是能通過不同的URL訪問最新的帖子,至少存在以下兩個機制:

  1. 不直接提供形如“xml?temp=xxxx”的URL(簡稱“地址A”),而是提供形如“topicview1.asp?id=4854274”的URL(簡稱“地址B”)。地址B,瀏覽器不緩存,總是能訪問服務器,而服務器則根據需要生成隨機的地址A,傳給瀏覽器,通過重定向,取得最新的xml文件。
  2. 爲了避免頻繁的改變地址A,至少當帖子更新後,必須重新生成一個temp查詢字符串。

 三、兩難境地

  基於以上的分析,訪問同一個帖子,將會對應地產生多個地址A,也就會在瀏覽器的臨時目錄中緩存多個帖子副本。顯然,只有最後一個副本有意義(脫機時),以前的是多餘的,不再可能被訪問的。可能有人會想,爲什麼不通過在服務器端設置頭部“Cache-Control:no-cache”,從而阻止瀏覽器緩存xml文件呢?一個簡單的理由是,爲了支持在脫機時能夠訪問以前訪問過的xml文件,必須使用緩存。

  於是,這將出現一個兩難境地。如果爲了節約緩存,那麼就不會使用“temp”這項技術,就有可能不能訪問最新的數據;如果爲了總是能訪問到最新的數據,就會在臨時目錄緩存大量重複的數據。

四、解決方案

  “CSDN助手”通過一個橋接技術,很好的解決了這個“兩難問題”。
舉例:
地址A:http://community.csdn.net/Expert/topic/4854/4854274.xml?temp=.5251428
地址B:http://community.csdn.net/expert/topicview1.asp?id=4854274
地址C:http://community.csdn.net/expert/cache/4854274.xml

  1. 截獲瀏覽器對“地址A”和“地址B”的訪問,通過URL Moniker技術,自己訪問服務器,取得數據文件後,以“地址C”的名義緩存至臨時目錄。這樣,當瀏覽器再次訪問“地址A”和“地址B”時,由於在緩存中找不到,所以仍然會再次訪問服務器。而“地址C”針對同一個帖子是唯一的,所以確保緩存中只有唯一的副本。
  2. 怎樣支持脫機:截獲瀏覽器對“地址A”和“地址B”的訪問,先判斷是否處於脫機狀態。如不是,則進行步驟1;如是,則通過“地址C”在緩存中找到副本直接打開。

五、URL Moniker

  前面講到,截獲瀏覽器對“地址A”和“地址B”的訪問,自己訪問服務器,從而有效的控制緩存的處理。自己訪問服務器,讀取數據文件,可以有多種技術。我們分析一下他們的特點,決定到底用哪一種技術:

  1. Socket函數:最底層(也是相對而言)的訪問方法,需要構造Request,分解Response,需要編碼、解碼,而且不支持系統提供的通過代理訪問服務器的能力。
  2. wininet函數:系統級的函數,支持代理,靈活性強,但考慮的細節過多。
  3. Msxml2.XMLHTTP組件:封裝了許多細節,調用方便,但不支持客戶端對緩存的控制。有許多人在進行Ajax開發時,對這個組件“不支持客戶端緩存控制”的特點頗有微詞。對緩存的控制,經常需要服務器的配合。顯然,開發“CSDN助手”不應該對服務器要求過多。
  4. URL Moniker對象:URL Moniker提供了一種建立並使用URL的框架,初次接觸時感覺不太好理解,但實際上很好控制,支持代理,支持客戶端的緩存控制,相對wininet函數而言,細節比較少。

  事實上,在“CSDN助手”的早期版本,由於沒有過多考慮“緩存優化”的細節,採用了“Msxml2.XMLHTTP組件”進行數據的讀取。由於組件的自身限制,不得不在其他的幾項技術中選中了“URL Moniker對象”。

  關於“URL Moniker對象”的實現細節,請參考

CSDN助手源碼剖析(二)--URL Moniker的封裝

六、相關函數

  爲節省篇幅,下面僅列出主要的函數與方法,便於“下斷點跟蹤”,源碼下載請轉到:http://blog.csdn.net/seasol/archive/2006/07/04/873747.aspx

  1. function fn_shell_callback(oWindow,oUrl,oTarget)
    位於“程序集/CSDNAssist/default.asps”文件中,用於截獲瀏覽器對“地址A”和“地址B”的訪問。
  2. CCSDNTools::topicviewPrecheck(BSTR bstrURL, BSTR* pbstrValue)
    檢測是否處於脫機狀態,如果是,則直接返回緩存中的副本。
  3. CCSDNTools::topicview(BSTR bstrUrl,VARIANT varDisp, BSTR bstrTarget, long nType,IDispatch* pDispCallback)
    啓動帖子的異步下載。
  4. CCSDNTools::func_topicviewResponseProc(void* pParam1,CParam_Http_Base* pParam2,CCuteHttpBase* pHttpBase,IStream* pStream)
    當帖子下載完成時調用的回調函數。
  5. CCSDNTools::SaveToCache(IStream* pStream,LPCTSTR szUrl,LPCTSTR szUrlCache,LPCTSTR szTopicID,CString& sCacheFile)
    將帖子緩存至Internet臨時目錄。

   

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章