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

相关文章

QT Creator配置Kit的实现示例

《QTCreator配置Kit的实现示例》本文主要介绍了使用Qt5.12.12与VS2022时,因MSVC编译器版本不匹配及WindowsSDK缺失导致配置错误的问题解决,感兴趣的可以了解一下... 目录0、背景:qt5.12.12+vs2022一、症状:二、原因:(可以跳过,直奔后面的解决方法)三、解决方

SpringBoot路径映射配置的实现步骤

《SpringBoot路径映射配置的实现步骤》本文介绍了如何在SpringBoot项目中配置路径映射,使得除static目录外的资源可被访问,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一... 目录SpringBoot路径映射补:springboot 配置虚拟路径映射 @RequestMapp

Python与MySQL实现数据库实时同步的详细步骤

《Python与MySQL实现数据库实时同步的详细步骤》在日常开发中,数据同步是一项常见的需求,本篇文章将使用Python和MySQL来实现数据库实时同步,我们将围绕数据变更捕获、数据处理和数据写入这... 目录前言摘要概述:数据同步方案1. 基本思路2. mysql Binlog 简介实现步骤与代码示例1

基于C#实现PDF转图片的详细教程

《基于C#实现PDF转图片的详细教程》在数字化办公场景中,PDF文件的可视化处理需求日益增长,本文将围绕Spire.PDFfor.NET这一工具,详解如何通过C#将PDF转换为JPG、PNG等主流图片... 目录引言一、组件部署二、快速入门:PDF 转图片的核心 C# 代码三、分辨率设置 - 清晰度的决定因

Java中HashMap的用法详细介绍

《Java中HashMap的用法详细介绍》JavaHashMap是一种高效的数据结构,用于存储键值对,它是基于哈希表实现的,提供快速的插入、删除和查找操作,:本文主要介绍Java中HashMap... 目录一.HashMap1.基本概念2.底层数据结构:3.HashCode和equals方法为什么重写Has

Nginx中配置使用非默认80端口进行服务的完整指南

《Nginx中配置使用非默认80端口进行服务的完整指南》在实际生产环境中,我们经常需要将Nginx配置在其他端口上运行,本文将详细介绍如何在Nginx中配置使用非默认端口进行服务,希望对大家有所帮助... 目录一、为什么需要使用非默认端口二、配置Nginx使用非默认端口的基本方法2.1 修改listen指令

Java使用正则提取字符串中的内容的详细步骤

《Java使用正则提取字符串中的内容的详细步骤》:本文主要介绍Java中使用正则表达式提取字符串内容的方法,通过Pattern和Matcher类实现,涵盖编译正则、查找匹配、分组捕获、数字与邮箱提... 目录1. 基础流程2. 关键方法说明3. 常见场景示例场景1:提取所有数字场景2:提取邮箱地址4. 高级

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程

Springboot项目构建时各种依赖详细介绍与依赖关系说明详解

《Springboot项目构建时各种依赖详细介绍与依赖关系说明详解》SpringBoot通过spring-boot-dependencies统一依赖版本管理,spring-boot-starter-w... 目录一、spring-boot-dependencies1.简介2. 内容概览3.核心内容结构4.

mysql5.7.15winx64配置全过程

《mysql5.7.15winx64配置全过程》文章详细介绍了MySQL5.7.15免安装版的配置步骤,包括解压安装包、设置环境变量、修改配置文件、初始化数据目录、安装服务、启动数据库、登录及密码修改... 目录前言一、首先下载安装包二、安android装步骤1.第一步解压文件2.配置环境变量3.复制my-