Squid合并回源技术
http://blog.chinaunix.net/uid-8474831-id-3830240.html
1. 合并回源的概念
對于CDN的cache服務(wù)器而言,減少回源,提高命中率是一個重要的功能,尤其是在處理大文件的時候。這次我們就講一講squid是怎樣讓盡可能多的對于相同url的請求共用同一個回源請求的。
當(dāng)然,如果一個object已經(jīng)完整地存在了squid的磁盤上,在它過期之前是不會回源的。我們要討論的是正在從原站下載過程中的object,當(dāng)另外一個客戶端來下載它的時候。其他cache軟件可能會忽略當(dāng)前正在下載的object,而另起一個回源請求去下載。這樣的話,在第一個客戶端完整地下完這個object的時候,cache會回源多次。而squid則可以將這些請求合并起來,用一個回源請求服務(wù)所有的客戶端。
2. Squid的store_client層
Squid合并回源請求,主要靠的就是store_client層。
Store_client層的工作原理是:當(dāng)有多個request請求文件的不同部分時,store_client層會對他們采取不同的處理。
圖1表示一個1G的object被多個請求同時訪問的情形。
request1是第一個訪問這個object的請求,由他發(fā)起了回源,現(xiàn)在回源已經(jīng)下載了200M的內(nèi)容;
request2是一個從頭開始的請求,它開始得比較晚,只請求了100M
request3是一個range請求,它請求的是還沒有從原站下到的部分;
?
圖 ?1
?
注意,雖然是request1發(fā)起了回源,但回源請求并不是request1本身,而是由fwdStart函數(shù)發(fā)起的一個單獨的回源請求。即使request1斷掉了,回源也是可以繼續(xù)的,直到下載完整個object為止。
這3個請求都要通過store_client層的storeClientCopy函數(shù)從store拿數(shù)據(jù)。
2.1 數(shù)據(jù)從內(nèi)存來
request1的copy_offset是199M,而從150M到200M的數(shù)據(jù)全都在內(nèi)存里,因此它進(jìn)入的分支在storeClientCopy3函數(shù)里,它是:
直接就用stmemCopy將內(nèi)存中的數(shù)據(jù)copy到sc->copy_buf中,然后storeClientCallback回調(diào)客戶端的函數(shù)(其實就是clientSendMoreData)。可以看到,根本不需要讀磁盤。
2.2????? 數(shù)據(jù)從磁盤來
request2的copy_offset是100M,比inmem_lo要低,它進(jìn)入的分支很簡單,就是storeClientCopy3函數(shù)的最后一行:
storeClientFileRead顧名思義,就是去讀文件了。
storeClientFileRead會調(diào)用storeRead,進(jìn)入多線程的aufs異步io,拿到文件內(nèi)容之后還是會調(diào)用storeClientCallback回調(diào)。
2.3????? 數(shù)據(jù)還在原站
request3很顯然,數(shù)據(jù)在磁盤和內(nèi)存都沒有。所以它所能做的就是等待了。它的分支是
點擊(此處)折疊或打開
既沒有讀磁盤,也沒有讀內(nèi)存,就return掉了。那么什么時候這個客戶端會繼續(xù)呢?就是當(dāng)回源鏈接每從原站讀到一塊數(shù)據(jù),會調(diào)用storeAppend,進(jìn)而調(diào)用InvokeHandler,由于request2的store_client是當(dāng)前storeEntry的client之一,invokeHandler會對request2的store_client重新調(diào)用storeClientCopy2和storeClientCopy3,如果到了那個時候它所需要的數(shù)據(jù)在內(nèi)存或硬盤了,客戶端就會繼續(xù)收到數(shù)據(jù)。
?
3.??? 折疊回源機制collapsed_forwarding
剛才說的是store_client層,它的作用是,管理已經(jīng)在訪問同一個object的所有客戶端,讓他們?nèi)〉礁髯孕枰臄?shù)據(jù)。
那么,怎樣讓所有的客戶端訪問到同一個object呢?
squid會為每一個object創(chuàng)建一個StoreEntry結(jié)構(gòu),并放到store_hash這個哈希表中,供后來的request查找。當(dāng)request1從原站下載到了數(shù)據(jù)時,它的StoreEntry肯定是已經(jīng)創(chuàng)建好了。這個階段要讓其他請求找到這個object是很容易的。
但問題就是request1的客戶端請求已經(jīng)發(fā)到了squid,而原站數(shù)據(jù)還沒有下載到的這個期間,如果其他請求來了怎么辦呢?其實squid為這個問題引入了一個配置項,叫做collapsed_forwarding,可以on或者off。這個配置項的意思就是,所有請求共用一個回源請求。
3.1 collapsed_forwarding on
當(dāng)配制成on的時候,只要request1的客戶端請求發(fā)到了,這時候url也知道了,就立即創(chuàng)建它的StoreEntry,并放到hash表中。即使回源的數(shù)據(jù)還沒拿到,其他請求也能找到它的StoreEntry。
但是,這時候就有一個問題了,萬一request1請求的是動態(tài)內(nèi)容怎么辦?難道讓其他請求也拿到跟request1一樣的內(nèi)容么?
當(dāng)然不會!squid在clientCacheHit中做了防范。clientCacheHit是當(dāng)一個回調(diào)函數(shù),在請求hit了,并拿到reply頭的時候由storeClientCallback回調(diào)。
假如request2就是一個這樣的請求,它發(fā)生在在request1拿到原站的數(shù)據(jù)之前,并找到了request1創(chuàng)建的StoreEntry,而且“以為”自己hit了。而回源的reply中有Cache-Control:no-cache,那么當(dāng)request2在進(jìn)入clientCacheHit時,它找到的StoreEntry中一定會有RELEASE_REQUEST這個標(biāo)識。這個標(biāo)識是httpCachableReply函數(shù)發(fā)現(xiàn)no-cache之后設(shè)置的。當(dāng)發(fā)現(xiàn)這個標(biāo)識的時候,就會從clientCacheHit轉(zhuǎn)入clientProcessMiss,重新回源,不會跟request1取到相同的數(shù)據(jù)。代碼如下
?
3.2????? collapsed_forwarding off
當(dāng)配制成off的時候,與on相反,當(dāng)request1發(fā)過來的時候,不立刻將 StoreEntry放到hash表中,只有當(dāng)回源請求拿到了reply頭,確認(rèn)是可緩存的內(nèi)容后,才將StoreEntry放到hash表中。
雖然回源拿到響應(yīng)頭的時間通常很短,但終究有可能發(fā)生“誤會”,request1和request2都回源了。那么這種情況下會不會兩個回源請求產(chǎn)生沖突,比如寫同一個cache文件之類的問題呢?
其實也不會。squid對這種情況也做了防范。
在發(fā)現(xiàn)一個object可緩存時,會調(diào)用httpMakePublic,進(jìn)而調(diào)用StoreSetPublicKey。StoreSetPublicKey主要是負(fù)責(zé)將一個StoreEntry放入hash表。這時候它會先檢查hash表中是否已經(jīng)有了key相同的object,如果有,要先刪除舊的再插入新的。
刪除舊的object之后,request1和request2的回源都不會停止,以保證客戶端下到完整的數(shù)據(jù)。
那么,它們會不會寫到相同的文件里呢?
還是不會。因為squid為新的object分配文件名不是直接將key轉(zhuǎn)換為文件名,而是用一個filebitmap來分配一個文件號,用這個文件號來生成文件名。分配過的文件號是不會被再次分配出去的。
還有最后一個問題,就算文件名不同,request1回源取到的數(shù)據(jù)還會不會被寫到磁盤上呢?
看到這里,你會知道squid是很聰明的,所以答案當(dāng)然還是不會了。因為舊的entry一旦被打上RELEASE_REQUEST標(biāo),同時會清掉ENTRY_CACHABLE標(biāo),它的swapout就不會再進(jìn)行了。這是在storeSwapOutMaintainMemObject里保證的。
其中storeSwapOutAble的定義如下:
4. 思考題?
最后,請大家想一想,什么樣的業(yè)務(wù)模式適合collapsed_forwardingon,什么樣的適合off呢?
總結(jié)
以上是生活随笔為你收集整理的Squid合并回源技术的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python安装教程之anaconda篇
- 下一篇: android实现多画面播放,快手同框怎