关于varnish缓存

2023-05-16

目录

  • 引言:缓存的概念
  • 一、varnish缓存
    • 1. 简介
    • 2. 总体结构
      • 2.1 两个主进程
      • 2.2 Varnish的日志
      • 2.3 VCL—varnish配置缓存策略的工具
  • 二、Varnish的工作模式(more)
    • 1. 状态引擎的处理流程
    • 2. Vcl内置函数和状态引擎的核心
      • 2.1 Vcl内置函数
      • 2.2 vcl的配置语法
    • 3. Vcl内置变量
  • 三、配置与管理工具
    • 1. varnish配置文件
    • 2. 管理工具(more)
      • 2.1 varnishd—启动命令
      • 2.2 varnishstat—缓存信息统计
      • 2.3 varnishtop—日志条目排名
      • 2.4 varnishadm—控制正在运行的Varnish实例

引言:缓存的概念

熟悉一些名词:

  • 时间局部性:一个数据被访问过之后,可能很快会被再次访问到;
  • 空间局部性:一个数据被访问时,其周边的数据也有可能被访问到

  • 数据缓存:例如MySQL到web应用服务器之间的缓存,服务器缓存的资源是数据缓存
  • 页面缓存:接入层和应用层中间的缓存,服务器缓存的是可缓存的页面,这层就是缓存层

  • 缓存命中率:hit/(hit+miss),一般高于30%命中率则是正向收益,好的设计系统可以达到80%到95%以上
  • 字节命中率:按照数据的字节大小来计算命中率
  • 请求命中率:按照请求的数量来计算命中率

  • 代理式缓存:客户端访问缓存服务器,缓存服务器没有命中缓存时到后端服务器请求数据,此时它作为反向代理服务器工作,这种类型的缓存服务器叫做代理式缓存
  • 旁挂式缓存:客户端亲自去查询数据库,并且将数据复制给缓存服务器一份,下次先去找缓存服务器,如果没有命中则再去数据库服务器查询,此时这种工作方式的缓存叫做旁挂式缓存,这个客户端叫做胖客户端(smart client)

  • private cache:私有缓存,用户代理附带的本地缓存机制
  • public cache:公共缓存,反向代理服务器的缓存功能

  • CND:Content Delivery Network 内容投递系统

  • GSLB:全网均衡调度

  • 缓存有效性判断机制
    • 过期时间
    • 条件式验证
      • Last-Modified/If-Modified-Since:基于文件的修改时间戳来判别
      • Etag/If-None-Match:基于文件的校验码来判别

“过期时间验证”缓存是否失效颗粒度太大,如果页面刚刚缓存应用服务器发生了变化,结果客户端拿到的就是过期数据;从而加入了条件式验证缓存的失效性,每次客户端请求到达缓存服务器,缓存服务器都要拿本地的数据和应用服务器的数据比较时间戳,如果时间戳发生了变化则缓存新的数据;这样虽然粒度小了,但是还是会有问题,如果应用服务器在同一秒页面数据变化了三次,而缓存服务器拿到的是第一份数据,这样还是会发生数据失效的问题;从而又引入了Etag(扩展标记)来标记唯一的页面数据。此时虽然解决了数据失效性的问题,但是每次客户端的请求都要去后端服务器做比较,对缓存和应用服务器都是不小的压力,我们不得不采取折中的解决方案就是“过期时间验证+条件式验证”,将不经常变动的页面做过期时间验证,变动频繁的采用条件式验证。

请求报文用于通知缓存服务如何使用缓存响应请求:

cache-request-directive = 
"no-cache" 不能使用缓存系统中的缓存响应我,必须先去应用服务器做缓存验证
"no-store" 不能使用缓存系统中的缓存响应我,必须去应用服务器请求响应我
"max-age" "=" delta-seconds 
"max-stale" [ "=" delta-seconds ]
"min-fresh" "=" delta-seconds
"no-transform"
"only-if-cached"
cache-extension

响应报文用于通知缓存服务器如何存储上级服务器响应的内容:

cache-response-directive =
"public" 所有缓存系统都可以缓存
"private" [ "=" <"> 1#field-name <"> ] 仅能够被私有缓存所缓存
"no-cache" [ "=" <"> 1#field-name <"> ],可缓存,但响应给客户端之前需要revalidation,即必须发出条件式请求进行缓存有效性验正
"no-store" ,不允许存储响应内容于缓存中
"no-transform" 不能转换格式
"must-revalidate" 必须重新验证
"proxy-revalidate" 
"max-age" "=" delta-seconds 私有缓存最大缓存时长
"s-maxage" "=" delta-seconds 公共缓存最大缓存时长
cache-extension

