一.Varnish概述

1.Varnish 簡介

Varnish是一款高性能且開源的反向代理服務器和HTTP加速器,其採用全新的軟件體系機構,和現在的硬件體係緊密配合。與傳統的squid相比,Varnish具有高性能、速度快、管理更加方便等優點,目前很多大型的網站都開始嘗試使用Varnish來代替squid,這便是Varnish迅速發展的最根本的原因。

Varnish的主要特徵:

(1)緩存代理位置:可以使用內存也可以使用磁盤;
(2)日誌存儲:日誌存儲在內存中;
(3)支持虛擬內存的使用;
(4)有精確的時間管理機制,即緩存的時間屬性控制;
(5)狀態引擎架構:在不同的引擎上完成對不同的緩存和代理數據進行處理;
(6)緩存管理:以二叉堆管理緩存數據,做到數據的及時清理;

2.Varnish 與Squid 的對比相同點

  • 都是開源軟件;
  • 都是一個反向代理服務器;

Varnish 的優勢

(1)穩定性:Varnish和Squid在完成相同負載的工作時,Squid服務器發生故障的機率要高於Varnish,因為使用Squid需要經常重啟;
(2)訪問速度更快:Varnish所有緩存的數據都是直接從內存中讀取,而Squid是從硬盤中讀取;
(3)支持更多的並發連接:因為Varnish的TCP連接和釋放的速度比Squid快很多

Varnish 的劣勢

(1)Varnish進程一旦重啟,緩存數據都會從內存中完全釋放,此時所有請求都會發送到後端服務器,在高並發情況下,會給後端服務器造成很大壓力;
(2)在Varnish使用中如果使用單個URL的請求通過負載均衡時,則每次請求都會落在不同的Varnish服務器中,造成請求都會到後端服務器;而且同樣的秦桂在多台服務器上緩存,也會造成Varnish的緩存資源的浪費,造成性能下降;

Varnish 劣勢的解決方案

針對劣勢一:在訪問量很大的情況下推薦使用varnish的內存緩存方式啟動,而且後面需要跟多台squid/nginx服務器。主要為了防止前面的varnish服務、服務器被重啟的情況下,大量請求穿透varnish,這樣squid/nginx可以就擔當第二層CACHE,而且也彌補了varnish緩存在內存中重啟都會釋放的問題;
針對劣勢二:可以在負載均衡上做url哈希,讓單個url請求固定請求到一台varnish服務器上;

3.Varnish的工作原理

當Varnish服務器收到客戶端的請求時,首選檢查緩存中是否有數據,如果有,則直接響應客戶端;如果沒有則向後端服務器請求相應的資源,緩存到Varnish服務器本地,再響應客戶端;

根據規則和請求頁面的類型選擇數據是否需要進行緩存,可以根據請求頭中Cache-Contorl判斷是否緩存,以及cookis是否有標記,這些功能都可以通過編寫配置文件的方式來實現。

4.Varnish簡單架構

Varnish分為management進程和child進程

  • management進程:對child進程進行管理,同事對VCL配置進行編譯,並應用到不同的狀態引擎中;
  • child進程:生成線程池,負責對用戶請求進行處理,並通過hash查找返回用戶結果;

child進程生成的常見線程有

  • accept線程:接收新的連接請求並響應;
  • worker線程:會話,處理請求資源;
  • expiry線程:清除緩存中過期的內容;

5.varnish 主要配置部分

  • 後端配置:給Varnish添加反向代理服務器節點,最少配置一個;
  • ACL配置:給Varnish添加訪問控制列表,可以指定這些列表訪問或禁止訪問;
  • probes配置:給Varnish添加探測後端服務器是否正常的規則,方便切換或禁止對應後端服務器;
  • directors配置:給Varnish添加負載均衡模式管理多個後端服務器;
  • 核心子程序配置:給Varnish添加後端服務器切換,請求緩存、訪問控制、錯誤處理等規則;

6.VCL 中內置預設變量:變量(也叫object):

如圖

