緩存服務器Varnish

博文參考

http://www.178linux.com/76700
http://www.mamicode.com/info-detail-229142.html

Varnish簡介

varnish 是很是輕量級,也很強大的一款提供緩存服務的應用.高性能且開源的反向代理服務器和HTTP加速器;
clipboard.pngjavascript

varnish的配置是經過VCL緩存策略工具實現的,這個工具是一種簡單的編程語言,用戶能夠自定義變量、php

有好幾個內置的函數和變量,可是它的函數不支持接受參數,並且沒有返回值。使用VCL編寫的緩存策略一般保存至.vcl文件中,css

其須要編譯成二進制的格式後才能由varnish調用。事實上,整個緩存策略就是由幾個特定的子例程如vcl_recv、html

vcl_fetch等組成,它們分別在不一樣的位置(或時間)執行,若是沒有事先爲某個位置自定義子例程,varnish將會執行默認的定義。java

VCL策略在啓用前,會由management進程將其轉換爲C代碼,然後再由gcc編譯器將C代碼編譯成二進制程序,linux

因此varnish的安裝和運行依賴於gcc庫。編譯完成後,management負責將其鏈接至varnish實例,web

即子進程。編譯時會檢查語法是否有誤,避免了裝載錯誤語法的VCL。一但編譯完成而且沒有語法錯誤就會被裝載,正則表達式

同時能夠保存好幾份配置,當你以爲以前的配置策略更科學時,調用以前的配置便可. 只要調用庫中的配置策略,就可使規則生效,算法

無需重啓或者reload.因此修改配置策略的代價很小。配置的策略只有在varnish重啓時纔會清除,固然,也能夠手動清理,chrome

可使用varnishadm的vcl.discard命令完成。

varnish支持多種不一樣類型的後端存儲,這能夠在varnishd啓動時使用-s選項指定。後端存儲的類型包括:

(1)file:使用特定的文件存儲所有的緩存數據,並經過操做系統的mmap()系統調用將整個緩存文件映射至內存區域(若是內存夠大,條件容許); 能夠指定其所保存的位置,大小,以及緩存分配粒度, 即每次分配的大小,直到size大小爲止再也不分配.使用方法 file[,path[,size[,granularity]]]

(2)malloc:使用malloc()庫調用在varnish啓動時向操做系統申請指定大小的內存空間以存儲緩存對象; 使用方法malloc[,size]

(3)persistent(experimental):與file的功能相同,但能夠持久存儲數據(即重啓varnish數據時不會被清除);仍處於測試期,悲催,好不容易有一個能持久保存的,還不穩定;

varnish的進程分兩類,

管理進程, (master進程),其工做職責以下

1,讀入配置文件

2,調用合適的存儲類型 ,varnish支持將緩存寫入磁盤

3,建立/讀入相應大小的緩存文件 (可是這個功能還處於測試階段,建議暫時不要使用)

4,初始化管理,將緩存文件結構空間關聯到存儲結構體 ,以待分配,

5,fork出多個空閒子進程並監控各child進程

工做進程 (child子進程)

1,將前面打開的存儲文件整個mmap到內存

2,建立並實始化空閒的結構體,用來存儲緩存對象,

3,由諸多線程各司其職負責完成相關的工做:

主進程 fork 子進程,主進程等待子進程的信號,子進程退出後,主進程從新啓動子進程,子進程生成若干線程。

Accept 線程:接受請求,將請求分配到空閒子進程上,並讓空閒的work線程響應用戶請求

Work線程: work線程有多個,從隊列領取請求,並對請求處理,處理完成後,繼續領取下一個請求進行處理

work線程處理時,會讀取該請求的url, 以此斷定本地緩存中是否有該緩存對象命中,若是命中直接構建響應報文,

若是沒有,則去上游服務器查找數據,並緩存至本地再構建響應報文響應請求.

Epoll 線程: 一個請求處理稱做一個 session,在 session 週期內,處理完請求後,會交給 Epoll 處理,監聽是否還有事件發生。

Expire 線程:對於緩存的對象,根據過時時間,組織成二叉堆,該線程週期檢查該堆的根,處理過時的文件。

線程之間的關係:

worker:處理用戶請求

  accept: 接收用戶請求

當緩存空間耗盡:

須要清理緩存空間了,可使用LRU算法清理,(LRU指最近最少使用的)

緩存處理流程

clipboard.png

什麼是web cache?

