Varnish原理和配置详解

一、varnish的简介

Varnish 是一款高性能且开源的反向代理服务器和 HTTP 加速器,其采用全新的软件体系机构,和现在的硬件体系紧密配合,与传统的squid 相比,varnish 具有性能更高、速度更快、管理更加方便等诸多优点,很多大型的网站都开始尝试使用 varnish 来替换 squid,这些都促进varnish 迅速发展起来。

1、varnish的架构

varnish主要运行两个进程:Management进程和Child进程(也叫Cache进程)。它们的工作原理大致如下图:

Management进程:

Management进程主要实现应用新的配置、编译VCL、监控varnish、初始化varnish以及提供一个命令行接口等。Management进程会每隔几秒钟探测一下Child进程以判断其是否正常运行,如果在指定的时长内未得到Child进程的回应,Management将会重启此Child进程。

Child进程:

Child进程包含多种类型的线程,常见的如:Acceptor线程:接收新的连接请求并响应;Worker线程:child进程会为每个会话启动一个worker线程,因此,在高并发的场景中可能会出现数百个worker线程甚至更多;Expiry线程:从缓存中清理过期内容;

Varnish依赖“工作区(workspace)”以降低线程在申请或修改内存时出现竞争的可能性。在varnish内部有多种不同的工作区,其中最关键的当属用于管理会话数据的session工作区。

日志:

为了与系统的其它部分进行交互,Child进程使用了可以通过文件系统接口进行访问的共享内存日志(shared memory log),因此,如果某线程需要记录信息,其仅需要持有一个锁,而后向共享内存中的某内存区域写入数据,再释放持有的锁即可。而为了减少竞争,每个worker线程都使用了日志数据缓存。

共享内存日志大小一般为90M,其分为两部分,前一部分为计数器,后半部分为客户端请求的数据。varnish提供了多个不同的工具如varnishlog、varnishncsa或varnishstat等来分析共享内存日志中的信息并能够以指定的方式进行显示。

二、varnish的后端存储

varnish支持多种不同类型的后端存储,这可以在varnishd启动时使用-s选项指定。后端存储的类型包括:

(1)file: 使用特定的文件存储全部的缓存数据,并通过操作系统的mmap()系统调用将整个缓存文件映射至内存区域(如果条件允许);

(2)malloc: 使用malloc()库调用在varnish启动时向操作系统申请指定大小的内存空间以存储缓存对象,类似于C语言中的malloc动态申请函数;

file和malloc存储方法类似,重启缓存服务时,先前缓存的数据不复存在。

三、varnish的状态引擎(state engine)

说道varnish的状态引擎,不得不说vcl(Varnish Configuration Language:varnish配置缓存策略的工具)。它是基于域的一种简单的编程语言,支持算数运算、允许使用正则表达式、支持if语句等。使用vcl语言编写的缓存策略通常保存于.vcl文件中,其需要编译成二进制的格式后才能由varnish调用。

VCL用于让管理员定义缓存策略,而定义好的策略将由varnish的management进程分析、转换成C代码、编译成二进制程序并连接至child进程。varnish内部有几个所谓的状态(state),在这些状态上可以附加通过VCL定义的策略以完成相应的缓存处理机制,因此VCL也经常被称作“域专用”语言或状态引擎,“域专用”指的是有些数据仅出现于特定的状态中。

具体的状态的是通过定义内置函数来实现的,具体过程如下图:

vcl各状态引擎的功用:
vcl_recv:是在Varnish完成对请求报文的解码为基本数据结构后第一个要执行的子例程
vcl_fetch:根据服务器端的响应作出缓存决策
vcl_pipe:用于将请求直接发往后端主机;
vcl_hash:自定义hash生成时的数据来源
vcl_pass:用于将请求直接传递至后端主机;
vcl_hit:从缓存中查找到缓存对象时要执行的操作;
vcl_miss:从缓存中款查找到缓存对象时要执行的操作;
vcl_deliver:将用户请求的内容响应给客户端时用到的方法; 
vcl_error:在varnish端合成错误响应而时;

四、HTTP协议与varnish

缓存相关的HTTP首部:

HTTP协议提供了多个首部用以实现页面缓存及缓存失效的相关功能,这其中最常用的有:
(1)Expires:用于指定某web对象的过期日期/时间,通常为GMT格式;一般不应该将此设定的未来过长的时间,一年的长度对大多场景来说足矣;其常用于为纯静态内容如JavaScripts样式表或图片指定缓存周期;
(2)Cache-Control:用于定义所有的缓存机制都必须遵循的缓存指示,这些指示是一些特定的指令,包括public、private、no-cache(表示可以存储,但在重新验正其有效性之前不能用于响应客户端请求)、no-store、max-age、s-maxage以及must-revalidate等;Cache-Control中设定的时间会覆盖Expires中指定的时间;
(3)Etag:响应首部,用于在响应报文中为某web资源定义版本标识符;
(4)Last-Mofified:响应首部,用于回应客户端关于Last-Modified-Since或If-None-Match首部的请求,以通知客户端其请求的web对象最近的修改时间;
(5)If-Modified-Since:条件式请求首部,如果在此首部指定的时间后其请求的web内容发生了更改,则服务器响应更改后的内容,否则,则响应304(not modified);
(6)If-None-Match:条件式请求首部;web服务器为某web内容定义了Etag首部,客户端请求时能获取并保存这个首部的值(即标签);而后在后续的请求中会通过If-None-Match首部附加其认可的标签列表并让服务器端检验其原始内容是否有可以与此列表中的某标签匹配的标签;如果有,则响应304,否则,则返回原始内容;
(7)Vary:响应首部,原始服务器根据请求来源的不同响应的可能会有所不同的首部,最常用的是Vary: Accept-Encoding,用于通知缓存机制其内容看起来可能不同于用户请求时Accept-Encoding-header首部标识的编码格式;
(8)Age:缓存服务器可以发送的一个额外的响应首部,用于指定响应的有效期限;浏览器通常根据此首部决定内容的缓存时长;如果响应报文首部还使用了max-age指令,那么缓存的有效时长为“max-age减去Age”的结果;

五、安装配置varnish

# rpm包下载地址:https://repo.varnish-cache.org/
rpm -ivh varnish-3.0.5-1.el6.x86_64.rpm varnish-libs-3.0.5-1.el6.x86_64.rpm varnish-docs-3.0.5-1.el6.x86_64.rpm

修改varnish的相关参数:

## /etc/sysconfig/varnish 的有效参数如下:
NFILES=131072
MEMLOCK=82000
NPROCS="unlimited"
RELOAD_VCL=1
VARNISH_VCL_CONF=/etc/varnish/default.vcl
VARNISH_LISTEN_PORT=80			# 一般修改varnish的监听端口
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1
VARNISH_ADMIN_LISTEN_PORT=6082
VARNISH_SECRET_FILE=/etc/varnish/secret
VARNISH_MIN_THREADS=50
VARNISH_MAX_THREADS=1000
VARNISH_THREAD_TIMEOUT=120
VARNISH_STORAGE_FILE=/var/lib/varnish/varnish_storage.bin
VARNISH_STORAGE_SIZE=1G
VARNISH_STORAGE_MEM_SIZE=128M      	# 使用malloc存储方法时的内存大小
VARNISH_STORAGE="malloc,${VARNISH_STORAGE_MEM_SIZE}"	 # 配置后端存储方法为malloc
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}              -w ${VARNISH_MIN_THREADS},${VARNISH_MAX_THREADS},${VARNISH_THREAD_TIMEOUT}              -u varnish -g varnish              -S ${VARNISH_SECRET_FILE}              -s ${VARNISH_STORAGE}"

配置vcl的相关参数:

# 修改 /etc/varnish/default.vcl 中以下内容:
backend default {
  .host = "172.16.10.11";
  .port = "80";
}

结果展示:

此时我们访问:http://172.16.10.77时,会发现第一次响应速度比较慢,随后的响应是很快的。

此时,可以通过varnishstat查看缓存命中情况。

也可以自行定义缓存策略:

Varnish内置变量:
请求到达时可用的内置变量:
    req.url
    req.request
    req.http.HEADER
    req.restarts: 请求被重启的次数;
    server.ip
    server.port
    server.hostname
    client.ip
    req.backend 

向后后端主机请求时可用的内置变量
    bereq.url
    bereq.request
    bereq.http.HEADER
    bereq.connect_timeout
    bereq.proto 

从后端主机获取到响应的object时可用的内置变量
    beresp.status
    beresp.response
    beresp.http.HEADER
    beresp.ttl
    beresp.backend.name
    beresp.backend.ip
    beresp.backend.port 

缓存对象进入缓存时可用的内置变量(只能用于vcl_hit或vcl_error,且大多为只读)
    obj.status
    obj.response
    obj.ttl
    obj.hits
    obj.http.HEADER 

响应给客户端时可用的内置变量
    resp.proto
    resp.status
    resp.response
    resp.http.HEADER

自定义web.vcl,内容如下:

[[email protected] ~]# cat /etc/varnish/web.vcl 
# 定义后端主机,并提供健康状态检测
backend web1 {
  .host = "172.16.10.11";
  .probe = {
	.url="/index.html";
	.interval=2s;
	.window=8;
	.threshold=2;
  }
}
backend web2 {
  .host = "172.16.10.16";
  .probe = {
        .url="/index.html";
        .interval=2s;
        .window=8;
        .threshold=2;
  }
}

director websrv round-robin {
	{ .backend = web1; }
	{ .backend = web2; }
}

# 定义一个acl 目的是进行缓存裁剪
acl purgers {
	"127.0.0.1";
	"172.16.0.0"/16;
}
sub vcl_recv {
	set req.backend = websrv;
	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.url ~ "^/test.html$") {
	   	return(pass);
	}
	if (req.request == "PURGE") {
		if (!client.ip ~ purgers) {
			error 405 "Method not allowed";
		 }
	return (lookup);
	}
     if (req.request != "GET" &&
       req.request != "HEAD" &&
       req.request != "PUT" &&
       req.request != "POST" &&
       req.request != "TRACE" &&
       req.request != "OPTIONS" &&
       req.request != "DELETE") {
         /* Non-RFC2616 or CONNECT which is weird. */
         return (pipe);
     }
     if (req.request != "GET" && req.request != "HEAD") {
         /* We only deal with GET and HEAD by default */
         return (pass);
     }
     if (req.http.Authorization || req.http.Cookie) {
         /* Not cacheable by default */
         return (pass);
     }
     return (lookup);
}
sub vcl_pipe {
    return (pipe);
}
# sub vcl_hash {
#     hash_data(req.url);
#     if (req.http.host) {
#         hash_data(req.http.host);
#     } else {
#         hash_data(server.ip);
#     }
#     return (hash);
# }

sub vcl_hit {
        if (req.request == "PURGE") {
                purge;
                error 200 "Purged";
        }
     return (deliver);
} 

sub vcl_miss {
        if (req.request == "PURGE") { 
                purge;
                error 404 "Not in cache";
        }
     return (fetch);
}

sub vcl_pass {
        if (req.request == "PURGE") {
                error 502 "PURGE on a passed object";
        }
     return (pass);
} 
# 
# sub vcl_fetch {
#     if (beresp.ttl <= 0s ||
#         beresp.http.Set-Cookie ||
#         beresp.http.Vary == "*") {
# 		/*
# 		 * Mark as "Hit-For-Pass" for the next 2 minutes
# 		 */
# 		set beresp.ttl = 120 s;
# 		return (hit_for_pass);
#     }
#     return (deliver);
# }

sub vcl_deliver {
        set resp.http.X-Age = resp.http.Age;
        unset resp.http.Age;

        if (obj.hits > 0) {
                set resp.http.X-Cache = "HIT Via" + " " + server.hostname;
        } else {
                set resp.http.X-Cache = "MISS Via" + " " + server.hostname;
        }
	return (deliver);
}
# sub vcl_deliver {
#
#
#     return (deliver);
# }
# 
# sub vcl_error {
#     set obj.http.Content-Type = "text/html; charset=utf-8";
#     set obj.http.Retry-After = "5";
#     synthetic {"
# <?xml version="1.0" encoding="utf-8"?>
# <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
#  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
# <html>
#   <head>
#     <title>"} + obj.status + " " + obj.response + {"</title>
#   </head>
#   <body>
#     <h1>Error "} + obj.status + " " + obj.response + {"</h1>
#"} + obj.response + {"#     Guru Meditation:
#XID: "} + req.xid + {"#     <hr>
#Varnish cache server#   </body>
# </html>
# "};
#     return (deliver);
# }
# 
sub vcl_init {
	return (ok);
}

sub vcl_fini {
	return (ok);
}

可以使用varnishadm命令手动编译vcl文件:

补充:

vcl自动编译的方法,编辑 /etc/sysconfig/varnish 文件中的:

VARNISH_VCL_CONF=/etc/varnish/web.vcl

时间: 2025-01-15 12:19:39

Varnish原理和配置详解的相关文章

varnish安装及配置详解

varnish系统架构: varnish主要运行两个进程:Management进程和Child进程(也叫Cache进程). Management进程主要实现应用新的配置.编译VCL.监控varnish.初始化varnish以及提供一个命令行接口等.Management进程会每隔几秒钟探测一下Child进程以判断其是否正常运行,如果在指定的时长内未得到Child进程的回应,Management将会重启此Child进程. Child进程包含多种类型的线程,常见的如:Acceptor线程:接收新的连接

Linux学习之路-DNS原理-BIND配置详解