(1)req:客戶端請求Varnish服務器時可用的變量;
(2)bereq:Varnish服務器請求後端服務器可用的變量;
(3)beresp:後端服務器響應Varnish服務器請求,並返回結果時,使用的變量;
(4)resp:Varnish服務器響應客戶端請求是使用的變量;
(5)obj:高速緩存對象,緩存後端響應請求內容;
(6)now:作用就是返回當前的時間戳;

客戶端

Clienet.ip:返回客戶端的IP地址
Client.port:獲取客戶端請求的端口號(在vatnish4.0以後需要調取std模塊才能使用)語法為import std; std.port(client.ip)
Client.identiy獲取客戶端標識碼,軟件在安裝過程中會生成一個序列號,用來標識身份

服務器

Server.hostname:服務器主機名
Server.identiy:獲取服務器標識碼
Server.ip:獲取服務器IP地址
Server.prot:獲取服務器IP端口號,需要調用std模塊

客戶端請求req (客戶端請求發送的對象)

  • Req:整個請求的數據結構
  • req.bachend_hint:指定請求後端節點如gif 給圖片服務器
  • Req.can_gzip:客戶端是否接受gzip傳輸編碼(通常瀏覽器支持所有壓縮格式)
  • req.hash_always_miss:是否從緩存中讀取數據
  • req.hash_ignore_busy: 忽略緩存中忙碌的數據死鎖(如兩台varnish服務器在處理過程中共同爭搶一個資源造成堵塞,如果不手動停止則會僵持支持僵持下去)
  • req.http:對應請求http的header
  • req.method :請求類型或者請求的方式(如gt,post)
  • req.proto:客戶端請求使用的http協議的版本
  • req.restarts:重新啟動次數,默認最大值是4(通常用於判斷是否訪問過服務器)
  • req.url:請求的url
  • req.xid:唯一id,varnish服務器訪問時在頭部增加了X-varnish,後面的數字是varnish的id,第一個數據是請求的標識id,第二個數據是緩存的標識id

varnish請求後端服務器(bereq)

  • bereq:整個後端請求的數據結構
  • bereq.backend:所請求後端節點的配置
  • bereq.between_bytes_timeout:從後端每接收一個字節之間的等待時間或者超時時間
  • bereq.http:對應發送到後端的http的頭部信息
  • bereq.method: 發送到後端的請求類型或者請求方式
  • bereq.proto:發送到後端的請求的http協議版本
  • bereq.retires:相同請求重試計數
  • bereq.uncacheable:請求數據沒有被緩存,或者請求不緩存
  • bereq.url:發送到後端請求的url
  • bereq.xid:請求唯一id

後端服務器向varnish返回數據beresq

  • Beresp:後端服務器響應數據
  • Beresp.backend.ip:後端響應(處理請求數據)服務器的IP地址
  • Beresp.backend.name:後端響應服務器的節點名
  • Beresp.do_gunzip:默認為false,緩存前解壓改對象
  • Beresp.grace:設置緩存過期的額外寬限時間
  • Beresp.http:響應時http的頭部
  • Beresp.keep:對象緩存後帶保持時間
  • Beresp.proto:響應的http版本
  • Beresp.reason :後端服務器返回的http狀態信息
  • Beresp.status:後端服務器返回的在狀態碼
  • Beresp.storage_hint:指定保存的的特定存儲器(內存)
  • Beresp.ttl:改對象緩存的剩餘時間,指定統一緩存剩餘時間
  • Beresp,uncacheable:對數據不進行緩存

存儲

  • Storage.<name>.free_space:存儲可用空間(字節數)
  • Storage.<name>.used_space:存儲剩餘時間(字節數)
  • Storage.<name>.happy:存儲節點狀態
  • deliver將數據發送給客戶端,返回的數據
  • fetch從後端獲取數據,並將數據緩存到本地

7.特定功能語句

  • Ban(expression):清除指定對象緩存;
  • Call(subroutine):調用子程序;
  • Hash_data(input):根據input的子程序的值生成hash鍵;
  • New():創建新的vcl對象,只能在vcl_init 子進程中;
  • Return():結束當前子程序,並指定繼續下一步動作;
  • Rollback():恢復HTTP 頭到原來狀態,已經棄用,使用std.rollback() 代替;
  • Synthetic (STRING):合成器,定義返回給客戶端頁面和狀態碼;
  • Regsub(str,regex,sub)使用正則表達式替換第一次出現的字符串;
  • Regsuball(str,regex,sub)替換所有出現的字符串;

