主頁 > 服務器技術 > 高負載網站之Varnish與Drupal – 基本篇

高負載網站之Varnish與Drupal – 基本篇

PDF版本

varnish作為一款優秀的反向代理服務器以及緩存服務器,已經越來越流行,本文就Varnish的基本使用以及如何與drupal合作使用,做一個簡要清單。

安裝
推薦使用系統自帶的源安裝,比如apt或者yum。

結構
/etc/varnish/ 存放varnish VCL配置文件
/etc/sysconfig/varnish 【CentOS】 存放varnish服務器運行的參數
/etc/default/varnish 【Ubuntu】 存放varnish服務器運行的參數
/usr/sbin/varnishd varnish服務器執行文件
/etc/init.d/varnish 運行程序

相關命令
這里列舉一下比較有用的幾個varnish管理命令

varnishadm 管理Varnish后端的工具 telnet也可以(下面詳細介紹)
varnishhist 查看Varnish命中的工具 運行可以看到一張柱狀描繪圖,|表示緩存命中,#表示未命中,橫向代表時間。 【非常有用】
varnishlog 實時顯示varnish的請求日志
varnishncsa 以Apache標準的格式combined輸出日志
varnishstat 查看狀態、參數等,具體查閱百度。【非常有用】
varnishtop 類似top工具,查看varnish相關進程的資源、運行等狀況。

varnishncsa 將Varnish的log以Apache的格式輸出,varnishlog以原始方式顯示Varnish的日志。我們知道varnish默認會把日志存放在內存中,如果我們要把日志存放起來,就需要你啟動一個守護進程,把內存中的日志存放到文件中。

Varnish — (http)—> Backend servers
|
|–> (Daemon) varnishncsa/varnishlog === (write) ==> Log Files

管理varnish以及清除內存等操作雖然可以使用varnishadm,但是這里推薦使用telnet,一個交互的管理界面。

比如: telnet 127.0.0.1 6082
之后,輸入help會顯示所有可用命令。

help [command]
ping [timestamp]
status
start
stop
stats
vcl.load
vcl.inline
vcl.use
vcl.discard
vcl.list
vcl.show
param.show [-l] []
param.set
quit
purge.url
purge.hash
purge    [&&   ]...
purge.list

重新加載Varnish配置文件

telnet 127.0.0.1 6082
vcl.load newconfig /data/app/varnish/etc/varnish/default.vcl
vcl.use newconfig

注意:varnish 的CLI可能需要認證,最簡單的辦法就是在varnish啟動的時候取掉相應的參數。

-S /etc/varnish/secret \

參考?https://www.varnish-cache.org/docs/trunk/reference/varnish-cli.html

 

Varnish的緩存方式
Malloc (malloc) 通過 malloc 獲取內存,簡單,速度快
Mmap file (file) 創建文件緩存
這個是varnish緩存的兩種方式,可以在啟動的時候通過參數指定。

Varnish處理流程

首次請求時過程如下:
recv->hash->miss->fetch->deliver
緩存后再次請求:
recv->hash->hit->deliver(fetch的過程沒了,這就是我們要做的,把要緩存的頁面保存下來)
直接交給后端pass的情況:
recv->hash->pass->fetch->deliver(直接從后端獲取數據后發送給客戶端,此時Varnish相當于一個中轉站,只負責轉發)

VCL以及基本對象

request 從客戶端進來
responses 從后端服務器過來
object 存儲在cache中

VCL語言
req 請求目標,當varnish接收到一個請求,這時req object就被創建了,你在vcl_recv中的大部分工作,都是在req object上展開的。
beresp 后端服務器返回的目標,它包含返回的頭信息,你在vcl_fetch中的大部分工作都是在beresp object上開展的。
obj 被cache的目標,只讀的目標被保存于內存中,obj.ttl的值可修改,其他的只能讀。

VCL支持一下運算符
= 賦值運算符
== 對比
~ 匹配,在ACL中和正則表達式中都可以用
! 否定
&& 邏輯與
|| 邏輯或

Grace mode

如果后端需要很長時間來生成一個對象,這里有一個線程堆積的風險。為了避免這 種情況,你可以使用 Grace。他可以讓 varnish 提供一個存在的版本,然后從后端生成新 的目標版本。
當同時有多個請求過來的時候,varnish只發送一個請求到后端服務器,在“set beresp.grace = 30m; ”時間內復制舊的請求結果給客戶端。

