緩存反向代理-Varnish

来源:https://www.cnblogs.com/walk1314/archive/2018/09/10/9606225.html
-Advertisement-
Play Games

簡介 Varnish是一款高性能、開源的緩存反向代理伺服器。它從客戶端接受請求,並嘗試從緩存中響應請求,如果無法從緩存中提供響應,Varnish 向後端伺服器發起請求,獲取響應,將響應存儲在緩存中,然後把響應發送給客戶端。如果Varnish能夠從Cache中響應一個請求,所消耗的時間是微秒級別的,這 ...


簡介

Varnish是一款高性能、開源的緩存反向代理伺服器。它從客戶端接受請求,並嘗試從緩存中響應請求,如果無法從緩存中提供響應,Varnish 向後端伺服器發起請求,獲取響應,將響應存儲在緩存中,然後把響應發送給客戶端。如果Varnish能夠從Cache中響應一個請求,所消耗的時間是微秒級別的,這個響應速度比直接從HTTP伺服器響應請求的速度要快兩個數量級,緩存命中率越高,網站的訪問速度就越快。

主要特性

  • 緩存位置:可以使用記憶體也可以使用磁碟,如果要使用磁碟的話推薦SSD做RAID1;
  • 日誌存儲:日誌也存儲在記憶體中,存儲策略:固定大小,迴圈使用;
  • 支持虛擬記憶體的使用;
  • 有精確的時間管理機制,即緩存的時間屬性控制;
  • 狀態引擎架構:在不同的引擎上完成對不同的緩存和代理數據進行處理,可以通過特定的配置語言設計不同的控制語句,以決定數據在不同位置以不同方式緩存;
  • 緩存管理:以二叉堆格式管理緩存數據,做到數據的及時清理。

系統架構

Varnish主要有兩個進程:Management進程與Child進程(也稱為Cache進程)。

  • Management進程:主要對子進程進行管理,實現應用新的配置、編譯VCL、監控varnish、初始化varnish以及提供一個命令行介面等;Management進程會每隔幾秒鐘探測一下Child進程以判斷其是否正常運行,如果在指定的時長內未得到Child進程的回應,Management將會重啟此Child進程。
  • Child進程:生成線程池,負責對用戶請求進行處理,並通過hash查找返回用戶結果。

    Child進程包含多種類型的線程,常見的有:

    • Accept線程:接收新的連接請求並響應;
    • Worker線程:child進程會為每個會話啟動一個worker線程,因此在高併發的場景中可能會出現數百個worker線程甚至更多;
    • Object Expiry線程:從緩存中清理過期內容;
    • Commad line線程 : 管理介面;
    • Storage/hashing線程:緩存存儲;
    • Log/stats線程:日誌管理線程;
    • Backend Communication線程:管理後端主機線程。

日誌

為了與系統的其它部分進行交互,Child進程使用可以通過文件系統介面進行訪問的共用記憶體日誌(shared memory log),因此如果某線程需要記錄信息,其僅需要持有一個鎖,而後向共用記憶體中的某記憶體區域寫入數據,再釋放持有的鎖即可;需要註意,為了減少競爭,每個worker線程都使用了日誌數據緩存。

共用記憶體日誌大小一般為90M,其分為兩部分,前一部分為計數器,後半部分為客戶端請求的數據。Varnish提供了多個不同的工具,如varnishlog、varnishncsa或varnishstat等來分析共用記憶體日誌中的信息並能夠以指定的方式進行顯示。

演算法

Varnish的Director支持的挑選方法中主要有round-robin(輪詢)和random(隨機)兩種。其中,round-robin類型沒有任何參數,只需要為其指定各後端主機即可,併在某後端主機故障時不再將其視作挑選對象;random方法隨機從可用後端主機中進行挑選,每一個後端主機都需要一個.weight參數指定其權重,同時還可以使用.retires參數來設定查找一個健康後端主機時的嘗試次數。

Varnish2.1.0後,random挑選方法又多了兩種變化形式client和hash。client類型的Director使用client.identity作為挑選因數,這意味著client.identity相同的請求都將被髮送至同一個後端主機;client.identity預設為cliet.ip,但也可以在VCL中將其修改為所需要的標識符。類似地,hash類型的Director使用hash數據作為挑選因數,這意味著對同一個URL的請求將被髮往同一個後端主機,其常用於多級緩存的場景中。無論是client還hash,當其傾向於使用後端主機不可用時將會重新挑選新的後端其機。

VCL工具

Varnish Configuration Language(VCL),Varnish配置緩存策略的工具,它是一種基於“域”(domain specific)的簡單編程語言,可以使用運算符包括“ =、==、!、&& ”等,支持使用正則表達式進行字元串匹配,允許用戶使用set自定義變數,支持if判斷語句,也有內置的函數和變數等。VCL策略在啟用前,會由management進程將其轉換為C代碼,而後再由gcc編譯器將C代碼編譯成二進位程式,編譯完成後management負責將其連接至varnish實例,即child進程。