8.varnish請求處理的步驟

如圖

varnish請求處理的步驟

Receive狀態(vcl_recv)。也就是請求處理的入口狀態,根據VCL規則判斷該請求應該pass(vcl_pass)或是pipe(vcl_pipe),還是進入lookup(本地查詢)。
Lookup狀態。進入該狀態後,會在hash表中查找數據,若找到,則進入hit(vcl_hit)狀態,否則進入miss(vcl_miss)狀態。
Pass(vcl_pass)狀態。在此狀態下,會直接進入後端請求,即進入fetch(vcl_fetch)狀態
Fetch(vcl_fetch)狀態。在fetch狀態下,對請求進行後端獲取,發送請求,獲得數據,並根據設置進行本地存儲。
Deliver(vcl_deliver)狀態。將獲取到的數據發給客戶端,然後完成本次請求。
Pipe狀態。建立客戶端和服務器之間的直接連接,從後端服務器調取數據

vcl_recv子程序:開始處理請求,通過return (動作);
vcl_pipe子程序: pipe模式處理,該模式主要用於直接取後端響應內容返回客戶端,可定義響應內容返回客戶端。
vcl_pass子程序: pass模式處理,該模式類似hash緩存模式,僅不做緩存處理.
vcl_hit子程序: hash緩存模式時,存在hash緩存時調用,用於緩存處理,可放棄或修改緩存.
vcl_miss子程序: hash緩存模式時,不存在hash緩存時調用,用於判斷性的選擇進入後端取響應內容,可以修改為pass模式。
vcl_hash子程序: hash緩存模式,生成hash值作為緩存查找鍵名提取緩存內容,主要用於緩存hash鍵值處理,可使用hash_data(string)指定鍵值組成結構,可在同一個頁面通過IP或cookie生成不同的緩存鍵值。
vcl_purge子程序:清理模式,當查找到對應的緩存時清除並調用,用於請求方法清除緩存,並報告
vcl_deliver子程序:客戶端交付子程序,在vcl_backend_response子程序後調用(非pipe模式),或vcl_hit子程序後調用,可用於追加響應頭信息,cookie等內容。
vcl_backend_fetch子程序:發送後端請求之前調用,可用於改變請求地址或其它信息,或放棄請求。
vcl_backend_response子程序:後端響應後調用,可用於修改緩存時間及緩存相關信息。
vcl_backend_error子程序:後端處理失敗調用,異常頁面展示效果處理,可自定義錯誤響應內容,或修改beresp.status與beresp.http.Location重定向等。
vcl_synth子程序:自定義響應內容。可以通過synthetic()和返回值synth調用,這裡可以自定義異常顯示內容,也可以修改resp.status與resp.http.Location重定向。
vcl_init子程序:加載vcl時最先調用,用於初始化VMODs,該子程序不參與請求處理,僅在vcl加載時調用一次。
vcl_fini子程序:卸載當前vcl配置時調用,用於清理VMODs,該子程序不參與請求處理,僅在vcl正常丟棄後調用。

 二.安裝Varnish

下載varnish軟件包鏈接: https://pan.baidu.com/s/1OfnyR-5xFuxMUYJTnhQesA提取碼: m9q4