Web Page Cache解决方案:squid和varnish,它们的关系就像Apache和Nginx

一、varnish缓存

1. 简介

Varnish cache,是一套高性能的开源反向网站缓存服务器(reverse proxy server)、HTTP加速器 ,很多门户网站已经部署了varnish,并且性能要比squid高上许多,甚至比squid还稳定,且效率更高,资源占用更少。

特点:

  • Varnish可以使用内存也可以使用硬盘进行数据缓存
  • 支持虚拟内存的使用
  • 有精确的时间管理机制
  • 状态引擎架构:通过特定的配置语言设计不同的语句
  • 以二叉堆格式管理缓存数据

优势:

  • 稳定性强:将worker单独分开;
  • 速度快:采用“page Cache”技术,所有缓存数据直接从内存读取;
  • 支持多并发;
  • 通过管理端口,使用正则批量清除部分缓存;或者通过页面清;
  • 通过fork打开多进程处理

劣势:

  • 进程一旦crash或重启,缓存的数据将从内存中完全释放
  • 在多台varnish实现负载均衡时,每次请求都会落到不同的varnish服务器中,造成url请求可能会穿透到后
  • 劣势解决方案
    • a. 在varnish的后端添加squid/nignx代理,这样防止了当varnish缓存被清空时,瞬间大量的请求发往web服务器
    • b. 在负载均衡上做url哈西,让单个url请求固定请求到一台varnish服务器上

2. 总体结构

64380cd

如上图所示,主要进程:Management、Cacher。

2.1 两个主进程

2.1.1 Management进程

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

Manager管理的接口

  • CLI interface :命令行接口
  • Telnet interface :telnet接口
  • Web interface :Web管理接口

2.1.2 Child/Cacher进程

进程包括多个线程

  • Accept 线程:接收新的连接请求并响应
  • Worker 线程:child进程会为每个会话启动一个worker线程,因此,在高并发的场景中可能会出现数百个worker线程甚至更多;
  • Object Expiry 线程:从缓存中清理过期内容;
  • Commad line 线程 : 管理接口
  • Storage/hashing 线程 :缓存存储
  • Log/stats 线程:日志管理线程
  • Backend Communication 线程:管理后端主机线程
  • Varnish依赖“工作区(workspace)”以降低线程在申请或修改内存时出现竞争的可能性。在varnish内部有多种不同的工作区,其中最关键的当属用于管理会话数据的session工作区。

2.2 Varnish的日志

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

varnish提供了多个不同的工具如varnishlog、varnishncsa或varnishstat等来分析共享内存日志中的信息并能够以指定的方式进行显示。

2.3 VCL—varnish配置缓存策略的工具

Varnish Configuration Language(VCL)是varnish配置缓存策略的工具,它是一种基于域(domain specific)的简单编程语言,它支持有限的算术运算和逻辑运算操作、允许使用正则表达式进行字符串匹配、允许用户使用set自定义变量、支持if判断语句,也有内置的函数和变量等。

