varnish 简介
varnish是一款强大的http加速器,其设计初衷因为计算机越来越复杂,不像那个只有内存与硬盘的存储媒介的年代,如今的计算机系统除了内存外还有cpu的L1、L2、L3快取,因此当初的Squid cache自行处理物件替换的架构不可能得知这些情况而做到最佳,但操作系统可以得知该情况,此PoulHenning Kamp设计了varinish的架构
varnish术语解析
缓存的衡量参数:命中率 # 1 文档命中率 # 2 字节命中率 缓存类型: # 私有缓存 (比如客户端的浏览器上的缓存) # 公共缓存 (比如一个组织机构建立的缓存服务器) 缓存的层次结构 #客户端 <---...-->2级代理<--------->1级代理 <----------->原始服务器
内容路由 #ICP : Internet Cache Protocol 互联网缓存协议 #CARP: Cache Array Routing Protocol 缓存阵列路由协议---用的比较多
缓存处理客户端请求的具体步骤 #接受请求 #解析请求 (代理的功能) #查询缓存 (检查本地缓存中是否存在对方请求的内容的副本) #副本的新鲜度检测 (检查本地缓存的副本是否为最新版本) #构建响应 (代理的功能---作为某个应用程序的代理服务器) #发送 #日志
保证副本的新鲜度?
# 文档过期机制:-----------响应首部
HTTP/1.0 : Expires (过期时间)
绝对时间 -----比如2014年5月5日过期
HTTP/1.1 :Cache-Control (max-age=)
相对时长 ------比如还有100小时可用
# 条件式请求: --------------请求首部
1 mtime: If-Modified-Since
基于时间的条件式请求
2 ETag :If-None-Match
基于拓展标签条件式请求原始服务器、缓存服务器、客户端 如何实现对缓存的控制
(1) 原始服务器或缓存服务器控制缓存的能力
# 由原始服务器定义:
Cache-Control
Cacmax-age =(属于私有缓存中)
s-maxage =(属于公共缓存中)
no-store :不能缓存
no-cache :能缓存下来,但不能直接使用此缓存对象; 缓存对象在使用之间必须做 新鲜度验证
must-revalidate:必须进行新鲜度验证
private : 客户端的私有数据,不缓存
public : 公共数据,缓存
#原始服务器不添加任何控制机制,而由缓存服务器自己决定缓存时长
(2)客户端对缓存使用情况的控制
# 客户端控制是否使用缓存:
Cache-Control:
max-stale:告知缓存机制可以使用过期的文件
no-cache :告知缓存机制必须进行验证,否则不会接受任何缓存文档;
no-store :告知缓存机制必须尽快删除缓存中的文档Varnish 基本架构
如上图所示: (1) varnish主要运行两个进程: Management进程和Child进程(也叫Cache进程)。 # Management进程主要实现应用新的配置、编译VCL、监控varnish、初始化varnish以及提供一个命令行接口等。Management进程会每隔几秒钟探测一下Child进程以判断其是否正常运行,如果在指定的时长内未得到Child进程的回应,Management将会重启此Child进程。 # Child进程包含多种类型的线程 # Accept线程:接收新的连接请求并响应; # Worker线程:child进程会为每个会话启动一个worker线程,因此,在高并发的场景中可能会出现数百个worker线程甚至更多; # Expiry线程:从缓存中清理过期内容;
(2)varnish日志 #为了与系统的其它部分进行交互,Child进程使用了可以通过文件系统接口进行访问的共享内存日志(shared memory log) #共享内存日志大小一般为80M,其分为两部分,前一部分为计数器,后半部分为客户端请求的数据。varnish提供了多个不同的工具如varnishlog、varnishncsa或varnishstat等来分析共享内存日志中的信息并能够以指定的方式进行显示。
(3)VCL # Varnish Configuration Language (VCL)是varnish配置缓存策略的工具 # 使用VCL编写的缓存策略通常保存至.vcl文件中,其需要编译成二进制的格式后才能由varnish调用 # 整个缓存策略就是由几个特定的子例程如vcl_recv、vcl_fetch等组成 VCL语法 # (1)//、#或/* comment */用于注释 # (2)sub $name 定义函数 ---即定义子例程 # (3)不支持循环,有内置变量 # (4)使用终止语句,没有返回值 # (5)域专用 # (6)操作符:=(赋值)、==(等值比较)、~(模式匹配)、!(取反)、&&(逻辑与)、||(逻辑或)
(4)varnish后端存储 # 1)file:使用特定的文件存储全部的缓存数据; # 2)malloc:使用malloc()库调用在varnish启动时向操作系统申请指定大小的内存空间以存储缓存对象; # 3)persistent(experimental):与file的功能相同,但可以持久存储数据(即重启varnish数据时不会被清除);仍处于测试期;
状态引擎(子例程)
VCL中由多个子例程组成,各个子例程之间有必然的关系,如下图所示
如上图 pipe 、lookup、pass 为vcl_recv 子例程的返回状态。依据此状态来判断下一步的去向
VCL中的变量
Varnish的安装配置
环境搭建
如上图 varnish服务器 172.16.13.2 外网网卡 192.168.20.11 内网网卡 后端服务器两个 192.168.20.12 服务器一内网地址 192.168.20.13 服务器二内网地址
准备工作
1 配置以上三台服务器的ip地址,此处不做详解
2 server1服务器 编辑web页面
#vim /var/www/html/index.html
<h1>node12.linux.com</h1>
#service httpd start
3 server2服务器 编辑web页面
#vim /var/www/html/index.html
<h1>node13.linux.com</h1>
#service httpd start安装varnish并配置
1)下载3.0版本的varnish
varnish-3.0.4-1.el6.x86_64.rpm
varnish-libs-3.0.4-1.el6.x86_64.rpm
varnish-docs-3.0.4-1.el6.x86_64.rpm
2)安装
# rpm -ivh varnish*.rpm 安装以上三个包
# rpm -ql varnish
3)编辑varnish配置文件,定义varnish启动时的特性
#vim /etc/sysconfig/varnish
NFILES=131072 打开的最大文件数
MEMLOCK=82000 默认分配给日志log的内存数82M
NPROCS="unlimited" 最大线程数 ,无限制
RELOAD_VCL=1 重新启动服务时候,是否重新编译vcl 重新使用vcl
VARNISH_VCL_CONF=/etc/varnish/default.vcl vcl配置缓存策略的配置文件
VARNISH_LISTEN_PORT=80 varnish侦听的默认端口为6081,接受用户请求 ----------一般更改为80端口
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1 varnish管理侦听的地址
VARNISH_ADMIN_LISTEN_PORT=6082 varnish管理接口,
VARNISH_SECRET_FILE=/etc/varnish/secret 进入varnish管理接口的密钥文件
VARNISH_MIN_THREADS=50 最小线程数
VARNISH_MAX_THREADS=1000 最大线程数---------varnish超过5000个线程后会不稳定
VARNISH_THREAD_TIMEOUT=120 空闲线程转向工作线程的延迟时间
VARNISH_STORAGE_FILE=/var/lib/varnish/varnish_storage.bin 基于文件存储时的文件路径
VARNISH_STORAGE_SIZE=1G 后端存储的的大小
VARNISH_STORAGE="malloc,100M" 自定义内存大小
VARNISH_TTL=120 请求后端服务器的超时时间
4)启动服务
# service varnish start
# ss -ntlp | grep 805 ) 进入varnish管理界面 #varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 varnish> help --------查看一下所有的命令参数 200 help [command] ping [timestamp] auth response quit banner status start stop vcl.load <configname> <filename> 加载编译某个vcl,加载的时候并指定一个配置名称(该名称随意指定) vcl.inline <configname> <quoted_VCLstring> vcl.use <configname> vcl.discard <configname> vcl.list 列出所有的vcl vcl.show <configname> 查看已经列出的vcl param.show [-l] [<param>] param.set <param> <value> panic.show panic.clear storage.list
6 )
创建vcl文件
#vim /etc/varnish/test.vcl 内容如下
backend websrv1 {
.host = "192.168.20.12";
.port = "80";
}
进入管理界面编译使用
#varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
varnish> vcl.load test2 test.vcl ------------------加载编译test.vcl
200
VCL compiled.
varnish> vcl.use test2 -----------------使用已经编译好 test.vcl 200
varnish> vcl.show test2 ------------------查看test.vcl 的内容
200
backend websrv1 {
.host = "192.168.20.12";
.port = "80";
}7)客户端测试
接下来进行vcl的功能拓展
一、 判断上边的配置是否命中缓存
(1)编辑test.vcl
#vim /etc/varnish/test.vcl
backend websrv1 {
.host = "192.168.20.12";
.port = "80";
}
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
}
(2)管理界面中重新编译 并使用
# varnish > vcl.load test3 test.vcl
# varnish > vcl.use test3
(3)在varnish服务器测试
# curl -I http://172.16.13.2命中
二、判断从哪个服务器命中缓存 ---使用变量server.ip
编辑test.vcl
#vim /etc/varnish/test.vcl
backend websrv1 {
.host = "192.168.20.12";
.port = "80";
}
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT" + server.ip;
} else {
set resp.http.X-Cache = "MISS";
}
}
管理界面 重新编译并使用
# varnish > vcl.load test4 test.vcl
# varnish > vcl.use test4
服务器测试
# curl -I http://172.16.13.2三、 拒绝使用缓存 ---使用变量req.url
server2服务器再创建一个测试页面
#vim /var/www/html/test.html
<h1>test!!!</h1>
编辑vcl配置文件增加vcl_recv子例程
#vim /etc/varnish/test.vcl
sub vcl_recv {
if (req.url ~ "test.html") {
return(pass);
}
return(lookup);
}
varnish服务器测试
# curl -I http://172.16.13.2/test.html全部miss,未命中
四、定义缓存时长
如果客户端请求的为图片文件,就缓存7200s,
如果客户端请求的为静态网页,就缓存1200s
编辑test.vcl 增加子例程vcl_fetch
#vim /etc/varnish/test.vcl
sub vcl_fetch {
if (req.url ~ "\.(jpg|jpeg|gif|png)$") {
set beresp.ttl = 7200s;
}
if (req.url ~ "\.(html|css|js)$") {
set beresp.ttl = 1200;
}
}
#serivice varnish reload
管理界面重新编辑 并使用
#varnish > vcl.load test6 test.vcl
#varnish > vcl.use test6五 使用PURGE修剪缓存
修剪缓存非常危险,所以我们必须要做好准备
在具体执行某清理工作时,需要事先确定如下问题:
#(1)仅需要检验一个特定的缓存对象,还是多个?
#(2)目的是释放内存空间,还是仅替换缓存的内容?
#(3)是不是需要很长时间才能完成内容替换?
#(4)这类操作是个日常工作,还是仅此一次的特殊需求?
移除单个缓存的实现
#vim /etc/varnish/test.vcl 增加内容如下
acl purgers {
"127.0.0.1";
"172.16.0.0"/16;
}
sub vcl_recv {
if (req.request == "PURGE") {
if (!client.ip ~ purgers) {
error 405 "Method not allowed";
}
}
if (req.url ~ "test.html") {
return(pass);
}
return(lookup);
}
sub vcl_hit {
if (req.request == "PURGE") {
purge;
error 200 "PURGE OK";
}
}
sub vcl_miss {
if (req.request == "PURGE") {
purge;
error 404 "Not in cache";
}
}
sub vcl_pass {
if (req.request == "PURGE") {
error 502 "Purged on a passed object";
}
}
管理界面重新编译vcl并使用
#varnish > vcl.load test8 vcl.test
#varnish > vcl.use test8
测试
客户端在发起HTTP请求时,只需要为所请求的URL使用PURGE方法即可
使用 curl -I -X PURGE http://varniship/path/to/someurl六、定义varnish服务器检测后端服务器健康状态
后端服务器为 192.168.12.12和 192.168.12.13
#vim /etc/varnish/test.vcl
backend web1 {
.host = "192.168.20.12";
.port = "80";
.probe = {
.url = "/index.html";
.interval = 1s;
.window = 5;
.threshold = 2;
}
}
backend web2 {
.host = "192.168.20.13";
.port = "80";
.probe = {
.url = "/index.html";
.interval = 1s;
.window = 5;
} .threshold = 2;
}
director webs random {
{
.backend = web1;
.weight = 2;
}
{
.backend = web2;
.weight = 1;
}
}
同时在子例程 vcl_recv 中添加调用req.backend
set req.backend = webs;
管理接口重新编译vcl 并好似用
# varnish > vcl.load test9 vcl.test
# varnish > vcl.use test9
客户端测试
首先关闭192.168.20.12 服务器的httpd服务
启动192.168.20.12 httpd服务
七 将请求的静态网页发送至web1服务器
将请求的图片发送至web2服务器
编辑test.vcl
# vim /etc/varnish/test.vcl 添加如下内容
sub vcl_recv {
if (req.url ~ "\.(html|css|js)$") {
set req.backend = web1;
} else {
set req.backend = web2;
}
#同时注释掉director所有内容八 如何防盗链
搜的例子:
if (req.http.referer ~ "http://.*") {
if ( !(req.http.referer ~ "http://.*ixdba\.net"
|| req.http.referer ~ "http://.*google\.com"
|| req.http.referer ~ "http://.*yahoo\.cn"et
|| req.http.referer ~ "http://.*google\.cn"
)) {
set req.http.host = "www.ixdba.net";
set req.url = "/templets/default/images/logo.gif";
}
return (lookup);
}
varnish常用的工具
1 varnishstat 查看状态的命令工具
用法:
-1
-l:列出所有参数
-f f1,f2 例如 varnishstat -f cache_hit,cache_miss 只查看这两项
# 需要关注的几个参数
cache hit
cache miss
client_req
client_conn
n_wrk
n_wrk_create
n_backend
n_expired
n_lru_moved
s_hdrbytes
s_bodybytes
2 varnishtop 实时显示日志中的信息
用法:
-i tag : 仅显示指定的tag,如RxHeader
-I regexp : 以模式匹配tag对应值;
-C :正则表达式匹配时不区分字符大小写;
3 varnishlog
#server varnishlog start 开启varnishlog
#tail -f /var/log/varnish/varnish.log
4 varnishreplay 日志重放工具,用于实现缓存预热几个重要调整的参数
# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 # varnish> help # varnish> param.show 查看所有参数 几个重要的参数 thread_pool_add_delay 两个客户端创建线程池时的时间间隔 thread_pool_fail_delay 创建线程池失败后,第二次创建时的时间间隔 thread_pool_max 一个线程池中默认装载的最大的线程数 thread_poo_min 一个线程池中默认装载的最小的线程数,限定避免其过于不均衡,防止在繁忙中有的线程池不能少于这个值 thread_pool_purge_delay 多长时间清理一次线程, thread_pool_timeout 一个线程空闲多长时间 就清除掉 thread_pool_workspace 一个线程池 thread_pools 工作线程池的个数 thread_stats_rate 一批搜集多少个工作线程的状态信息 参数调整方法 # varnish> param.show thread_pools # varnish> param.set thread_pools 3 # varnish> param.show thread_pools
思考篇
缓存命中率低的原因
缓存空间太小 --------------增大内存,增大磁盘 不存在明显的热点数据------------(二八法则:80%的请求落在20%的数据上 )---可以不用做缓存了,或者将原数据全部做到缓存 源文件更新过于频繁 -----------建议不要使用缓存了 缓存服务器的可用性 ---------------做分布式
本文出自 “西风瘦猪” 博客,请务必保留此出处http://jungege.blog.51cto.com/4102814/1408107
强大的http加速器------varnish,布布扣,bubuko.com
原文地址:http://jungege.blog.51cto.com/4102814/1408107