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

相关文章

windos server2022的配置故障转移服务的图文教程

《windosserver2022的配置故障转移服务的图文教程》本文主要介绍了windosserver2022的配置故障转移服务的图文教程,以确保服务和应用程序的连续性和可用性,文中通过图文介绍的非... 目录准备环境:步骤故障转移群集是 Windows Server 2022 中提供的一种功能,用于在多个

windos server2022里的DFS配置的实现

《windosserver2022里的DFS配置的实现》DFS是WindowsServer操作系统提供的一种功能,用于在多台服务器上集中管理共享文件夹和文件的分布式存储解决方案,本文就来介绍一下wi... 目录什么是DFS?优势:应用场景:DFS配置步骤什么是DFS?DFS指的是分布式文件系统(Distr

关于Maven中pom.xml文件配置详解

《关于Maven中pom.xml文件配置详解》pom.xml是Maven项目的核心配置文件,它描述了项目的结构、依赖关系、构建配置等信息,通过合理配置pom.xml,可以提高项目的可维护性和构建效率... 目录1. POM文件的基本结构1.1 项目基本信息2. 项目属性2.1 引用属性3. 项目依赖4. 构

龙蜥操作系统Anolis OS-23.x安装配置图解教程(保姆级)

《龙蜥操作系统AnolisOS-23.x安装配置图解教程(保姆级)》:本文主要介绍了安装和配置AnolisOS23.2系统,包括分区、软件选择、设置root密码、网络配置、主机名设置和禁用SELinux的步骤,详细内容请阅读本文,希望能对你有所帮助... ‌AnolisOS‌是由阿里云推出的开源操作系统,旨

Java操作PDF文件实现签订电子合同详细教程

《Java操作PDF文件实现签订电子合同详细教程》:本文主要介绍如何在PDF中加入电子签章与电子签名的过程,包括编写Word文件、生成PDF、为PDF格式做表单、为表单赋值、生成文档以及上传到OB... 目录前言:先看效果:1.编写word文件1.2然后生成PDF格式进行保存1.3我这里是将文件保存到本地后

windows系统下shutdown重启关机命令超详细教程

《windows系统下shutdown重启关机命令超详细教程》shutdown命令是一个强大的工具,允许你通过命令行快速完成关机、重启或注销操作,本文将为你详细解析shutdown命令的使用方法,并提... 目录一、shutdown 命令简介二、shutdown 命令的基本用法三、远程关机与重启四、实际应用

mysql-8.0.30压缩包版安装和配置MySQL环境过程

《mysql-8.0.30压缩包版安装和配置MySQL环境过程》该文章介绍了如何在Windows系统中下载、安装和配置MySQL数据库,包括下载地址、解压文件、创建和配置my.ini文件、设置环境变量... 目录压缩包安装配置下载配置环境变量下载和初始化总结压缩包安装配置下载下载地址:https://d

使用SpringBoot创建一个RESTful API的详细步骤

《使用SpringBoot创建一个RESTfulAPI的详细步骤》使用Java的SpringBoot创建RESTfulAPI可以满足多种开发场景,它提供了快速开发、易于配置、可扩展、可维护的优点,尤... 目录一、创建 Spring Boot 项目二、创建控制器类(Controller Class)三、运行

springboot整合gateway的详细过程

《springboot整合gateway的详细过程》本文介绍了如何配置和使用SpringCloudGateway构建一个API网关,通过实例代码介绍了springboot整合gateway的过程,需要... 目录1. 添加依赖2. 配置网关路由3. 启用Eureka客户端(可选)4. 创建主应用类5. 自定

gradle安装和环境配置全过程

《gradle安装和环境配置全过程》本文介绍了如何安装和配置Gradle环境,包括下载Gradle、配置环境变量、测试Gradle以及在IntelliJIDEA中配置Gradle... 目录gradle安装和环境配置1 下载GRADLE2 环境变量配置3 测试gradle4 设置gradle初始化文件5 i