1. 程式人生 > >Linux 緩存服務varnish

Linux 緩存服務varnish

linux varnish

Varnish是一款高性能的開源HTTP加速器,Squid服務也是,兩者的關系就像apache跟nginx,Varnish更年輕輕量,Squid更成熟穩重。
Varnish4.0工作工作流程如下圖
技術分享圖片
各個點說明
vcl_recv:接收請求
vcl_pass, 跳過緩存
vcl_hit, 緩存命中
vcl_miss, 緩存丟失
vcl_pipe, 非http
vcl_purge, 手動清楚緩存為過期
vcl_synth, 手動清楚緩存過期同步
vcl_deliver 發送給客戶端
每個節點上的變量作用域如下圖
技術分享圖片

內建變量:

1、req.*:request,表示由客戶端發來的請求報文相關;
req.http.User-Agent, req.http.Referer, ...

2、bereq.*:由varnish發往BE主機的httpd請求相關;
3、 beresp.*:由BE主機響應給varnish的響應報文相關;
4、 resp.*:由varnish響應給client相關;
5、obj.*:存儲在緩存空間中的緩存對象的屬性;只讀;

常用變量:

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

//-------------------------------------
beresp.http.HEADERS
beresp.status:響應的狀態碼;
reresp.proto:協議版本;
beresp.backend.name:BE主機的主機名;
beresp.ttl:BE主機響應的內容的余下的可緩存時長;
//-------------------------------------
obj.hits:此對象從緩存中命中的次數;
obj.ttl:對象的ttl值
//-------------------------------------
server.ip
server.hostname
//-------------------------------------
client.ip


Varnish的特長體現在緩存命中vcl_hit,以及緩存清理vcl_purge方便。

簡單使用說明

1、 安裝

[root@node1 ~]# yum install varnish

2、 查看

[root@node1 ~]# rpm -ql varnish
/etc/varnish   #配置文件目錄
/etc/varnish/default.vcl      #配置各Child/Cache線程的緩存策略;
/etc/varnish/varnish.params   # 配置varnish服務進程的工作特性,例如監聽的地址和端口,緩存機制;
/run/varnish.pid

/usr/bin/varnishadm  #客戶端腳本
/usr/bin/varnishtest  #測試工具程序:

#Shared Memory Log交互工具:
/usr/bin/varnishhist
/usr/bin/varnishlog
/usr/bin/varnishncsa
/usr/bin/varnishstat
/usr/bin/varnishtop

/usr/sbin/varnishd  #主程序
/usr/sbin/varnish_reload_vcl  #編譯配置文件

#啟動腳本
/usr/lib/systemd/system/varnish.service
/usr/lib/systemd/system/varnishlog.service     #持久化日誌  二選一
/usr/lib/systemd/system/varnishncsa.service    #持久化日誌  二選一

3、配置文件

[root@node1 varnish]# vim /etc/varnish/varnish.params
RELOAD_VCL=1   #啟動程序後能否reload配置文件
VARNISH_VCL_CONF=/etc/varnish/default.vcl   #
VARNISH_LISTEN_PORT=80 #默認6081 端口   如果直接當web服務器用改80

# Admin interface listen address and port  管理端口地址
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1
VARNISH_ADMIN_LISTEN_PORT=6082
VARNISH_SECRET_FILE=/etc/varnish/secret  #密鑰

#VARNISH_STORAGE="malloc,256M"  #緩存
VARNISH_STORAGE="file,/www/data/varnish,1g"

VARNISH_USER=varnish
VARNISH_GROUP=varnish
[root@node1 data]# mkdir varnish/cache
[root@node1 data]# chown -R varnish.varnish varnish

4、啟動

[root@node1 varnish]# systemctl start varnish
[root@node1 varnish]# ss -lntup|grep varnish
tcp    LISTEN     0      128       *:80                    *:*                   users:(("varnishd",pid=1765,fd=7))
tcp    LISTEN     0      10     127.0.0.1:6082                  *:*                   users:(("varnishd",pid=1764,fd=6))
tcp    LISTEN     0      128      :::80                   :::*                   users:(("varnishd",pid=1765,fd=8))

5、緩存策略後臺配置

[root@node1 varnish]# vim /etc/varnish/default.vcl
backend default {
    .host = "192.168.1.202";
    .port = "80";
}

6、重載

Loading vcl from /etc/varnish/default.vcl
Current running config name is
Using new config name reload_2018-06-06T09:17:17
VCL compiled.
VCL ‘reload_2018-06-06T09:17:17‘ now active
available       0 boot
active          0 reload_2018-06-06T09:17:17

Done

7、admin管理