Saint mode
有時候,服務器很古怪,他們發出隨機錯誤,您需要通知 varnish 使用更加優雅的方式處理 它,這種方式叫神圣模式(saint mode)。Saint mode 允許您拋棄一個后端服務器或者另一 個嘗試的后端服務器或者 cache 中服務陳舊的內容。

sub vcl_fetch {
 if (beresp.status == 500) {
  set beresp.saintmode = 10s;
  restart;
 }
 set beresp.grace = 5m;
}

Varnish代理

########
backend default {
  .host = "192.168.0.12";
  .port = "8080";
}
#現在添加一個新的backend服務器
backend test {
  .host = "192.168.0.12";
  .port = "8000";
}
#要定義特殊的url被發送到哪里
sub vcl_recv {
  if (req.url ~ "^/abcd/") {
    set req.backend = test;
  } else {
    set req.backend = default;
  }
}

Varnish負載均衡
可以把多臺 backends 聚合成一個組,這些組被叫做directors。這樣可以增強性能和彈力。您可以定義多個backends和多個group在同一個directors。

backend server1 {
    .host = "192.168.0.1" ;
    .port = "8080" ;
}
backend server2 {
    .host = "192.168.0.2" ;
    .port = "8080" ;
}
director drupal001 round-robin {
    { .backend = server1; }
    { .backend = server2; }
}
sub vcl_recv {
   if (req.http.host !~ "www\.drupal001\.com$"){
      error 404 "Unknown HostName!";
    }
    set req.backend = drupal001;
 }

健康檢查
在之前的兩個后端服務器上加上健康檢查。

backend server1 {
    .host = "192.168.0.1" ;
    .port = "8000" ;
    .probe = {
      .url = "/";       #哪個 url需要varnish請求。
      .interval = 5s;   #檢查的間隔時間。
      .timeout = 1 s;   #等待多長時間探針超時。
      .window = 5;      #維持5個sliding window的結果。
      .threshold = 3;   #至少有三次window是成功的,就宣告bachend健康。
     }
}

注意事項:
1. Varnish的不同版本的配置不同,必須查閱官方文檔。
比如,在2.x 直接用ESI表示啟用ESI,在3.x就不是了。
2. Varnish 2.x有Cookie的問題,當Cookie過大,會產生503錯誤,升級varnish或者減少set_cookie的操作。
3. 啟動varnishd的時候如果選用-s file方式,每次會重新建立緩存文件,而原來的文件不會刪除,因此注意清除這些遺留文件。

注釋完整的一段VCL文件參考

#設置后端服務器地址
backend default {
     .host = "127.0.0.1";
     .port = "80";
}
 
#允許刷新緩存的ip
acl purgeAllow {
     "localhost";
     "192.168.56.1";
}
 
sub vcl_recv {
     #刷新緩存設置
     if (req.request == "PURGE") {
          #判斷是否允許ip
          if (!client.ip ~ purgeAllow) {
               error 405 "Not allowed.";
          }
          #去緩存中查找
          return (lookup);
     }
 
     #首次訪問增加X-Forwarded-For頭信息,方便后端程序
     #獲取客戶端ip
     if (req.restarts == 0) {
          #如果設置過此header則要再次附加上,用,隔開,如果
          #只有一層代理的話,就無需設置了
          if (req.http.x-forwarded-for) {
               set req.http.X-Forwarded-For =
                    req.http.X-Forwarded-For ", " client.ip;
          }
          #沒有則要加上
          else {
               set req.http.X-Forwarded-For = client.ip;
          }
     }
 
     #修正客戶端的Accept-Encoding頭信息,默認選用gzip方式
     #防止個別瀏覽器發送類似 deflate, gzip
     #當然后端如果只支持gzip的話.可以只設置gizp
     if (req.http.Accept-Encoding) {
          if (req.http.Accept-Encoding ~ "gzip") {
               set req.http.Accept-Encoding = "gzip";
          }
          #如果后端支持deflate方式,建議去掉,否則刷新緩存時
          #需特殊處理
          elsif (req.http.Accept-Encoding ~ "deflate") {
               set req.http.Accept-Encoding = "deflate";
          }
          #其他的壓縮方式忽略
          else {
               remove req.http.Accept-Encoding;
          }
     }
 
     #靜態文件和明確以.php結尾的url無需緩存, 建議把靜態文件分離
     #至單獨服務器下,減少動態應用服務器壓力,同時降低arnishd的壓力
     if(req.url ~ "\.(png|gif|jpg|css|js|php)$"){
          return (pass);
     }
 
     #非正規的請求直接轉發給后端服務器
     if (req.request != "GET" &&
          req.request != "HEAD" &&
          req.request != "PUT" &&
          req.request != "POST" &&
          req.request != "TRACE" &&
          req.request != "OPTIONS" &&
          req.request != "DELETE") {
          /* Non-RFC2616 or CONNECT which is weird. */
          return (pipe);
     }
 
     #只處理GET和HEAD請求,如果你不想緩存POST的頁面話
     if (req.request != "GET" && req.request != "HEAD") {
          return (pass);
     }
     #http認證的頁面也pass
     if (req.http.Authorization) {
          return (pass);
     }
 
     return (lookup);
}
 