Web緩存是指一個Web資源(如html頁面,圖片,js,數據等)存在與Web服務器和客戶端(瀏覽器)直接的副本。緩存會根據進來的請求保存輸出內容的副本;當下一個請求到來的時候,若是是相同的URL,緩存會根據緩存機制決定是直接使用副本響應訪問請求仍是向源服務器再次發送請求。 —–摘自Alloy Team

緩存命中率類型:

文檔命中率:按文檔數量進行衡量

字節命中率:按命中的字節數量進行衡量

緩存處理流程:

接受請求:接受來自client的訪問請求

解析請求:提取client訪問請求的URL中的頭部信息

查詢緩存:根據提取的頭部信息查詢緩存數據是否含有客戶端訪問的請求數據

新鮮度監測:若是緩存數據中含有客戶端訪問的數據,則檢查數據的有效性

建立響應報文:當肯定緩存命中的數據有效,則建立響應報文

發送響應報文:當響應報文構建完成以後,發送響應報文給客戶端

記錄日誌:發送響應報文的同時記錄日誌信息

新鮮度監測的方法:

一、過時日期或有效性:

HTTP/1.0:使用Expries定義緩存過時的絕對時間

例如:Expires:Sat, 18 Jul 2015 03:41:04 GMT

HTTP/1.1: 利用Cache-Control定義文檔的最大使用期限,是相對時長

例如:Cache-Control: max-age 1d: 緩存有效期爲1天

二、服務器再驗證:向服務器驗證數據是否發送改變

1)若是原始內容沒有改變,則服務器僅響應首部,不附帶body部分,響應碼爲304;

2)若是原始內容發生改變,則正常響應,響應碼爲200;

3)若果原始內容已不存在,則響應碼爲404,此時緩存也應該清除緩存項;

三、條件式請求首部:

If-Modified-Since: 從指定時間以後的時間內,原始內容是否發生啦的改變

If-None-Match: 每一個版本的文檔都有一個標籤ETag,當內容發生改變此ETag也會發送更改

控制緩存能力:

服務器端:Cache-Control

no-store: 不許緩存;

no-cache: 能夠緩存,但在提供給請求者以前必須作新鮮度監測;

must-revalidate:能夠緩存,但在提供給請求者以前必須作新鮮度監測;

max-age: 最大使用期限

Expires:過時的絕對時間

客戶端新鮮度限制:Cache-Control

max-stale: 最大失效時間

max-stale=<s>:指定最大失效時間

min-fresh=<s>:最短有效時間

max-age=<s>:最大有效時間

注意:含有private、authentication、cookie等信息最好不要緩存;

varnishi有兩類線程:

management:

1)讀入配置文件

2)調用合適類型的存儲(有malloc內存、tmp、persisten三種存儲類型)

3)建立/讀入相應大小的緩存文件

4)初始化管理結構體空間

5)fork並監控child進程

child/cache:

1)將打開的存儲文件映射進內存空間

2)建立並初始化空閒的結構體空間

varnish有九個狀態引擎,以下圖所示:

varnish九個狀態引擎

clipboard.png

varnish配置文件介紹:

1)後端節點定義:

backend name { } ;

代理緩存:子進程定義

sub+狀態引擎 { };

引擎之間都有相關性,前一個引擎經過return(x)定義退出狀態,進而決定繼續處理下一個引擎;

2)vcl:

vcl是基於「域」的簡單編程語言;支持算術運算和邏輯運算,支持正則表達式,支持使用set、unset自定義變量或取消變量,支持if條件判斷,有內置的函數和變量;

配置語法:

①註釋://單行註釋,/…../多行註釋

②sub $name 定義函數

③不支持循環

④支持終止語句return,沒有返回值

⑤域專用

⑥操做符:=(賦值)、==(比較)、~(正則)、!(取反)、&&(和)、||(或者)

3)vcl的內置函數

regsub(str,regexp,sub):以regexp爲模式匹配str,將匹配到的第一個替換爲sub

  regsuball(str,regexp,sub):以regexp爲模式匹配str,將全部匹配到的都替換爲sub

  hash_date(str):作hash計算

  purge:從緩存中挑出某對象並刪除

  return(x): 定義退出狀態
4)內置變量: 
![clipboard.png](/img/bVTJhn)
![clipboard.png](/img/bVTJhI)
# 配置文件:
·/etc/varnish/varnish.params—配置varnish服務進程的工做特性,例如監聽的地址和端口,緩存機制;
·/etc/varnish/default.vcl—配置各Child/Cache線程的緩存工做屬性;

配置函數

一、vcl_recv函數

用於接收和處理請求,當請求到達併成功接收後被調用,經過判斷請求的數據來決定如何處理請求。
此函數通常以以下幾個關鍵字結束:
pass:表示進入pass模式,把請求控制權交給vcl_pass函數。
pipe:表示進入pipe模式,把請求控制權交給vcl_pipe函數。