後端存儲

Varnish支持多種不同類型的後端存儲,這可以在varnishd啟動時使用-s選項指定。後端存儲的類型包括:

  • file:使用特定的文件存儲全部的緩存數據,並通過操作系統的mmap()系統調用,將整個緩存文件映射至記憶體區域(如果條件允許);
  • malloc:使用malloc()庫調用在varnish啟動時向操作系統申請指定大小的記憶體空間以存儲緩存對象;
  • persistent(experimental):與file的功能相同,但可以持久存儲數據(即重啟varnish數據時不會被清除),但仍處於測試階段。

Varnish無法追蹤某緩存對象是否存入了緩存文件,也就無從得知磁碟上的緩存文件是否可用,因此file存儲方法在varnish停止或重啟時會清除數據;而persistent方法的出現對此有了一個彌補,但persistent仍處於測試階段,其僅適用於有著巨大緩存空間的場景。

選擇使用合適的存儲方式有助於提升系統性。從經驗的角度來看,建議在記憶體空間足以存儲所有的緩存對象時使用malloc的方法,而file存儲有著更好的性能表現。需要註意的是,varnishd實際上使用的空間比使用-s選項指定的緩存空間更大,一般說來,其需要為每個緩存對象多使用差不多1K左右的存儲空間,這意味著,對於100萬個緩存對象的場景來說,其使用的緩存空間將超出指定大小1G左右。另外,為了保存數據結構等,varnish自身也會占去不小的記憶體空間。

為varnishd指定使用的緩存類型時,-s 選項可接受的參數格式如下:

  • malloc [size] 或 file [path [size [granularity]]] 或 persistent path size {experimental}

VCL內置函數

  • vcl_recv函數:用於接收和處理請求。當請求到達併成功接收後被調用,通過判斷請求的數據來決定如何處理請求。此函數一般以如下幾個關鍵字結束:
    • pass:進入pass模式,把請求控制權交給vcl_pass函數;
    • pipe:進入pipe模式,把請求控制權交給vcl_pipe函數;
    • error code [reason]:返回code給客戶端並放棄處理該請求;code是錯誤標識,例如200、405等;reason是錯誤提示信息。
  • vcl_pipe函數:此函數在進入pipe模式時被調用,用於將請求直接傳遞至後端主機,在請求和返回的內容沒有改變的情況下,將不變的內容返回給客戶端,直到這個鏈接關閉。此函數一般以如下幾個關鍵字結束:
    • error code [reason]
    • pipe
  • vcl_pass函數:此函數在進入pass模式時被調用,用於將請求直接傳遞至後端主機,後端主機應答數據後送給客戶端,但不進行任何緩存,在當前連接下每次都返回最新的內容。此函數一般以如下幾個關鍵字結束:
    • error code [reason]
    • pass
  • vcl_hash:表示在緩存里查找被請求的對象,並且根據查找的結果把控制權交給函數vcl_hit或者函數vcl_miss
  • vcl_hit函數:在執行vcl_hash後,如果在緩存中找到請求的內容,將自動調用該函數。此函數一般以如下幾個關鍵字結束:
    • deliver:表示將找到的內容發送給客戶端,並把控制權交給函數vcl_deliver
    • error code [reason]
    • pass
  • vcl_miss函數:在執行val_hash後,如果沒有在緩存中找到請求的內容時自動調用該方法,此函數可以用於判斷是否需要從後端伺服器取內容。此函數一般以如下幾個關鍵字結束:
    • fetch:表示從後端獲取請求的內容,並把控制權交給vcl_fetch函數
    • error code [reason]
    • pass
  • vcl_fetch函數:在從後端主機更新緩存並且獲取內容後調用該方法,接著,通過判斷獲取的內容來決定是否將內容放入緩存,還是直接返回給客戶端。此函數一般以如下幾個關鍵字結束:
    • error code [reason]
    • pass
    • deliver
  • vcl_deliver函數:在緩存中找到請求的內容後,發送給客戶端前調用此方法。此函數一般以如下幾個關鍵字結束:
    • error code [reason]
    • deliver
  • vcl_timeout函數:此函數在緩存內容到期前調用。一般以如下幾個關鍵字結束:
    • discard:表示從緩存中清除該內容。
    • fetch
  • vcl_discard函數:在緩存內容到期後或緩存空間不夠時,自動調用該方法。此函數一般以如下幾個關鍵字結束:
    • keep:表示將內容繼續保留在緩存中
    • discard

以下是VCL處理流程圖,通過下圖可以更清楚Varnish的工作過程:

Varnish處理 HTTP請求 的過程分為以下幾個步驟:

  • Receive狀態,也就是請求處理的入口狀態,根據VCL規則判斷該請求應該Pass或Pipe,或者進入Lookup(本地查詢);
  • PIPE狀態,不可緩存數據,直接管道後端處理;
  • Lookup狀態,進入此狀態後,會在hash表中查找數據,若找到,則進入Hit狀態,否則進入miss狀態;
  • Pass狀態,在此狀態下,會進入後端請求,即進入Fetch狀態;
  • Fetch狀態,在Fetch狀態下,對請求進行後端獲取,發送請求,獲得數據,併進行本地存儲;
  • Deliver狀態,將獲取到的數據發送給客戶端,然後完成本次請求。