#管道?按官方文檔說的是此模式下請求會原封不動的轉交給后端知道連接關閉
sub vcl_pipe {
     return (pipe);
}
 
#交給后端服務器
sub vcl_pass {
    return (pass);
}
 
#緩存文件名的哈希處理
sub vcl_hash {
     #以url為hash
     set req.hash += req.url;
     #加上host
     if (req.http.host) {
          set req.hash += req.http.host;
     }
     #沒有則取ip
     else {
          set req.hash += server.ip;
     }
     #支持壓縮的要增加,防止發送給不支持壓縮的瀏覽器壓縮的內容
     if(req.http.Accept-Encoding){
          set req.hash += req.http.Accept-Encoding;
     }
     return (hash);
}
 
#緩存命中后的處理
sub vcl_hit {
     #如果不可緩存,直接交給后端
     if (!obj.cacheable) {
          return (pass);
     }
     #如果為更新緩存的請求,則設置ttl為0,并告知客戶端處理結果
     if (req.request == "PURGE") {
          set obj.ttl = 0s;
          error 200 "Purged.";
     }
 
     return (deliver);
}
 
#緩存未命中
sub vcl_miss {
     #更新緩存的請求,提示緩存不存在Not in cache
     if (req.request == "PURGE") {
          error 404 "Not in cache.";
     }
     #既然緩存不存在了,就去后端取吧
     return (fetch);
}
#
sub vcl_fetch {
 
     #是否開啟ESI功能(僅做演示用,單獨給/esi-test.html開啟esi)
     if (req.url == "/esi-test.html") {
          esi;
     }
 
     #如果后端返回不可緩存,直接pass
     if (!beresp.cacheable) {
          return (pass);
     }
 
     #/article/下的url緩存30分鐘(演示用)
     if (req.url ~ "^/article/\d+\.html$"){
          set beresp.ttl = 30m;
     }
 
     #/category/下的url緩存20分鐘(演示用)
     if (req.url ~ "^/category/$"){
          set beresp.ttl = 20m;
     }
 
     #如果后端發送了set-cookie頭信息(如session會話開啟),則不緩存
     if (beresp.http.Set-Cookie) {
          return (pass);
     }
 
     return (deliver);
}
 
#發送給客戶端
sub vcl_deliver {
     #去掉varnish中的一些頭信息(如果你不想保留的話,建議保留Age,方便查看)
     #remove resp.http.X-Varnish;
     #remove resp.http.Via;
     return (deliver);
}
 
#定義錯誤頁面的信息
sub vcl_error {
     #設置返回頁面的類型及編碼
     set obj.http.Content-Type = "text/html; charset=utf-8";
     #具體內容,可以更加自己的需要修改錯誤提示信息
     synthetic {"
       HTTP ERROR
    "};
     return (deliver);
}

官方文檔
非常重要,必須參考。
https://www.varnish-cache.org/docs

官方示例 Example
https://www.varnish-cache.org/trac/wiki/VCLExamples

VCL2.x升級到3.0
https://www.varnish-cache.org/docs/3.0/installation/upgrade.html?

WIKI
https://www.varnish-cache.org/trac/?

drupal on Varnish
https://www.varnish-cache.org/trac/wiki/VarnishAndDrupal?

至此,基本的Varnish了解完畢,后面繼續討論ESI的使用,以及如何配合Drupal模塊構建高性能網站
待續…


聲明: 本站所有文章歡迎轉載,所有文章未說明,均屬于原創,轉載均請注明出處。
本文有效鏈接: http://www.vczhtn.live/2011/12/varnish-drupal-basic/
版權所有: Drupal與高性能網站架構 http://www.vczhtn.live


, , ,

發表評論

電子郵件地址不會被公開。 必填項已用 * 標注


九 − = 1

您可以使用這些 HTML 標簽和屬性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

引用:0

下面所列的是引用到本博客的鏈接
高負載網站之Varnish與Drupal – 基本篇 來自 Drupal與高性能網站架構
頂部
安徽福彩15选5走势图