Varnish 4.0.3详细配置

2023-12-13 09:38
文章标签 配置 详细 4.0 varnish

本文主要是介绍Varnish 4.0.3详细配置,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最近在折腾varnish 4.0,话说从3.0到4.0变化挺大的,许多配置做了调整

对比Varnish 3.x的主要改进点
(1)、完全支持流对象;
(2)、可后台获取失效的对象,即Client/backend分离;
(3)、新的vanishlog查询语言,允许对请求进行自动分组;
(4)、复杂的请求时间戳和字节计数;
(5)、安全方面的提升;


涉及VCL语法的改变点
(1)、vcl配置文件需明确指定版本:即在vcl文件的第一行写上 vcl 4.0;
(2)、vcl_fetch函数被vcl_backend_response代替,且req.*不再适用vcl_backend_response;
(3)、后端源服务器组director成为varnish模块,需import directors后再在vcl_init子例程中定义;
(4)、自定义的子例程(即一个sub)不能以vcl_开头,调用使用call sub_name;
(5)、error()函数被synth()替代;
(6)、return(lookup)被return(hash)替代;
(7)、使用beresp.uncacheable创建hit_for_pss对象;
(8)、变量req.backend.healty被std.healthy(req.backend)替代;
(9)、变量req.backend被req.backend_hint替代;
(10)、关键字remove被unset替代;

详细可以参考:

https://www.varnish-cache.org/docs/4.0/whats-new/upgrading.html


工作流程

wKioL1VeCY-DPKO0AAJMe9Ky6sI343.jpg

Varnish 分为 master 进程和 child 进程:
Master 进程读入存储配置文件,调用合适的存储类型,然后创建 / 读入相应大小的缓存文件,接着 master 初始化管理该存储空间的结构体,然后 fork 并监控 child 进程;

Child 进程在主线程的初始化的过程中,将前面打开的存储文件整个 mmap 到内存中,此时创建并初始化空闲结构体,挂到存储管理结构体,以待分配;

对外管理接口分为3种,分别是命令行接口、Telnet接口和Web接口;

同时在运行过程中修改的配置,可以由VCL编译器编译成C语言,并组织成共享对象(Shared Object)交由Child进程加载使用;

wKioL1VeCjXQzfqpAAGwhfW_hms381.jpg

Child 进程分配若干线程进行工作,主要包括一些管理线程和很多 worker 线程,可分为:
Accept线程:接受请求,将请求挂在overflow队列上;
Work线程:有多个,负责从overflow队列上摘除请求,对请求进行处理,直到完成,然后处理下一个请求;
Epoll线程:一个请求处理称为一个session,在session周期内,处理完请求后,会交给Epoll处理,监听是否还有事件发生;
Expire线程:对于缓存的object,根据过期时间,组织成二叉堆,该线程周期检查该堆的根,处理过期的文件,对过期的数据进行删除或重取操作;


请求处理流程

wKioL1VeC6nTO12hAALZCRVU5rE198.jpg

 

Varnish 处理 HTTP 请求的过程如下
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)状态:将获取到的数据发给客户端,然后完成本次请求;

注:Varnish4中在vcl_fetch部分略有出入,已独立为vcl_backend_fetch和vcl_backend_response 2个函数;

内置函数(也叫子例程)
vcl_recv:用于接收和处理请求;当请求到达并成功接收后被调用,通过判断请求的数据来决定如何处理请求;
vcl_pipe:此函数在进入pipe模式时被调用,用于将请求直接传递至后端主机,并将后端响应原样返回客户端;
vcl_pass:此函数在进入pass模式时被调用,用于将请求直接传递至后端主机,但后端主机的响应并不缓存直接返回客户端;
vcl_hit:在执行 lookup 指令后,在缓存中找到请求的内容后将自动调用该函数;
vcl_miss:在执行 lookup 指令后,在缓存中没有找到请求的内容时自动调用该方法,此函数可用于判断是否需要从后端服务器获取内容;
vcl_hash:在vcl_recv调用后为请求创建一个hash值时,调用此函数;此hash值将作为varnish中搜索缓存对象的key;
vcl_purge:pruge操作执行后调用此函数,可用于构建一个响应;
vcl_deliver:将在缓存中找到请求的内容发送给客户端前调用此方法;
vcl_backend_fetch:向后端主机发送请求前,调用此函数,可修改发往后端的请求;
vcl_backend_response:获得后端主机的响应后,可调用此函数;
vcl_backend_error:当从后端主机获取源文件失败时,调用此函数;
vcl_init:VCL加载时调用此函数,经常用于初始化varnish模块(VMODs)
vcl_fini:当所有请求都离开当前VCL,且当前VCL被弃用时,调用此函数,经常用于清理varnish模块;