[root@node1 varnish]# varnishadm -h
varnishadm: invalid option -- ‘h‘
usage: varnishadm [-n ident] [-t timeout] [-S secretfile] -T [address]:port command [...]
    -n is mutually exlusive with -S and -T

[root@node1 varnish]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
200
-----------------------------
Varnish Cache CLI 1.0
-----------------------------
Linux,3.10.0-693.el7.x86_64,x86_64,-sfile,-smalloc,-hcritbit
varnish-4.0.5 revision 07eff4c29

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

varnish> vcl.list  #配置文件版本
200
available       0 boot
active          0 reload_2018-06-06T09:17:17

#切換vcl配置  每次配置文件加載都會保存下來,在這裏可以切換
vcl.use boot
200
VCL ‘boot‘ now active
vcl.use reload_2018-06-06T09:17:17
200
VCL ‘reload_2018-06-06T09:17:17‘ now active

#查看默認配置選項
vcl.show -v reload_2018-06-06T09:17:17

#線程數量
param.show thread_pools
200
thread_pools
        Value is: 2 [pools] (default)
        Default is: 2
        Minimum is: 1

param.show thread_pool_max   #min
200
thread_pool_max
        Value is: 5000 [threads] (default)
        Default is: 5000
        Minimum is: 100

#設置參數
varnish> param.set thread_pools 4
200

#存儲查看
varnish> storage.list
200
Storage devices:
    storage.Transient = malloc
    storage.s0 = file

#後端查看
varnish> backend.list
200
Backend name                   Refs   Admin      Probe
default(127.0.0.1,,8080)       1      probe      Healthy (no probe)
default(192.168.1.202,,80)     1      probe      Healthy (no probe)

#--------------------------------------------------------------------------
#非交互式
[root@node1 varnish]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 status
Child in state running

規則編寫

默認規則查看,很重要,因為varnish先讀取客戶端配置,在讀取默認規則

[root@node1 varnish]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 vcl.list
available       0 boot
available       0 reload_2018-06-06T09:17:17
available       0 reload_2018-06-06T10:43:58
available       0 reload_2018-06-06T11:08:20
available       0 reload_2018-06-06T12:52:47
available       0 reload_2018-06-06T13:04:19
active          0 reload_2018-06-06T13:06:08

[root@node1 varnish]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 vcl.show -v reload_2018-06-06T13:06:08

1、不檢查緩存

sub vcl_recv {
        if (req.url ~ "(?i)^/(login|admin)") {
                return(pass);
        }
}

技術分享圖片

2、合成錯誤碼

sub vcl_recv {
    if (req.http.User-Agent ~ "(?i)curl"){
        return(synth(403));
    }

}

marvindeMacBook-Pro:~ marvin$ curl http://192.168.1.200/admin.php
<!DOCTYPE html>
<html>
  <head>
    <title>403 Forbidden</title>
  </head>
  <body>
    <h1>Error 403 Forbidden</h1>
    <p>Forbidden</p>
    <h3>Guru Meditation:</h3>
    <p>XID: 196684</p>
    <hr>
    <p>Varnish cache server</p>
  </body>
</html>

3、默認vcl_recv策略

sub vcl_recv {

       if (req.method != "GET" &&
       req.method != "HEAD" &&
       req.method != "PUT" &&
       req.method != "POST" &&
       req.method != "TRACE" &&
       req.method != "OPTIONS" &&
       req.method != "DELETE") {
                        /* Non-RFC2616 or CONNECT which is weird. */
                        return (pipe);
       }

        if (req.method != "GET" && req.method != "HEAD") {
            /* We only deal with GET and HEAD by default */
            return (pass);
        }
        if (req.http.Authorization || req.http.Cookie) {
            /* Not cacheable by default */
            return (pass);
        }
            return (hash);

}

4、指定資源去除cookie做緩存

sub vcl_recv {
    if (req.url ~ "(?i)\.(jpg|jpge)$" ){
                unset req.http.Cookie;
                return(hash);
    }
}
sub vcl_backend_response {
    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;
        }
    }
}  

技術分享圖片

5、客戶端ip

 vcl_recv: 如果多級代理需要加 ,默認是有X-Forwarded-For
 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;
        }

技術分享圖片

6、緩存修剪(實用)

#白名單設置  掩碼寫在外面
acl purgers{
#       "192.168.1.104";
        "127.0.0.1"/8;
}
sub vcl_recv {
    if(req.method == "PURGE"){
        if (!client.ip ~ purgers){
                return(synth(403));
        }
        return(purge);
    }
}

#默認規則裏面的行為    
sub vcl_purge {
    return (synth(200, "Purged"));
}    