lookup: 表示進入hash,把請求控制權交給vcl_hash函數.
error code [reason]:表示返回「code」給客戶端,並放棄處理該請求,「code」是錯誤標識,例如200、405等,「reason」是錯誤提示信息。
二、vcl_pipe函數
此函數在進入pipe模式時被調用,用於將請求直接傳遞至後端主機,在請求和返回的內容沒有改變的狀況下,將不變的內容返回給客戶端,直到這個連接關閉
此函數通常以以下幾個關鍵字結束:
error code [reason]
pipe
三、vcl_pass函數
此函數在進入pass模式時被調用,用於將請求直接傳遞至後端主機,後端主機應答數據後送給客戶端,但不進行任何緩存,在當前鏈接下每次都返回最新的內容, 關鍵字結束:
error code [reason]
pass
四、lookup
表示在緩存裏查找被請求的對象,而且根據查找的結果把控制權交給函數vcl_hit或者函數vcl_miss
五、vcl_hit函數
在執行lookup指令後,若是在緩存中找到請求的內容,將自動調用該函數
此函數通常以以下幾個關鍵字結束:
deliver:表示將找到的內容發送給客戶端,並把控制權交給函數vcl_deliver
error code [reason]
pass
六、vcl_miss函數
在執行lookup指令後,若是沒有在緩存中找到請求的內容時自動調用該方法,此函數能夠用於判斷是否須要從後端服務器取內容
此函數通常以以下幾個關鍵字結束:
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:從緩存中清除該內容。

配置文件:

·/etc/varnish/varnish.params—配置varnish服務進程的工做特性,例如監聽的地址和端口,緩存機制;
·/etc/varnish/default.vcl—配置各Child/Cache線程的緩存工做屬性;

1)安裝

[root@varnish ~]# yum -y install varnish

2)配置varnish服務配置文件

[root@varnish ~]# vim /etc/sysconfig/varnish 
# Configuration file for varnish

NFILES=131072 \\定義能夠打開的最大文件數量

MEMLOCK=82000 \\定義log信息使用多大的內存空間,注意varnish log信息保存在內存中
 
NPROCS="unlimited"  \\ 每一個線程響應多少請求

# DAEMON_COREFILE_LIMIT="unlimited" \\ 保持默認便可

RELOAD_VCL=1 \\保持默認便可

# This file contains 4 alternatives, please use only one. \\有四種配置方法:

## Alternative 1, Minimal configuration, no VCL \\方法一
#
# Listen on port 6081, administration on localhost:6082, and forward to
# content server on localhost:8080.  Use a fixed-size cache file.
#
#DAEMON_OPTS="-a :6081 \
#             -T localhost:6082 \
#             -b localhost:8080 \
#             -u varnish -g varnish \
#             -s file,/var/lib/varnish/varnish_storage.bin,1G"


## Alternative 2, Configuration with VCL \\方法二
#
# Listen on port 6081, administration on localhost:6082, and forward to
# one content server selected by the vcl file, based on the request.  Use a
# fixed-size cache file.
#
#DAEMON_OPTS="-a :6081 \
#             -T localhost:6082 \
#             -f /etc/varnish/default.vcl \
#             -u varnish -g varnish \
#             -S /etc/varnish/secret \
#             -s file,/var/lib/varnish/varnish_storage.bin,1G"