DNS原理-BIND配置详解 DNS系统概述 DNS系统作用     a) DNS,简单地说,就是Domain Name System,翻成中文就是"域名系统".主要的功能就是将人易于记忆的Domain Name与人不容易记忆的IP Address作转换.      b) DNS提供正向解析和反向解析          正向解析:根据主机名称(域名)查找对应的IP地址.          反向解析:根据IP地址查找对应的主机域名 DNS系统结构  系统结构原理  目前DNS采用的是分布

Mysql主从数据库架构的复制原理及配置详解

1 复制概述 Mysql内建的复制功能是构建大型,高性能应用程序的基础.将Mysql的数据分布到多个系统上去,这种分布的机制,是通过将Mysql的某一台主机的数据复制到其它主机(slaves)上,并重新执行一遍来实现的.复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器.主服务器将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环.这些日志可以记录发送到从服务器的更新.当一个从服务器连接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置.从服务器接收

nagios原理及配置详解

1.Nagios如何监控Linux机器 NRPE总共由两部分组成:(1).check_nrpe插件,运行在监控主机上.服务器端安装详见:(2).NRPE daemon,运行在远程的linux主机上(通常就是被监控机)客户端具体安装详见: 图1按照上图,整个的监控过程如下:当Nagios需要监控某个远程linux主机的服务或者资源情况时:1).nagios会运行check_nrpe插件,我们要在nagios配置文件中告诉它要检查什么.2).check_nrpe插件会通过SSL连接到远程的NRPE

Spring MVC原理及配置详解

Spring MVC原理及配置 1.Spring MVC概述: Spring MVC是Spring提供的一个强大而灵活的web框架.借助于注解,Spring MVC提供了几乎是POJO的开发模式,使得控制器的开发和测试更加简单.这些控制器一般不直接处理请求,而是将其委托给Spring上下文中的其他bean,通过Spring的依赖注入功能,这些bean被注入到控制器中. Spring MVC主要由DispatcherServlet.处理器映射.处理器(控制器).视图解析器.视图组成.他的两个核心是

Varnish工作原理及配置详解

1.基本概念 在当前主流的Web架构中,Cache担任着越来越重要的作用.常见的基于浏览器的C/S架构,Web Cache更是节约服务器资源的关键.而最近几年由FreeBSD创始人之一Kamp开发的varnish更是一个不可多得的Web Cache Server.严格意义上说,Varnish是一个高性能的反向代理软件,只不过与其出色的缓存功能相比,企业更愿意使用其搭建缓存服务器.同时,由于其工作在Web Server的前端,有一部分企业已经在生产环境中使用其作为旧版本的squid的替代方案,以在

【Spring】Spring MVC原理及配置详解

1.Spring MVC概述: Spring MVC是Spring提供的一个强大而灵活的web框架.借助于注解,Spring MVC提供了几乎是POJO的开发模式,使得控制器的开发和测试更加简单.这些控制器一般不直接处理请求,而是将其委托给Spring上下文中的其他bean,通过Spring的依赖注入功能,这些bean被注入到控制器中. Spring MVC主要由DispatcherServlet.处理器映射.处理器(控制器).视图解析器.视图组成.他的两个核心是两个核心: 处理器映射:选择使用

MySQL主从原理及配置详解

MySQL主从配置及原理,供大家参考,具体内容如下 一.环境选择: 1.Centos 6.5 2.MySQL 5.7 二.什么是MySQL主从复制 MySQL主从复制是其最重要的功能之一.主从复制是指一台服务器充当主数据库服务器,另一台或多台服务器充当从数据库服务器,主服务器中的数据自动复制到从服务器之中.对于多级复制,数据库服务器即可充当主机,也可充当从机.MySQL主从复制的基础是主服务器对数据库修改记录二进制日志,从服务器通过主服务器的二进制日志自动执行更新. 三.MySQL主从复制的类型

CIsco路由器实现IPSec 虚拟专用网原理及配置详解

博文大纲:一.虚拟专用网概述:1.虚拟专用网的定义:2.虚拟专用网的模型与类型:(1)虚拟专用网的连接模式:(2)虚拟专用网的类型: 二.虚拟专用网技术:1.加密技术:(1)对称加密算法:(2)非对称加密算法:(3)密钥交换:2.数据报文验证:(1)HMAC功能实现验证功能:(2)MD5和SHA: 三.IPSec 虚拟专用网: 1.IPsec连接:2.ISAKMP/IKE阶段1:3.ISAKMP/IKE阶段2:四.配置实现IPSec 虚拟专用网:五.常用排错的命令: 关于虚拟专用网理论知识较多,