VCL內置公用變數

  • 當請求到達後,可以使用的公用變數如下所示:
    • req.backend:指定對應的後端主機
    • server.ip:表示伺服器端IP
    • client.ip:表示客戶端IP
    • req.request:指定請求的類型,例如GET、HEAD、POST等
    • req.url:指定請求的地址
    • req.proto:表示客戶端發起請求的HTTP協議版本
    • req.http.header:表示對應請求中的http頭部信息
    • req.restarts:表示請求重啟的次數,預設最大值為4
  • Varnish 在向後端主機請求時,可以使用的公用變數如下所示:
    • beresp.request:指定請求的類型,例如GET、HEAD等
    • beresp.url:指定請求的地址
    • beresp.proto:表示客戶端發起請求的HTTP協議版本
    • beresp.http.header:表示對應請求中的http頭部信息
    • beresp.ttl:表示緩存的生存周期,也就是cache保留多長時間,單位是秒
  • 從cache或者後端主機獲取內容後,可以使用的公用變數如下所示:
    • obj.status:返回內容的請求狀態代碼,例如200、302、504等
    • obj.cacheable:返回的內容是否可以緩存,也就是說,如果HTTP返回是200、203、300、301、302、404、410等,並且有非0的生存期,則可以緩存
    • obj.valid:表示是否是有效的HTTP應答
    • obj.response:返回內容的請求狀態信息
    • obj.proto:返回內容的HTTP協議版本
    • obj.ttl:返回內容的生存周期,也就是緩存時間,單位是秒
    • obj.lastuse:返回上一次請求到現在的間隔時間,單位是秒
  • 對客戶端應答時,可以使用的公用變數如下所示:
    • resp.status:返回客戶端的HTTP狀態代碼
    • resp.proto:返回客戶端的HTTP協議版本
    • resp.http.header:返回客戶端的HTTP頭部信息
    • resp.response:返回客戶端的HTTP狀態信息

  如果想要瞭解更多請查閱Varnish官方文檔 查看文檔


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 方法是什麼 方法是C#中將一堆代碼進行進行重用的機制 他是在類中實現一種特定功能的代碼塊,將重覆性功能提取出來定義一個新的方法 這樣可以提高代碼的復用性,使編寫程式更加快捷迅速 方法格式 訪問修飾符 返回類型 方法名稱(參數列表) { 方法體; } 方法是在類或結構中聲明的,聲明時需要訪問修飾符、返 ...
  • 記得前面老周寫過在.net core 中使用 Composition 的爛文。上回老周給大伙伴們介紹的是一個“重量級”版本—— System.ComponentModel.Composition。應該說,這個“重量級”版本是.NET 框架中的“標配”。 很多東西都會有雙面性,MEF 也一樣,對於擴展 ...
  • Docker 相關的基礎知識點非常多,比如基本概念,鏡像管理,數據捲(容器)管理,常用命令,周邊生態等等。在這裡梳理出個大概框架,方便後續學習使用。《Docker 遇見前端》系列文章,旨在分享學習如何通過 docker 構建一個相對完備的前端自動化開發環境。 ...
  • 儘管Linux系統非常強大,穩定,但是我們在使用過程當中,如果人為操作不當,仍然會影響系統,甚至可能使得系統無法開機,無法運行服務等等各種問題。那麼這篇博文就總結一下一些常見的故障排除方法,但是不可能面面俱到,只能不斷的補充,更新。 一、管理員忘記密碼 (1)、重啟電腦,進入單用戶模式 1 2 3 ...
  • Linux 中採用了兩種不同的優先順序範圍,一種是 nice 值,一種是實時優先順序。在上一篇粗略的說了一下 nice 值和實時優先順序,仍有不少疑問,本文來詳細說明一下進程優先順序。linux 內核版本為 linux 2.6.34 。 進程優先順序的相關信息,存放在進程描述符 task_struct 中: ...
  • core dump 某些信號的產生會導致產生core dump,包含了進程終止時的記憶體鏡像。在某些時候這個core文件就非常的有用處,配合gdb或者lldb調試起來非常方便。 更詳細的文檔參考 Linux Manual Page http://man7.org/linux/man pages/man ...
  • 第1章 SSH基本概述 1.1 SSH服務協議說明 SSH 是 Secure Shell Protocol 的簡寫,由 IETF 網路工作小組(Network Working Group )制定 在進行數據傳輸之前,SSH先對聯機數據包通過加密技術進行加密處理,加密後在進行數據傳輸。確保了傳遞的數據 ...
  • 修改windows server的機器名的時候,發現change按鈕是disable的。 手動修改不了,用註冊表regedit來修改。 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerNam ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...