除了一台varnish服務器,可以再開倆台web服務器,提供web頁面就可以。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
[root@localhost ~]# yum -y install autoconf automake libedit-devel libtool ncurses-devel pcre-devel pkgconfig python-docutils python-sphinx
[root@localhost ~]# tar zxf varnish-4.0.3.tar.gz
[root@localhost ~]# cd varnish-4.0.3/
[root@localhost varnish-4.0.3]# ./configure && make && make install
[root@localhost varnish-4.0.3]# cp etc/example.vcl /usr/local/var/varnish/
//复制Varnish主配置文件
[root@localhost /]# vim /usr/local/var/varnish/example.vcl
//编辑Varnish主配 看原来的修改
vcl 4.0;
import directors;
import std;
backend default {
  .host = "127.0.0.1";
  .port = "80";
}
probe backend_healthcheck {
    .url="/";
    .interval = 5s;
    .timeout = 1s;
    .window = 5;
    .threshold = 3;
}
backend web1 {
    .host = "192.168.148.132";
    .port = "80";
    .probe = backend_healthcheck;
}
backend web2 {
    .host = "192.168.148.133";
    .port = "80";
    .probe = backend_healthcheck;
}
acl purgers {
    "127.0.0.1";
    "localhost";
    "192.168.148.0/24";
    !"192.168.148.133";
}
sub vcl_init {
    new web_cluster=directors.round_robin();
    web_cluster.add_backend(web1);
    web_cluster.add_backend(web2);
}
//把原来的全部删除添加如下
sub vcl_recv {
    set req.backend_hint = web_cluster.backend();
    if (req.method == "PURGE") {
        if (!client.ip ~ purgers) {
            return (synth(405, "Not Allowed."));
    }
    return (purge);
}
if (req.method != "GET" &&
    req.method != "HEAD" &&
    req.method != "PUT" &&
    req.method != "POST" &&
    req.method != "TRACE" &&
    req.method != "OPTIONS" &&
    req.method != "PATCH" &&
    req.method != "DELETE") {
        return (pipe);
    }
if (req.method != "GET" && req.method != "HEAD") {
    return (pass);
}
if (req.url ~ "\.(php|asp|aspx|jsp|do|ashx|shtml)($|\?)") {
    return (pass);
}
if (req.http.Accept-Encoding) {
    if (req.url ~ "\.(bmp|png|gif|jpg|jpeg|ico|gz|tgz|bz2|tbz|zip|rar|mp3|mp4|ogg|swf|flv)$") {
    unset req.http.Accept-Encoding;
} elseif (req.http.Accept-Encoding ~ "gzip") {
        set req.http.Accept-Encoding = "gzip";
    } elseif (req.http.Accept-Encoding ~ "deflate") {
        set req.http.Accept-Encoding = "deflate";
    } else {
    unset req.http.Accept-Encoding;
    }
   }
if (req.url ~ "\.(css|js|html|htm|bmp|png|gif|jpg|jpeg|ico|gz|tgz|bz2|tbz|zip|rar|mp3|mp4|ogg|swf|flv)($|\?)") {
    unset req.http.cookie;
    return (hash);
}
if (req.restarts == 0) {
    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;
    }
}
return (hash);
}
sub vcl_hash {
    hash_data(req.url);
    if (req.http.host) {
    hash_data(req.http.host);
    } else {
        hash_data(server.ip);
    }
    return (lookup);
}
sub vcl_hit {
    if (req.method == "PURGE") {
        return (synth(200, "Purged."));
    }
    return (deliver);
}
sub vcl_miss {
  if (req.method == "PURGE") {
        return (synth(404, "Purged."));
    }
    return (fetch);
}
sub vcl_deliver {
    if (obj.hits > 0) {
        set resp.http.CXK = "HIT-from-varnish";
        set resp.http.X-Cache-Hits = obj.hits;
    } else {
    set resp.http.X-Cache = "MISS";
    }
    unset resp.http.X-Powered-By;
    unset resp.http.Server;
    unset resp.http.X-Drupal-Cache;
    unset resp.http.Via;
    unset resp.http.Link;
    unset resp.http.X-Varnish;
    set resp.http.xx_restarts_count = req.restarts;
    set resp.http.xx_Age = resp.http.Age;
    set resp.http.hit_count = obj.hits;
        unset resp.http.Age;
            return (deliver);
            }
 
sub vcl_purge {
    return (synth(200,"success"));
}
sub vcl_backend_error {
    if (beresp.status == 500 ||
        beresp.status == 501 ||
        beresp.status == 502 ||
        beresp.status == 503 ||
        beresp.status == 504) {
        return (retry);
    }
}
sub vcl_fini {
    return (ok);
}
[root@localhost /]# varnishd -f /usr/local/var/varnish/example.vcl -s malloc,200M -a 0.0.0.0:80
//启动服务