## Alternative 3, Advanced configuration  \\方法三
#
# See varnishd(1) for more information.
#
# # Main configuration file. You probably want to change it ?
VARNISH_VCL_CONF=/etc/varnish/test.vcl  \\定義主配置文件
#
# # Default address and port to bind to
# # Blank address means all IPv4 and IPv6 interfaces, otherwise specify
# # a host name, an IPv4 dotted quad, or an IPv6 address in brackets.
# VARNISH_LISTEN_ADDRESS=
VARNISH_LISTEN_PORT=80  \\定義監聽端口,默認爲6081
#
# # Telnet admin interface listen address and port
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1    \\管理varnish監聽地址
VARNISH_ADMIN_LISTEN_PORT=6082   \\管理varnish的監聽端口
#
# # Shared secret file for admin interface
VARNISH_SECRET_FILE=/etc/varnish/secret \\varnish加密文件
#
# # The minimum number of worker threads to start
VARNISH_MIN_THREADS=50  \\varnish最小進程數
#
# # The Maximum number of worker threads to start
VARNISH_MAX_THREADS=1000 \\varnish最大進程數
#
# # Idle timeout for worker threads
VARNISH_THREAD_TIMEOUT=120 \\varnish工做進程超時時長
#
# # Cache file location
VARNISH_STORAGE_FILE=/var/lib/varnish/varnish_storage.bin \\緩存文件存儲類型,能夠定義使用內存存儲
#
# # Cache file size: in bytes, optionally using k / M / G / T suffix,
# # or in percentage of available disk space using the % suffix.
VARNISH_STORAGE_SIZE=1G  \\定義存儲空間大小
#
# # Backend storage specification
VARNISH_STORAGE="file,${VARNISH_STORAGE_FILE},${VARNISH_STORAGE_SIZE}" \\定義存儲屬性
#
# # Default TTL used when the backend does not specify one
VARNISH_TTL=120 \\緩存時長
#
# # DAEMON_OPTS is used by the init script.  If you add or remove options, make
# # sure you update this section, too.
DAEMON_OPTS="-a ${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \
             -f ${VARNISH_VCL_CONF} \
             -T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT} \
             -t ${VARNISH_TTL} \
             -w ${VARNISH_MIN_THREADS},${VARNISH_MAX_THREADS},${VARNISH_THREAD_TIMEOUT} \
             -u varnish -g varnish \
             -S ${VARNISH_SECRET_FILE} \
             -s ${VARNISH_STORAGE}"
#

## Alternative 4, Do It Yourself. See varnishd(1) for more information. \\方法四
#
# DAEMON_OPTS="

3)配置varnish主配置文件,添加響應報文首部

[root@varnish sysconfig]# cd /etc/varnish/
[root@varnish varnish]# cp default.vcl test.vcl
[root@varnish varnish]# vim test.vcl 
backend default {  \\定義後端主
  .host = "172.16.2.14";  \\後端主機地址
  .port = "80"; \\後端主機監聽端口
}
sub vcl_deliver {   \\在vcl_deliver狀態引擎中定義
     if (obj.hits > 0) {    \\若是緩存命中次數大於0
       set resp.http.X-Cache = "HIT";  \\添加響應首部X-Cache;設置值爲HIT;
     } else {
       set resp.http.X-Cache = "MISS"; \\ 添加響應首部X-Cache;設置值爲MISS;
     }
     return (deliver); \\定義返回狀態
}

應用此配置:

[root@varnish ~]# /etc/init.d/varnish start
root@varnish ~]# varnishadm -S /etc/varnish/secret  -T 127.0.0.1:6082 \\進入varnish管理界面
200        
-----------------------------
Varnish Cache CLI 1.0
-----------------------------
Linux,2.6.32-431.el6.x86_64,x86_64,-sfile,-smalloc,-hcritbit
varnish-3.0.7 revision f544cd8

Type 'help' for command list.
Type 'quit' to close CLI session.

varnish> vcl.load t1 /etc/varnish/test.vcl  \\載入配置文件
200        
VCL compiled.
varnish> vcl.use t1  \\使用配置文件
200

 VCL狀態引擎:

 內建變量:

·req.*:request,表示由客戶端發來的請求報文相關;
·bereq.*:由varnish發往BE主機的httpd請求相關;
·beresp.*:由BE主機響應給varnish的響應報文相關;
·resp.*:由varnish響應給client相關;
·obj.*:存儲在緩存空間中的緩存對象的屬性;只讀;

經常使用變量:

·bereq., req.

bereq.http.HEADERS
bereq.request:請求方法;
bereq.url:請求的url;
bereq.proto:請求的協議版本;
bereq.backend:指明要調用的後端主機;
req.http.Cookie:客戶端的請求報文中Cookie首部的值;
req.http.User-Agent ~ 「chrome」

·beresp., resp.

beresp.http.HEADERS
beresp.status:響應的狀態碼;
reresp.proto:協議版本;
beresp.backend.name:BE主機的主機名;
beresp.ttl:BE主機響應的內容的餘下的可緩存時長;

·obj.*

obj.hits:此對象從緩存中命中的次數;
obj.ttl:對象的ttl值

·server.*

server.ip
server.hostname

·client.*

交互式配置

varnishadm
登陸:

-S /etc/varnish/secret -T 127.0.0.1:80

配置文件相關:

vcl.list :狀態引擎列表;
vcl.load:裝載,加載並編譯;
vcl.use:激活;
vcl.discard:刪除;
vcl.show [-v] <configname>:查看指定的配置文件的詳細信息,可看默認配置;

運行時參數:

param.show -l:顯示列表;
param.show <PARAM>
param.set <PARAM> <VALUE>

緩存存儲:

storage.list

後端服務器:

backend.list

對某種請求不檢查緩存

示例:
vcl_recv {
    if (req.url ~ 「(?i)^/(login|admin)」) {
    return(pass);
}
}

拒絕某種請求訪問

示例:
vcl_recv {
    if (req.http.User-Agent ~ 「(?i)curl」) {
    return(synth(405));
}
}

對公開資源,取消私有標記,並設定緩存時長

示例:
if (beresp.http.cache-control !~ 「s-maxage」) {
if (bereq.url ~ 「(?i)\.(jpg|jpeg|png|gif|css|js)$」) {
    unset beresp.http.Set-Cookie;
    set beresp.ttl = 3600s;
}
}

顯示後端主機IP

示例:
if (req.restarts == 0) {
if (req.http.X-Fowarded-For) {
    set req.http.X-Forwarded-For = req.http.X-Forwarded-For + 「,」 + client.ip;
} else {
    set req.http.X-Forwarded-For = client.ip;
}
}

根據purge請求清除緩存

示例:
sub vcl_recv {
    if (req.method == 「PURGE」) {
    return(purge);
}
}

設置acl訪問控制

示例:
acl purgers {
「127.0.0.0」/8;
「10.1.0.0」/16;
}
sub vcl_recv {
    if (req.method == 「PURGE」) {
    if (!client.ip ~ purgers) {
    return(synth(405,」Purging not allowed for 」 + client.ip));
}
    return(purge);
}
}

用ban命令清除緩存

示例:
ban req.url ~ ^/javascripts
ban req.url ~ /js$

配置varnish後端多臺主機

示例:
import directors; # 導入模塊
backend server1 {
    .host = 「172.16.42.2」;
    .port = 「80」;
}
backend server2 {
    .host = 「172.16.42.3」;
    .port = 「80」;
}
sub vcl_init {
    new websrvs = directors.round_robin();
    websrvs.add_backend(server1);
    websrvs.add_backend(server2);
}
sub vcl_recv {
# 用哪一組server來請求
set req.backend_hint = websrvs.backend();
}

varnish動靜分離

示例:
backend default {
    .host = 「172.16.42.10」;
    .port = 「80」;
}
backend appsrv {
    .host = 「172.16.42.2」;
    .port = 「80」;
}
sub vcl_recv {
if (req.url ~ 「(?i)\.php$」) {
    set req.backend_hint = appsrv;
} else {
    set req.backend_hint = default;
}
}

對後端主機進行健康狀態檢測

.probe:定義健康狀態檢測方法;
.url:檢測時請求的URL,默認爲」/」;
.request:發出的具體請求;
.window:基於最近的多少次檢查來判斷其健康狀態;
.threshhold:最近.window中定義的這麼次檢查中至有.threshhold定義的次數是成功的;
.interval:檢測頻度;
.timeout:超時時長;
.expected_response:指望的響應碼,默認爲200;
示例:
backend server1 {
    .host = 「172.16.42.3」;
    .port = 「80」;
    .probe = {
    .url= 「/.healthcheck.html」 #得先建立這個測試頁面;
    .timeout= 1s;
    .interval= 2s;
    .window=5;
    .threshold=5;
    }
}

varnish的性能優化

·thread_pools: 最好小於或等於CPU核心數量;
·thread_pool_max:每線程池的最大線程數;
·thread_pool_min:額外意義爲「最大空閒線程數」;
·thread_pool_timeout:線程超時時間
·thread_pool_add_delay:新建立線程
·thread_pool_destroy_delay:殺死空閒線程延遲時間
設置方式:
/etc/varnish/varnish.params (永久有效)
param.set
示例:
DAEMON_OPTS=」-p thread_pools=6 -p thread_pool_min=5 -p thread_pool_max=500 -p thread_pool_timeout=300″

varnish日誌查看

一、varnishstat – Varnish Cache statistics

-1
-1 -f FILED_NAME
-l:可用於-f選項指定的字段名稱列表;
MAIN.cache_hit
MAIN.cache_miss
示例:
varnishstat -1 -f MAIN.cache_hit -f MAIN.cache_miss
varnishstat -l -f MAIN -f MEMPOOL

二、varnishtop – Varnish log entry ranking

-1 Instead of a continously updated display, print the statistics once and exit.
-i taglist,能夠同時使用多個-i選項,也能夠一個選項跟上多個標籤;
-I <[taglist:]regex>
-x taglist:排除列表
-X <[taglist:]regex>

三、varnishlog – Display Varnish logs四、varnishncsa – Display Varnish logs in Apache / NCSA combined log format

相關文章
相關標籤/搜索