以上内容为在他人基础上学习总结而来,并非全部原创,望多多指教

废话就不多说了,以下是我目前整理出来的配置,有些参数还需要进一优化调整:

1、后端服务器健康检查

# vim /etc/varnish/health_check.vcl

1
2
3
4
5
6
7
8
9
10
11
12
probe backend_healthcheck {
     .interval = 5s;
     .timeout = 3s;
     .window = 10;
     .threshold = 8;
     
     .request =
     "GET /favicon.ico HTTP/1.1"
     "Host: www.xxx.com"
     "Connection: close"
     "Accept-Encoding: foo/bar";
}

2、后端服务器地址池配置

# vim /etc/varnish/backends.vcl

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
import directors;
include "health_check.vcl";
backend d102_app_07 {
     .host = "10.0.11.145";
     .port = "80";
     
     .first_byte_timeout = 9s;
     .connect_timeout = 3s;
     .between_bytes_timeout = 1s;
     
     .probe = backend_healthcheck;
}
backend d102_app_08 {
     .host = "10.0.11.146";
     .port = "80";
     
     .first_byte_timeout = 9s;
     .connect_timeout = 3s;
     .between_bytes_timeout = 1s;
     
     .probe = backend_healthcheck;
}
sub vcl_init {
     new web = directors.random();
     
     web.add_backend(d102_app_07, 1);
     web.add_backend(d102_app_08, 1);
}

3、缓存规则主配置