使用VCL编写的缓存策略通常保存至.vcl文件中(默认文件:$varnish_home/default.vcl,其需要编译成二进制的格式后才能由varnish调用,即编写的.vcl文件由VCL compiler来编译,VCL compiler调用C compiler来编译后由management来读取生效(读取是及时的),编译后management让各Child进程来应用生效(因为编译成sharedobject为各子进程各读取了一份)。事实上,整个缓存策略就是由几个特定的子例程如vcl_recv、vcl_fetch等组成,它们分别在不同的位置(或时间)执行,如果没有事先为某个位置自定义子例程,varnish将会执行默认的定义。

VCL策略在启用前,会由management进程将其转换为C代码,而后再由gcc编译器将C代码编译成二进制程序。编译完成后,management负责将其连接至varnish实例,即child进程。正是由于编译工作在child进程之外完成,它避免了装载错误格式VCL的风险。因此,varnish修改配置的开销非常小,其可以同时保有几份尚在引用的旧版本配置,也能够让新的配置即刻生效。编译后的旧版本配置通常在varnish重启时才会被丢弃,如果需要手动清理,则可以使用varnishadm的vcl.discard命令完成。

[VCL的工作流程]
vcl处理流程

(1)Receive 状态,也就是请求处理的入口状态,根据 VCL 规则判断该请求应该是 Pass 或Pipe,或者进入 Lookup(本地查询)。
(2)Lookup 状态,进入此状态后,会在 hash 表中查找数据,若找到,则进入 Hit 状态,否则进入 miss 状态。
(3)Pass 状态,在此状态下,会进入后端请求,即进入 fetch 状态。
(4)Fetch 状态,在 Fetch 状态下,对请求进行后端的获取,发送请求,获得数据,并进行本地的存储。
(5)Deliver 状态, 将获取到的数据发送给客户端,然后完成本次请求。

二、Varnish的工作模式(more)

说在前面:关于“内置函数/状态引擎”这两个名词概念:你只需记住varnish的缓存策略是基于vcl进行编写的,因此可以叫vcl内置函数/vcl状态引擎,也可以叫做varnish内置函数/varnish状态引擎;“内置函数”与”状态引擎“大致可以理解为同一事物的不同体现,”内置函数“可以在.vcl文件中直接体现,而”状态引擎“是”内置函数“在实现缓存的处理过程的一种抽象,怎么理解就见仁见智吧。

1. 状态引擎的处理流程

上面提到VCL是配置varnish缓存策略的工具,因此缓存的处理流程还是围绕VCL展开。
缓存策略的进行是由vcl状态引擎来实现的,所谓的状态引擎就是当一个用户请求到达后,根据处理逻辑到达不同阶段,在每个阶段中需要做出的处理动作可以理解为这个状态。

varnish工作流


详细流程
缓存策略在vcl状态引擎的体现

  • 图椭圆形部分称为varnish的状态节点,又称为vcl状态引擎,还有种叫法为varnish的vcl内置函数
  • 红色的线条:没有查询缓存/缓存中数据过期/缓存中没有数据 情况下的流程
  • 橙黄色的线条:直接将匹配数据通过内置函数vcl_pipe送往后台主机的流程
  • 绿色的线条:查询缓存数据命中且数据没有过期/经后台主机返回的数据经被缓存后返回给客户流程
  • 蓝色的线条:数据没有命中缓存向后台主机发出查询的流程
  • 黑色的线条:数据从后台主机返回给varnish缓存的流程

2. Vcl内置函数和状态引擎的核心

2.1 Vcl内置函数

基于vcl配置的varnish缓存策略,(结合上节)总结其作用如下:

vcl_recv:用于接受和处理请求。当请求到达并成功接收后被调用,通过判断请求的数据来决定如何处理请求。例如如何响应、怎么响应、使用哪个后端服务器等。
vcl_fetch:根据服务器端的响应作出缓存决策,如判断获取的内容来决定是将内容放入缓存,还是直接返回给客户端。
vcl_pipe:对于无法理解的用户请求,将请求直接发往后端主机;
vcl_hash:自定义hash生成时的数据来源
vcl_pass:用于将请求直接传递至后端主机,后端主机在应答数据后将应答数据发送给客户端,但不进行任何缓存。
vcl_hit:从缓存中查找到缓存对象时要执行的操作;
vcl_miss:从缓存中款查找到缓存对象时要执行的操作;
vcl_deliver:将用户请求的内容响应给客户端时用;
vcl_error:在varnish端合成错误响应而时;

因此,其大致流程可分为如下:

vcl_recv-->vcl_hash-->vcl_hit-->vcl_deliver
vcl_recv-->vcl_hash-->vcl_miss-->vcl_fetch-->vcl_deliver
vcl_recv-->vcl_pass-->vcl_fetch-->vcl_deliver
vcl_recv-->vcl_pipe

Engine

2.2 vcl的配置语法

(1) //, #, /*comment*/用于注释;
(2) sub $NAME 用于定义函数;
(3) 不支持循环;
(4) 有众多内置变量;
(5) 支持终止语句,没有返回值;
(6) “域”专用语言;
(7) 操作符: =, ==, ~, !, &&, ||

pipe 无法理解请求方法,管道直接送到后台
pass 不查缓存

常用语句

if else
set name=value
unset name
req.http.HEADER:调用请求报文中http协议的指定的变量
req.request:请求方法

3. Vcl内置变量

太多了,现学现查:

官方连接:https://varnish-cache.org/docs/6.3/reference/vcl.html#varnish-configuration-language


三、配置与管理工具

$varnish_home/default.vcl:编写缓存策略的核心配置,通过官网学习最新的Varnish子进程的使用。
$varnish_home/varnish.params:配置varnish服务启动时,进程的工作特性,例如监听的地址和端口,缓存机制;(注:自”5.0“版本开始,已经没有此参数文件,且官方给出的参考是可以从命令行设置启动的运行参数。

1. varnish配置文件

涉及知识包括:vcl内置函数、常用变量、条件语句等,上文中已做一些基础入门。
需要深入学习请点击进阶传送门

2. 管理工具(more)

2.1 varnishd—启动命令

通过varnishd命令来启动varnish服务:

varnishd -a 0.0.0.0:80 -s malloc,10g -t 2592000 -w 200,4000,300 -h classic,300000 -p thread_pools=10 -p session_linger=100 -p listen_depth=4096 -p lru_interval=3600 -p sess_workspace=9437184 -p http_resp_size=4194304 -p thread_pool_workspace=9437184 -u admin -g admin -f /path/varnish.vcl

下面分析下上面主要的几个参数:

-a 0.0.0.0:80 #设置varnish监听本机80端口的请求
-s malloc,10g #分配10G的内存用于缓存
-t 2592000 #设置缓存对象过期时间为30天
-w 200,4000,300 #设置线程池中最小线程和最大线程数及线程空闲时间
-h classic,300000 #设置hash算法classic,bucket推荐为缓存对象数的10倍默认为16383,simple_list算法不推荐生产环境使用,critbit算法是一个几乎无锁的树
-p thread_pools=10 #设置线程池大小
-p session_linger=100 #让session重用的时间,重用session可提高性能,这个值设的太大如果没有重用就浪费资源,如果太小重用率太低(大家自己权衡设置)
-p listen_depth=4096 #监听队列的深度
-p sess_workspace=9437184 #session工作内存的大小,vcl操作中需要用到这些内存
-p http_resp_size=4194304 #后端请响应允许的最大字节数,这个的内存就是从上面的sess_workspace分配的
-p thread_pool_workspace=9437184 #设置线程池内存大小,vcl中处理请求和响应将用到
-u admin #以admin用户运行varnish服务
-g admin #以admin组运行varnish服务
-f /path/varnish.vcl #指定vcl配置

2.2 varnishstat—缓存信息统计

#显示指定参数的当前统计数据
varnishstat -1 -f MAIN.cache_hit -f MAIN.cache_miss 
#列出指定配置段的每个参数的意义
varnishstat -l -f MAIN -f MEMPOOL 

2.3 varnishtop—日志条目排名

-1:打印统计信息一次并退出,而不是持续更新的显示
-i taglist:可以同时使用多个-i选项,也可以一个选项跟上多个标签
-I <[taglist:]regex>:对指定的标签的值基于regex进行过滤
-x taglist:排除列表
-X <[taglist:]regex>:对指定的标签的值基于regex进行过滤,符合条件的予以排除

2.4 varnishadm—控制正在运行的Varnish实例

#登录管理程序
varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 

 
[sleepy↓]







 

转载于:https://www.cnblogs.com/sunhongleibibi/p/11613188.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于varnish缓存 的相关文章

随机推荐

  • PX4 FMU启动流程 2. 二、 nsh_initscript

    PX4 FMU启动流程 2 二 nsh initscript PX4 FMU启动流程 2 二 nsh initscript 转载请注明出处 2014 11 27 冷月追风
  • Eigen库

    MatrixXd表示任意size的矩阵 xff0c 元素类型为double VectorXd表示任意size的向量 xff0c 元素类型为double 创建3 1的向量v xff0c 并赋值为1 2 3 VectorXd v 3 v lt
  • 亲爱的热爱的百度云全集资源

    网盘链接 转载于 https www cnblogs com awesome share p 11234341 html
  • 解决Docker容器 iptables问题---docker: Error response from daemon: driver failed programming external conne...

    一 问题现象 最近在研究Docker容器日志管理时 xff0c 启动容器出现iptables相关报错 xff0c 具体问题如下 运行容器 root 64 node 11 docker run d p 24224 24224 p 24224
  • 内网穿透远程查看内网监控摄像头

    在现代社会中 xff0c 大家总是奔波于家和公司之间 大部分时间用于工作中 xff0c 也就很难及时知晓家中的动态情况 xff0c 对于家中有老人 小孩或宠物的 xff08 甚至对居住环境安全不放心的 xff09 xff0c 这已然是个棘手
  • 2022/6/15 docker安装与项目部署(入门教程)

    目录 一丶docker简介 二丶Docker私库简介 xff08 Dockerhub xff09 三丶Docker优势 四丶docker安装 4 1 使用官方安装脚本自动安装 xff08 仅适用于公网环境 xff09 4 2 手动安装 4
  • vim实现批量注释和批量删除注释

    批量注释 1 进入文档 xff0c vim test txt 后 xff0c 按住ctrl 43 v进入VISUAL BLOCK模式 xff0c 上下选择需要注释的行 2 按大写键 xff0c 再按i xff0c 或者直接按shift 43
  • 20191003

    A 把字典树建出来 xff0c 问题就转化成要选择m个节点 xff0c 使得它们能覆盖所有叶子节点 xff0c 且不存在两个节点使得一个是另一个的祖先 于是可以在字典树上跑树形dp xff0c 复杂度 O n 2m 或 O nm 2 xff
  • 20191004

    A 解 1 我们发现只需要关心处于结果字符串前 k 位的字符 因此考虑从后往前处理 对于一个询问区间 xff0c 我们暴力连边 xff0c 用并查集维护 xff0c x 的父亲等于 y 相当于位于 x 的字符是从位于 y 的字符处复制过来的
  • git 如何解决 (master|MERGING)

    git 如何解决 master MERGING git reset hard head 回退版本信息 git pull origin master 转载于 https www cnblogs com 651434092qq p 110188
  • linux ping 指定次数

    ping 192 168 0 1 c4 转载于 https www cnblogs com sea stream p 10345600 html
  • java 解决 java.lang.Integer cannot be cast to java.lang.String

    1 在执行代码打印map的value时 xff0c 提示错误java lang Integer cannot be cast to java lang String xff0c 这个错误很明显是类型转换错误 查看表字段的数据 解决方案 1
  • DBoW2应用

    图像对应的bag of words向量 v t 假设词典总共有 W 个单词 xff0c 那么每一幅图像能够用一个 W 维的向量表示 xff08 t 1 t 2 t 3 t W xff09 其中 t i 61 frac n id n nd l
  • 平衡车终于成功了

    说来惭愧2017 12 0118 13 27 并非原创 xff0c 代码资料也是从论坛搜刮的 自己做了适配性的调整 这个小车断断续续造了将近1个月 xff01 1 include 34 Wire h 34 96 2 include lt U
  • 彻底解决 Jenkins Slaver 节点无法执行 Git-LFS 命令

    最新配置新增一台iMac当作持续集成构建的Slaver节点 xff0c 添加节点很顺利 xff0c 但是拉取代码的时候发现无法正常 出现以下提示 xff1a hudson plugins git GitException Command 3
  • FreeRTOS

    在嵌入式领域中 xff0c 嵌入式实时操作系统正得到越来越广泛的应用 采用嵌入式实时操作系统 RTOS 可以更合理 更有效地利用CPU的资源 xff0c 简化应用软件的设计 xff0c 缩短系统开发时间 xff0c 更好地保证系统的实时性和
  • 使用固定的公网TCP端口地址远程桌面【内网穿透】

    文章目录 1 为远程桌面保留一个TCP地址2 配置远程桌面隧道2 1 登录cpolar web ui2 2 修改远程桌面隧道信息2 3 查看公网地址 3 使用固定TCP地址远程桌面总结 在上一篇文章中 xff0c 我们通过cpolar映射远
  • [Openwrt 项目开发笔记]:Openwrt平台搭建(一)补遗

    Openwrt项目开发笔记 系列文章传送门 xff1a http www cnblogs com double win p 3888399 html 正文 xff1a 昨晚上熬夜写了 Openwrt项目开发笔记 Openwrt平台搭建 xf
  • Mac下IDEA启动Springboot项目慢

    经过百度以及google查询发现 xff0c 启动时调用了java net InetAddress getLocalHost 方法 以此排查调用此方法慢的问题 网上的解决方法都是修改hosts xff0c 后来有人提出 xff0c 慢的原因
  • 关于varnish缓存

    目录 引言 xff1a 缓存的概念一 varnish缓存 1 简介2 总体结构 2 1 两个主进程2 2 Varnish的日志2 3 VCL varnish配置缓存策略的工具二 Varnish的工作模式 more 1 状态引擎的处理流程2