菲爾Karlton曾經說過,“只有兩種計算機科學堅硬的東西:緩存失效和命名的東西”這篇文章是關于這兩個較硬的: 緩存失效 。 這是沖著誰的讀者已經與光油緩存工作。 要了解更多關于它,你會發現背景信息在“ 加快你的手機網站清漆 。“
10微秒(或者250毫秒):這是提供一個高速緩存命中和提供一個高速緩存未命中之間的差異。 “命中率” – 你怎么經常得到后者將取決于緩存的效率,這是被稱為緩存未命中取決于兩個因素:交通量和平均生存時間(TTL),這是一個數字,指示緩存多長時間允許保留的對象。 作為系統管理員和開發人員, 我們不能做很多有關交通的,但我們可以影響的TTL。
然而,有一個高的TTL,我們需要能夠從緩存中無效的對象,使我們避免提供陳舊的內容。 清漆緩存,有無數的方法可以做到這一點。 我們將探討最常見的方式,以及如何部署它們。
清漆做了一大堆其他的東西為好,但其緩存服務是最流行 ??的。 緩存由在職緩存的靜態內容加速Web服務 。 當光油緩存是提供一個高速緩存命中,它通常只是轉儲的內存塊插入插座。 清漆緩存是如此之快,以至于,在現代硬件上,我們實際上測量微秒響應時間!
當使用高速緩存,你需要知道什么時候從緩存中逐出內容。 如果你沒有辦法驅逐的內容,那么你會在預定的時間量后,依靠緩存超時的對象。 這是一種方法,但幾乎沒有最優化的解決方案。 最好的辦法是讓光油緩存保持對象在內存中永遠的(大部分),然后告訴該對象時刷新。 讓我們詳細討論如何實現這一點。
HTTP吹掃
HTTP吹掃是最直接的這些方法。 而不是發送的GET /url
到光油,你會送PURGE /url
。 清漆然后將丟棄該對象從緩存中。 訪問控制列表添加到光油,這樣不只是任何人都可以從緩存中清除的對象; 除此之外,雖然,你到家了自由。
acl purge { "localhost"; "192.168.55.0"/24; } sub vcl_recv { # allow PURGE from localhost and 192.168.55... if (req.request == "PURGE") { if (!client.ip ~ purge) { error 405 "Not allowed."; } return (lookup); } } sub vcl_hit { if (req.request == "PURGE") { purge; error 200 "Purged."; } } sub vcl_miss { if (req.request == "PURGE") { purge; error 200 "Purged."; } }
吹掃的缺點
HTTP清洗達不到時,一塊內容有復雜的關系,它出現在的URL。 新聞文章,例如,可能出現在多個網址。 這篇文章可能有一個桌面視圖和移動視圖,它可能出現在部分頁面,并在頭版。 因此,你必須要么得到的內容管理系統來跟蹤所有這些表現還是讓光油為你做它。 讓光油做到這一點,你會使用的禁令,我們將進入現在。
禁令
禁令是針對光油,一個是經常被誤解的功能。 它使您能夠從服務在內存中的某些內容禁止光油,迫使光油獲取這些頁面的新版本。
一個有趣的方面是如何規定禁止的頁面 。 清漆設有提供相當多的靈活性語言。 你能告訴光油禁止通過在命令行界面給人的禁令命令,通常連接到它與varnishadm
。 您也可以通過光油配置語言(VCL),它提供了實現基于HTTP的禁止一種簡單的方式做到這一點。
讓我們從一個例子。 假設我們需要清除本網站的所有圖像。
> ban obj.http.content-type ~ “^image/”
這樣做的結果是,在內存中的所有對象,HTTP響應頭Content-Type
將匹配正則表達式^image/
,它會立即失效。
下面是在上光油會發生什么。 首先,禁令命令會將有關禁令“封殺名單”。當這個命令是禁止列表中,每個高速緩存命中,供應對象年紀比禁令本身會開始看禁令名單和對象比較的禁止名單上。 如果對象匹配,那么光油殺死它并獲取較新的。 如果對象不匹配,那么光油會使它記下來,??這樣就不會再次進行檢查。
讓我們建立在我們的例子。 現在,我們只禁止那些在某處放置圖像/feature
的URL。 注意,邏輯“與”運算, &&
。
> ban obj.http.content-type ~ “^image/” && req.url ~ “^/feature”
你會發現,它說obj.http.content-type
和req.url
。 在禁令的第一部分中,我們將存儲在光油一個對象的屬性。 在后者中,我們指的對一個對象的請求的一部分。 這可能是一個有點不合常規,但實際上你可以使用屬性上的要求,在緩存中無效的對象。 現在, req.url
通常不存儲在對象,所以指的是要求是我們可以在這里做的唯一的事情,你可以用這個做瘋狂的事情 ,就像被要求由一個特定的客戶端的IP地址禁止的一切,或禁止一切所要求的Chromium瀏覽器。 由于這些要求打光油,對象是無效的,并從源服務器刷新。
依賴于請求發出禁令開辟了一些有趣的可能性。 不過,有一個缺點的過程:禁令的一個很長的名單可能放緩的內容交付。
有分配給縮短禁令的名單,“禁令潛行者”的任務,一個工作線程。 這項禁令潛行者試圖匹配適用對象的禁令。 當禁令已匹配年紀比自己所有的對象,它被丟棄。
通過禁令禁止潛行者迭代,它沒有,它試圖成為一個HTTP請求。 因此,依賴于從請求數據的任何禁止不能被禁止潛伏者進行測試。 為了保持禁令性能高達的話,我們會建議不使用的禁令請求數據。 如果你需要禁止的東西,通常是在請求中,如URL,您可以從請求中的數據復制到對象vcl_fetch
,像這樣:
set beresp.http.x-url = req.url;
現在,你就可以使用上禁止obj.http.x-url
。 請記住, beresp
對象變成obj
,因為它被存儲在高速緩存中。
標簽內容為禁令
當你給光油有點幫助禁令往往很多更為有效。 如果對象具有X-Article-id
頭,那么你并不需要知道所有的對象是作為的URL。
對于依賴幾個對象的頁面,你可以有內容管理系統增加一個X-depends-on
標題。 在這里,你會列出應觸發當前文檔的更新對象。 再次參加我們的新聞網站,你可以使用此列出頭版提到的所有的文章:
X-depends-on: 3483 4376 32095 28372
當然,那么,如果文章之一發生變化,你會發出禁令,像這樣:
ban obj.http.x-depends-on ~ “\D4376\D”
這是潛在的非常強大。 試想一下,通過觸發器使數據庫的問題這些無效宣告請求,從而消除了需要改變的中間件層。 整齊的,??是嗎?
優美的緩存失效
試想一下,清除的東西從上光油,然后這是應該更換突然死機的內容源服務器。 您剛剛扔掉的內容你唯一可行的副本。 你做了什么?! 原來,定期不少內容管理系統崩潰。
理想情況下,我們希望把對象在第三狀態 – 無效它我們能夠得到一些新的內容的條件。 這第三種狀態存在于清漆:它被稱為“寬限期”,它是使用基于TTL的廢票。 一個對象過期后,它被保存在內存中的情況下后端服務器崩潰。 如果光油不能談論到后端,然后它會檢查是否有任何寬限對象匹配,并且它提供的不是。
一光油模塊(或VMOD),命名為softpurge
,讓你的對象是放入的恩典狀態無效。 使用它很簡單。 只需更換PURGE
與使用VCL的VCL softpurge
VMOD。
import softpurge; sub vcl_hit { if (req.method == "PURGE") { softpurge.softpurge(); error 200 “Successful softpurge”; } } sub vcl_miss { if (req.method == "PURGE) { softpurge.softpurge(); error 200 "Successful softpurge"; } }
分發緩存失效事件
所有上面列出的方法描述了一個緩存服務器上的內容無效化的處理。 最嚴重的結構將有一個以上的上光油服務器。 如果你有兩個,應該給予足夠的魅力對于大多數的網站,那么你將要發出一份失效事件為每個服務器。 但是,如果你有20或30光油的服務器,那么你真的不希望通過一個巨大的服務器列表有它循環陷入癱瘓的應用。
相反,你會希望有一個單一的API終點,你可以把你的大清洗 ,有它的失效事件分發到所有的服務器上光油。 作為參考,這里是一個用shell腳本非常簡單無效的服務。 它將偵聽端口2000和無效的URL到三個不同的服務器( alfa
, beta
和gamma
使用cURL)。
nc -l 2000 | while true do read url for srv in “alfa” “beta” “gamma” do curl -m 2 -x $srv -X PURGE $url done done
它可能不適合生產,因為錯誤處理留下的東西不理想!
緩存失效幾乎是緩存同樣重要。 因此,具有健全的策略無效的內容是至關重要的維持高水平的性能,并具有較高的高速緩存命中率。 如果你保持較高的命中率,那么你就需要更少的服務器上,將有更快樂的用戶和可能減少停機時間。 有了這個,你是希望更舒適的使用這樣的工具,以獲得陳舊的內容了您的高速緩存。