技術分享圖片
技術分享圖片
技術分享圖片
以上三次請求,第一次刪除緩存,第二次沒有命中(添加緩存),第三次命中緩存

在交互模式下(用於臨時清理)   這種方式很有用
ban req.url ~ ^/javascript   #清空所有/javascript 開頭的
ban req.url ~ ^/            #清空所有

#配置文件清空
if (req.method == "BAN") {
    ban("req.http.host == " + req.http.host + " && req.url == " + req.url);
    # Throw a synthetic page so the request won‘t go to the backend.
    return(synth(200, "Ban added"));
}

7、綁定多個後臺

import directors;
#默認是backend default
backend websrv1 {
    .host = "192.168.1.201";
    .port = "80";
}

backend websrv2 {
    .host = "192.168.1.202";
    .port = "80";
}
sub vcl_init {
    #輪詢
    new websrvs = directors.round_robin();
    websrvs.add_backend(websrv1);
    websrvs.add_backend(websrv2);

    #權重
    new websrvs3 = directors.random();
    websrvs3.add_backend(websrv1,1);
    websrvs3.add_backend(websrv2,2);

}

#可以區分出來 動態頁面跟靜態頁面
sub vcl_recv {
       if (req.url ~ "(?i)\.php$") {
                set req.backend_hint = websrv1;
        } else {
                set req.backend_hint = websrvs.backend();
        }
}    

#---------------------------------------------------------
#會話綁定
sub vcl_init {
    new h = directors.hash();
    h.add_backend(one, 1);   // backend ‘one‘ with weight ‘1‘
    h.add_backend(two, 1);   // backend ‘two‘ with weight ‘1‘
}

sub vcl_recv {
    // pick a backend based on the cookie header of the client
    set req.backend_hint = h.backend(req.http.cookie);
}

8、健康狀態監測

probe www_probe {
    .url = "/index.html";
    .timeout = 1s;
    .interval = 4s;
    .window = 5;   #探測5次 成功3次算在線
    .threshold = 3;
    .expected_response:期望的響應碼,默認為200;
}

backend websrv1 {
    .host = "192.168.1.201";
    .port = "80";
    .probe = www_probe;
}

backend websrv2 {
    .host = "192.168.1.202";
    .port = "80";
    .probe = www_probe;
}

[root@node1 varnish]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 backend.list
Backend name                   Refs   Admin      Probe
default(192.168.1.201,,80)     9      probe      Healthy (no probe)
websrv1(192.168.1.201,,80)     5      probe      Healthy 5/5
websrv2(192.168.1.202,,80)     5      probe      Healthy 5/5

在交互模式下手動設置下線
backend.set_health websrv Sick
backend.set_health websrv Healthy

服務進程配置

DAEMON_OPTS="-p thread_pool=3  thread_pool_min=5 -p thread_pool_max=500 -p thread_pool_timeout=300"

thread_pool 2 線程池 小於等於cpu
thread_pool_min 100 每個線程池最小幾個線程 默認100
thread_pool_max 5000 最大幾個線程  默認5000
thread_pool_timeout 300.000 空閑線程的最長時常  超過thread_pool_min個數後 空閑的超過這個時間就會被殺死
thread_queue_limit 20  線程池隊列長度默認20  可以增加
thread_pool_add_delay 0.000 [seconds]  增加不延遲
thread_pool_destroy_delay  1 second 殺死延遲一秒
thread_pool_fail_delay 0.200 [seconds] 創建失敗時候,間隔多少時間在重新創建

client:
send_timeout 600.000   發送響應包給客戶端
timeout_idle 5     保持連接超時空閑時常  可調增加
timeout_req  2      接收客戶端請求報文首部  超過2秒放棄
cli_timeout    admin 管理工具請求超時時常  
backend BE_NAME {
    ...
    .connect_timeout = 3.5s;
    .first_byte_timeout = 60s;
    .between_bytes_timeout = 60s;
}

log

1、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

[root@node1 varnish]# varnishstat -1 #一次顯示所有

[root@node1 varnish]# varnishstat -1 -f MAIN.cache_hit -f MAIN.cache_miss
MAIN.cache_hit              63         0.00 Cache hits
MAIN.cache_miss             18         0.00 Cache misses

2、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>

[root@node1 varnish]# varnishtop -i RespStatus  #壓測 狀態碼

3、日誌文件,一般不開啟,一級代理采用

[root@node1 varnish]# systemctl start varnishncsa
[root@node1 varnish]# tail /var/log/varnish/varnishncsa.log
192.168.1.104 - - [06/Jun/2018:20:54:42 +0800] "GET http://192.168.1.200/robots.txt HTTP/1.1" 404 571 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36"

Linux 緩存服務varnish