# vim /etc/varnish/default.vcl

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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
vcl 4.0;
import std;
include "backends.vcl";
acl allow_purge_cache {
     "127.0.0.1";
     "10.0.0.0"/8;
     "172.0.0.0"/8;
}
sub vcl_recv {
     if (req.method == "PURGE") {
         if (!client.ip ~ allow_purge_cache) {
             return (synth(405, "Not Allowed."));
         }
         
         return (purge);
     }
     
     set req.backend_hint = web.backend();
     
     if (req.url ~ "\.(php|asp|aspx|jsp|do|ashx|shtml)($|\?)") {
         return (pass);
     }
     
     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;
         }
     }
     
     if (req.http.Cache-Control ~ "(?i)no-cache") {
         if (!(req.http.Via || req.http.User-Agent ~ "(?i)bot" || req.http.X-Purge)) {
             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.http.Authorization) {
         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.http.Upgrade ~ "(?i)websocket") {
         return (pipe);
     }
     
     if (!std.healthy(req.backend_hint)) {
         unset req.http.Cookie;
     }
     
     if (req.http.x-pipe && req.restarts > 0) {
         unset req.http.x-pipe;
         return (pipe);
     }
     
     return (hash);
}
sub vcl_pipe {
     if (req.http.upgrade) {
         set bereq.http.upgrade = req.http.upgrade;
     }
     
     return (pipe);
}
sub vcl_pass {
     if (req.method == "PURGE") {
         return (synth(502, "PURGE on a passed object."));
     }
}
sub vcl_hash {
     hash_data(req.url);
     
     if (req.http.host) {
         hash_data(req.http.host);
     } else {
         hash_data(server.ip);
     }
     
     if (req.http.Cookie) {
         hash_data(req.http.Cookie);
     }
     
     if (req.http.Accept-Encoding ~ "gzip") {
         hash_data("gzip");
     } elseif (req.http.Accept-Encoding ~ "deflate") {
         hash_data("deflate");
     }
}
sub vcl_hit {
     if (req.method == "PURGE") {
         return (synth(200, "Purged."));
     }
     
     if (obj.ttl >= 0s) {
         return (deliver);
     }
     
     if (std.healthy(req.backend_hint)) {
         if (obj.ttl + 10s > 0s) {
             return (deliver);
         } else {
             return(fetch);
         }
     } else {
         if (obj.ttl + obj.grace > 0s) {
             return (deliver);
         } else {
             return (fetch);
         }
     }
     
     return (deliver);
}
sub vcl_miss {
     if (req.method == "PURGE") {
         return (synth(404, "Purged."));
     }
     
     return (fetch);
}
sub vcl_backend_response {
     set beresp.grace = 5m;
     
     set beresp.ttl = std.duration(regsub(beresp.http.Cache-Control, ".*s-maxage=([0-9]+).*", "\1") + "s", 0s);
     if (beresp.ttl > 0s) {
         unset beresp.http.Set-Cookie;
     }
     
     if (beresp.http.Set-Cookie) {
         set beresp.uncacheable = true;
         return (deliver);
     }
     
     if (beresp.http.Cache-Control && beresp.ttl > 0s) {
         set beresp.grace = 1m;
         unset beresp.http.Set-Cookie;
     }
     
     if (beresp.http.Content-Length ~ "[0-9]{8,}") {
         set bereq.http.x-pipe = "1";
         return (retry);
     }
     
     if (bereq.url ~ "\.(php|asp|aspx|jsp|do|ashx|shtml)($|\?)") {
         set beresp.uncacheable = true;
         return (deliver);
     }
     
     if (bereq.url ~ "\.(css|js|html|htm|bmp|png|gif|jpg|jpeg|ico|gz|tgz|bz2|tbz|zip|rar|mp3|mp4|ogg|swf|flv)($|\?)") {
         unset beresp.http.set-cookie;
     }
     
     if (bereq.url ~ "^[^?]*\.(mp[34]|rar|tar|tgz|gz|wav|zip|bz2|xz|7z|avi|mov|ogm|mpe?g|mk[av])(\?.*)?$") {
         unset beresp.http.set-cookie;
         set beresp.do_stream = true;
         set beresp.do_gzip = false;
     }
     
     if ((!beresp.http.Cache-Control && !beresp.http.Expires) || 
          beresp.http.Pragma ~ "no-cache" || 
          beresp.http.Cache-Control ~ "(no-cache|no-store|private)") {
         set beresp.ttl = 120s;
         set beresp.uncacheable = true;
         return (deliver);
     }
     
     if (beresp.ttl <= 0s || beresp.http.Set-Cookie || beresp.http.Vary == "*") {
         set beresp.ttl = 120s;
         set beresp.uncacheable = true;
         return (deliver);
     }
     
     if (bereq.url ~ "\.(css|js|html|htm|bmp|png|gif|jpg|jpeg|ico)($|\?)") {
         set beresp.ttl = 15m;
     } elseif (bereq.url ~ "\.(gz|tgz|bz2|tbz|zip|rar|mp3|mp4|ogg|swf|flv)($|\?)") {
         set beresp.ttl = 30m;
     } else {
         set beresp.ttl = 10m;
     }
     
     return (deliver);
}
sub vcl_purge {
     if (req.method != "PURGE") {
         set req.http.X-Purge = "Yes";
         return (restart);
     }
}
sub vcl_deliver {
     if (obj.hits > 0) {
         set resp.http.X-Cache = "HIT from " + req.http.host;
         set resp.http.X-Cache-Hits = obj.hits;
     } else {
         set resp.http.X-Cache = "MISS from " + req.http.host;
     }
     
     unset resp.http.X-Powered-By;
     unset resp.http.Server;
     
     unset resp.http.Via;
     unset resp.http.X-Varnish;
     
     unset resp.http.Age;
}
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);
}

4、启动参数配置