第一台web提供頁面

1
2
3
4
[root@localhost ~]# yum -y install httpd
[root@localhost ~]# echo aaa > /var/www/html/index.html
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# systemctl start httpd

第二台

1
2
3
4
[root@localhost ~]# yum -y install httpd
[root@localhost ~]# echo bbb > /var/www/html/index.html
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# systemctl start httpd

如果重啟Varnishd如下:

1
2
3
[root@localhost /]# netstat -anpt | grep 80
[root@localhost /]# killall -9 varnishd
[root@localhost /]# varnishd -f /usr/local/var/varnish/example.vcl -s malloc,200M -a 0.0.0.0:80

客戶端訪問如下:

刷新一下

1
2
[root@localhost /]# curl -X "PURGE" 192.168.148.130
//清除缓存

Varnish配置文件解釋

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
vcl 4.0;
import directors;
import std;
# Default backend definition. Set this to point to your content server.
probe backend_healthcheck {
    .url="/"; #访问后端服务器根路径
    .interval = 5s;  #请求时间间隔
    .timeout = 1s;  #请求超时时间
    .window = 5;  #指定轮询次数5次
    .threshold = 3;  #如果出现3次失败则表示后端服务器异常
}
backend web1 {  #定义后端服务器
    .host = "192.168.1.7"; #要转向主机(即后端主机)的 IP 或域名
    .port = "80"; #指定后端服务器的端口号
    .probe = backend_healthcheck; #健康检查调用backend_healthcheck定义的内容
}
backend web2 {
    .host = "192.168.1.8";
    .port = "80";
    .probe = backend_healthcheck;
}
acl purgers { #定义访问控制列表
    "127.0.0.1";
    "localhost";
    "192.168.1.0/24";
    !"192.168.1.8";
}
sub vcl_init {   #调用 vcl_init 初始化子程序创建后端主机组,即 directors
    new web_cluster=directors.round_robin(); #使用 new 关键字创建 drector 对象,使用 round_robin(轮询) 算法
    web_cluster.add_backend(web1);  #添加后端服务器节点
    web_cluster.add_backend(web2);
}
sub vcl_recv {
    set req.backend_hint = web_cluster.backend(); #指定请求的后端节点web_cluster定义的后端节点
    if (req.method == "PURGE") {  #判断客户端的请求头部是否是PURGE
        if (!client.ip ~ purgers) {  #如果是,再判断客户端的IP地址是不是在ACL访问控制列表中.
            return (synth(405, "Not Allowed.")); #如果不是,返回给客户端405状态码并且返回定义的页面.
    }
    return (purge);  #如果是ACL定义的,则交给purge处理.
}
if (req.method != "GET" &&
    req.method != "HEAD" &&
    req.method != "PUT" &&
    req.method != "POST" &&
    req.method != "TRACE" &&
    req.method != "OPTIONS" &&
    req.method != "PATCH" &&
    req.method != "DELETE") {   #判断客户端的请求类型
        return (pipe);
    }
if (req.method != "GET" && req.method != "HEAD") {
    return (pass);   #如果不是GET及HEAD则交给pass.
}
if (req.url ~ "\.(php|asp|aspx|jsp|do|ashx|shtml)($|\?)") {
    return (pass);  #当客户端访问的是.php等结尾的交给pass处理.
}
if (req.http.Accept-Encoding) {
    if (req.url ~ "\.(bmp|png|gif|jpg|jpeg|ico|gz|tgz|bz2|tbz|zip|rar|mp3|mp4|ogg|swf|flv)$") {
    unset req.http.Accept-Encoding;  #取消客户端接收的压缩类型
    } elseif (req.http.Accept-Encoding ~ "gzip") {
        set req.http.Accept-Encoding = "gzip"; #如果有gzip类型,标记gzip类型.
    } elseif (req.http.Accept-Encoding ~ "deflate") {
        set req.http.Accept-Encoding = "deflate";
    } else {
    unset req.http.Accept-Encoding; #其他未定义的页面也取消客户但接收的压缩类型.
    }
   }
if (req.url ~ "\.(css|js|html|htm|bmp|png|gif|jpg|jpeg|ico|gz|tgz|bz2|tbz|zip|rar|mp3|mp4|ogg|swf|flv)($|\?)") {
    unset req.http.cookie; #取消客户端的cookie值.
    return (hash);  #将请求转发给hash子程序,也就是查看本地缓存.
}
if (req.restarts == 0) { #判断客户端是不是第一次请求
    if (req.http.X-Forwarded-For) {   #如果是第一次请求,设置获取客户端的IP地址.
        set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
    } else {
    set req.http.X-Forwarded-For = client.ip;
    }
}
return (hash);
}
sub vcl_hash {
    hash_data(req.url);  #查看客户端请求的页面,并且进行hash
    if (req.http.host) {
        hash_data(req.http.host); #设置客户端的主机
    } else {
        hash_data(server.ip);  #设置服务器的IP
    }
    return (lookup);
}
sub vcl_hit {
    if (req.method == "PURGE") {  #如果是HIT并且当客户端请求的类型是PURGE返回的200的状态码,并返回相应页面.
        return (synth(200, "Purged."));
    }
    return (deliver);
}
sub vcl_miss {
  if (req.method == "PURGE") {
        return (synth(404, "Purged."));  #如果是miss返回404
    }
    return (fetch);
}
sub vcl_deliver {
    if (obj.hits > 0) {
        set resp.http.CXK = "HIT-from-varnish"; #设置http头部X-Cache =hit
        set resp.http.X-Cache-Hits = obj.hits; #返回命令的次数
    } else {
    set resp.http.X-Cache = "MISS";
    }
    unset resp.http.X-Powered-By; #取消显示web版本
    unset resp.http.Server;  #取消显示varnish服务
    unset resp.http.X-Drupal-Cache;  #取消显示缓存的框架
    unset resp.http.Via;  #取消显示文件内容来源
    unset resp.http.Link; #取消显示HTML的超链接地址
    unset resp.http.X-Varnish; #取消显示varnish的id
    set resp.http.xx_restarts_count = req.restarts;  #设置客户端请求的次数
    set resp.http.xx_Age = resp.http.Age;  #显示缓存文件的时长
    #set resp.http.hit_count = obj.hits;  #显示缓存命中的次数
    #unset resp.http.Age;
    return (deliver);
}
sub vcl_pass {
    return (fetch);  #将后端服务器返回的数据缓存到本地
}
sub vcl_backend_response {
    set beresp.grace = 5m;  #缓存额外宽限时间
    if (beresp.status == 499 || beresp.status == 404 || beresp.status == 502) {
        set beresp.uncacheable = true;  #当后端服务器相应状态码是449等,不缓存
    }
    if (bereq.url ~ "\.(php|jsp)(\?|$)") {
        set beresp.uncacheable = true; #当是PHP的页面不缓存
    } else {
        if (bereq.url ~ "\.(css|js|html|htm|bmp|png|gif|jpg|jpeg|ico)($|\?)") {
        set beresp.ttl = 15m; #当是上面结尾的,缓存15分钟
        unset beresp.http.Set-Cookie;
        } elseif (bereq.url ~ "\.(gz|tgz|bz2|tbz|zip|rar|mp3|mp4|ogg|swf|flv)($|\?)") {
            set beresp.ttl = 30m; #缓存30分钟
            unset beresp.http.Set-Cookie;
        } else {
            set beresp.ttl = 10m; #生存时间10分钟
            unset beresp.http.Set-Cookie;
        }
    }
    return (deliver);
}
sub vcl_purge {
    return (synth(200,"success"));
}
sub vcl_backend_error {
    if (beresp.status == 500 ||
        beresp.status == 501 ||
        beresp.status == 502 ||
        beresp.status == 503 ||
        beresp.status == 504) {
        return (retry); #如果状态码是上述其中之一,则重新请求
    }
}
sub vcl_fini {
    return (ok);
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

arrow
arrow
    全站熱搜

    科技幫 發表在 痞客邦 留言(0) 人氣()