# vim /etc/sysconfig/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
NFILES=131072
MEMLOCK=25165824
NPROCS="unlimited"
RELOAD_VCL=1
VARNISH_VCL_CONF=/etc/varnish/default.vcl
VARNISH_LISTEN_ADDRESS=0.0.0.0
VARNISH_LISTEN_PORT=6081
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1
VARNISH_ADMIN_LISTEN_PORT=6082
VARNISH_SECRET_FILE=/etc/varnish/secret
VARNISH_MIN_THREADS=240
VARNISH_MAX_THREADS=4800
VARNISH_THREAD_TIMEOUT=120
VARNISH_STORAGE_SIZE=24G
VARNISH_STORAGE="malloc,${VARNISH_STORAGE_SIZE}"
VARNISH_TTL=120
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} \
         -p thread_pools=24 \
         -p thread_pool_min=${VARNISH_MIN_THREADS} \
         -p thread_pool_max=${VARNISH_MAX_THREADS} \
         -p thread_pool_timeout=${VARNISH_THREAD_TIMEOUT} \
         -u varnish -g varnish \
         -S ${VARNISH_SECRET_FILE} \
         -s ${VARNISH_STORAGE} \
         -p timeout_idle=60 \
         -p timeout_linger=1 \
         -p http_resp_hdr_len=16k \
         -p http_max_hdr=256 \
         -p http_req_hdr_len=16k \
         -p lru_interval=120 \
         -p listen_depth=8192"

5、启动脚本调整

# vim /etc/init.d/varnish


exec="/usr/sbin/varnishd"
修改为
exec="/usr/bin/numactl --interleave all /usr/sbin/varnishd"

这篇关于Varnish 4.0.3详细配置的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/487976

相关文章

MySQL 中的服务器配置和状态详解(MySQL Server Configuration and Status)

《MySQL中的服务器配置和状态详解(MySQLServerConfigurationandStatus)》MySQL服务器配置和状态设置包括服务器选项、系统变量和状态变量三个方面,可以通过... 目录mysql 之服务器配置和状态1 MySQL 架构和性能优化1.1 服务器配置和状态1.1.1 服务器选项

SpringBoot整合easy-es的详细过程

《SpringBoot整合easy-es的详细过程》本文介绍了EasyES,一个基于Elasticsearch的ORM框架,旨在简化开发流程并提高效率,EasyES支持SpringBoot框架,并提供... 目录一、easy-es简介二、实现基于Spring Boot框架的应用程序代码1.添加相关依赖2.添

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Spring AI集成DeepSeek的详细步骤

《SpringAI集成DeepSeek的详细步骤》DeepSeek作为一款卓越的国产AI模型,越来越多的公司考虑在自己的应用中集成,对于Java应用来说,我们可以借助SpringAI集成DeepSe... 目录DeepSeek 介绍Spring AI 是什么?1、环境准备2、构建项目2.1、pom依赖2.2

Goland debug失效详细解决步骤(合集)

《Golanddebug失效详细解决步骤(合集)》今天用Goland开发时,打断点,以debug方式运行,发现程序并没有断住,程序跳过了断点,直接运行结束,网上搜寻了大量文章,最后得以解决,特此在这... 目录Bug:Goland debug失效详细解决步骤【合集】情况一:Go或Goland架构不对情况二:

Python itertools中accumulate函数用法及使用运用详细讲解

《Pythonitertools中accumulate函数用法及使用运用详细讲解》:本文主要介绍Python的itertools库中的accumulate函数,该函数可以计算累积和或通过指定函数... 目录1.1前言:1.2定义:1.3衍生用法:1.3Leetcode的实际运用:总结 1.1前言:本文将详

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll

SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤

《SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤》本文主要介绍了SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤,文中通过示例代码介绍的非常详... 目录 目标 步骤 1:确保 ProxySQL 和 mysql 主从同步已正确配置ProxySQL 的

Spring Boot整合log4j2日志配置的详细教程

《SpringBoot整合log4j2日志配置的详细教程》:本文主要介绍SpringBoot项目中整合Log4j2日志框架的步骤和配置,包括常用日志框架的比较、配置参数介绍、Log4j2配置详解... 目录前言一、常用日志框架二、配置参数介绍1. 日志级别2. 输出形式3. 日志格式3.1 PatternL

Springboot 中使用Sentinel的详细步骤

《Springboot中使用Sentinel的详细步骤》文章介绍了如何在SpringBoot中使用Sentinel进行限流和熔断降级,首先添加依赖,配置Sentinel控制台地址,定义受保护的资源,... 目录步骤 1: 添加 Sentinel 依赖步骤 2: 配置 Sentinel步骤 3: 定义受保护的