简介

Varnish是一款高性能、开源的缓存反向代理服务器。它从客户端接受请求,并尝试从缓存中响应请求,如果无法从缓存中提供响应,Varnish 向后端服务器发起请求,获取响应,将响应存储在缓存中,然后把响应发送给客户端。如果Varnish能够从Cache中响应一个请求,所消耗的时间是微秒级别的,这个响应速度比直接从HTTP服务器响应请求的速度要快两个数量级,缓存命中率越高,网站的访问速度就越快。

主要特性

  • 缓存位置:可以使用内存也可以使用磁盘,如果要使用磁盘的话推荐SSD做RAID1;
  • 日志存储:日志也存储在内存中,存储策略:固定大小,循环使用;
  • 支持虚拟内存的使用;
  • 有精确的时间管理机制,即缓存的时间属性控制;
  • 状态引擎架构:在不同的引擎上完成对不同的缓存和代理数据进行处理,可以通过特定的配置语言设计不同的控制语句,以决定数据在不同位置以不同方式缓存;
  • 缓存管理:以二叉堆格式管理缓存数据,做到数据的及时清理。

系统架构

Varnish主要有两个进程:Management进程与Child进程(也称为Cache进程)。

  • Management进程:主要对子进程进行管理,实现应用新的配置、编译VCL、监控varnish、初始化varnish以及提供一个命令行接口等;Management进程会每隔几秒钟探测一下Child进程以判断其是否正常运行,如果在指定的时长内未得到Child进程的回应,Management将会重启此Child进程。
  • Child进程:生成线程池,负责对用户请求进行处理,并通过hash查找返回用户结果。

    Child进程包含多种类型的线程,常见的有:

    • Accept线程:接收新的连接请求并响应;
    • Worker线程:child进程会为每个会话启动一个worker线程,因此在高并发的场景中可能会出现数百个worker线程甚至更多;
    • Object Expiry线程:从缓存中清理过期内容;
    • Commad line线程 : 管理接口;
    • Storage/hashing线程:缓存存储;
    • Log/stats线程:日志管理线程;
    • Backend Communication线程:管理后端主机线程。

日志

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

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

算法

Varnish的Director支持的挑选方法中主要有round-robin(轮询)和random(随机)两种。其中,round-robin类型没有任何参数,只需要为其指定各后端主机即可,并在某后端主机故障时不再将其视作挑选对象;random方法随机从可用后端主机中进行挑选,每一个后端主机都需要一个.weight参数指定其权重,同时还可以使用.retires参数来设定查找一个健康后端主机时的尝试次数。

Varnish2.1.0后,random挑选方法又多了两种变化形式client和hash。client类型的Director使用client.identity作为挑选因子,这意味着client.identity相同的请求都将被发送至同一个后端主机;client.identity默认为cliet.ip,但也可以在VCL中将其修改为所需要的标识符。类似地,hash类型的Director使用hash数据作为挑选因子,这意味着对同一个URL的请求将被发往同一个后端主机,其常用于多级缓存的场景中。无论是client还hash,当其倾向于使用后端主机不可用时将会重新挑选新的后端其机。

VCL工具

Varnish Configuration Language(VCL),Varnish配置缓存策略的工具,它是一种基于“域”(domain specific)的简单编程语言,可以使用运算符包括“ =、==、!、&& ”等,支持使用正则表达式进行字符串匹配,允许用户使用set自定义变量,支持if判断语句,也有内置的函数和变量等。VCL策略在启用前,会由management进程将其转换为C代码,而后再由gcc编译器将C代码编译成二进制程序,编译完成后management负责将其连接至varnish实例,即child进程。

后端存储

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

  • file:使用特定的文件存储全部的缓存数据,并通过操作系统的mmap()系统调用,将整个缓存文件映射至内存区域(如果条件允许);
  • malloc:使用malloc()库调用在varnish启动时向操作系统申请指定大小的内存空间以存储缓存对象;
  • persistent(experimental):与file的功能相同,但可以持久存储数据(即重启varnish数据时不会被清除),但仍处于测试阶段。

Varnish无法追踪某缓存对象是否存入了缓存文件,也就无从得知磁盘上的缓存文件是否可用,因此file存储方法在varnish停止或重启时会清除数据;而persistent方法的出现对此有了一个弥补,但persistent仍处于测试阶段,其仅适用于有着巨大缓存空间的场景。

选择使用合适的存储方式有助于提升系统性。从经验的角度来看,建议在内存空间足以存储所有的缓存对象时使用malloc的方法,而file存储有着更好的性能表现。需要注意的是,varnishd实际上使用的空间比使用-s选项指定的缓存空间更大,一般说来,其需要为每个缓存对象多使用差不多1K左右的存储空间,这意味着,对于100万个缓存对象的场景来说,其使用的缓存空间将超出指定大小1G左右。另外,为了保存数据结构等,varnish自身也会占去不小的内存空间。

为varnishd指定使用的缓存类型时,-s 选项可接受的参数格式如下:

  • malloc [size] 或 file [path [size [granularity]]] 或 persistent path size {experimental}

VCL内置函数

  • vcl_recv函数:用于接收和处理请求。当请求到达并成功接收后被调用,通过判断请求的数据来决定如何处理请求。此函数一般以如下几个关键字结束:

    • pass:进入pass模式,把请求控制权交给vcl_pass函数;
    • pipe:进入pipe模式,把请求控制权交给vcl_pipe函数;
    • error code [reason]:返回code给客户端并放弃处理该请求;code是错误标识,例如200、405等;reason是错误提示信息。
  • vcl_pipe函数:此函数在进入pipe模式时被调用,用于将请求直接传递至后端主机,在请求和返回的内容没有改变的情况下,将不变的内容返回给客户端,直到这个链接关闭。此函数一般以如下几个关键字结束:
    • error code [reason]
    • pipe
  • vcl_pass函数:此函数在进入pass模式时被调用,用于将请求直接传递至后端主机,后端主机应答数据后送给客户端,但不进行任何缓存,在当前连接下每次都返回最新的内容。此函数一般以如下几个关键字结束:
    • error code [reason]
    • pass
  • vcl_hash:表示在缓存里查找被请求的对象,并且根据查找的结果把控制权交给函数vcl_hit或者函数vcl_miss
  • vcl_hit函数:在执行vcl_hash后,如果在缓存中找到请求的内容,将自动调用该函数。此函数一般以如下几个关键字结束:
    • deliver:表示将找到的内容发送给客户端,并把控制权交给函数vcl_deliver
    • error code [reason]
    • pass
  • vcl_miss函数:在执行val_hash后,如果没有在缓存中找到请求的内容时自动调用该方法,此函数可以用于判断是否需要从后端服务器取内容。此函数一般以如下几个关键字结束:
    • fetch:表示从后端获取请求的内容,并把控制权交给vcl_fetch函数
    • error code [reason]
    • pass
  • vcl_fetch函数:在从后端主机更新缓存并且获取内容后调用该方法,接着,通过判断获取的内容来决定是否将内容放入缓存,还是直接返回给客户端。此函数一般以如下几个关键字结束:
    • error code [reason]
    • pass
    • deliver
  • vcl_deliver函数:在缓存中找到请求的内容后,发送给客户端前调用此方法。此函数一般以如下几个关键字结束:
    • error code [reason]
    • deliver
  • vcl_timeout函数:此函数在缓存内容到期前调用。一般以如下几个关键字结束:
    • discard:表示从缓存中清除该内容。
    • fetch
  • vcl_discard函数:在缓存内容到期后或缓存空间不够时,自动调用该方法。此函数一般以如下几个关键字结束:
    • keep:表示将内容继续保留在缓存中
    • discard

以下是VCL处理流程图,通过下图可以更清楚Varnish的工作过程:

Varnish处理 HTTP请求 的过程分为以下几个步骤:

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

VCL内置公用变量

  • 当请求到达后,可以使用的公用变量如下所示:

    • req.backend:指定对应的后端主机
    • server.ip:表示服务器端IP
    • client.ip:表示客户端IP
    • req.request:指定请求的类型,例如GET、HEAD、POST等
    • req.url:指定请求的地址
    • req.proto:表示客户端发起请求的HTTP协议版本
    • req.http.header:表示对应请求中的http头部信息
    • req.restarts:表示请求重启的次数,默认最大值为4
  • Varnish 在向后端主机请求时,可以使用的公用变量如下所示:
    • beresp.request:指定请求的类型,例如GET、HEAD等
    • beresp.url:指定请求的地址
    • beresp.proto:表示客户端发起请求的HTTP协议版本
    • beresp.http.header:表示对应请求中的http头部信息
    • beresp.ttl:表示缓存的生存周期,也就是cache保留多长时间,单位是秒
  • 从cache或者后端主机获取内容后,可以使用的公用变量如下所示:
    • obj.status:返回内容的请求状态代码,例如200、302、504等
    • obj.cacheable:返回的内容是否可以缓存,也就是说,如果HTTP返回是200、203、300、301、302、404、410等,并且有非0的生存期,则可以缓存
    • obj.valid:表示是否是有效的HTTP应答
    • obj.response:返回内容的请求状态信息
    • obj.proto:返回内容的HTTP协议版本
    • obj.ttl:返回内容的生存周期,也就是缓存时间,单位是秒
    • obj.lastuse:返回上一次请求到现在的间隔时间,单位是秒
  • 对客户端应答时,可以使用的公用变量如下所示:
    • resp.status:返回客户端的HTTP状态代码
    • resp.proto:返回客户端的HTTP协议版本
    • resp.http.header:返回客户端的HTTP头部信息
    • resp.response:返回客户端的HTTP状态信息

  如果想要了解更多请查阅Varnish官方文档 查看文档

缓存反向代理-Varnish的更多相关文章

  1. nginx 反向代理与负载均衡应用实践

    集群介绍 集群就是指一组(若干个)相互独立的计算机,利用高速通信网络组成的一个较大的计算机服务系统,每个集群节点(即集群中的每台计算机)都是运行各自服务的独立服务器.这些服务器之间可以彼此通信,协同向 ...

  2. 轻量级别的Cache和反向代理软件---Varnish

    1.Varnish描述 1.1 Varnish的结构与特点 Varnish是一个轻量级别的Cache和反向代理软件,先进的设计理念和成熟的设计框架是Varnish的主要特点: 基于内存进行缓存,重启后 ...

  3. nginx的反向代理功能和缓存功能

    html { font-family: sans-serif } body { margin: 0 } article,aside,details,figcaption,figure,footer,h ...

  4. 高级运维(一):反向代理&使用Varnish加速Web

    案例1.反向代理      目标: 1.代理服务器可以将远程的Web服务器页面缓存于本地 2.代理服务器端口设置为80端口 3.用户通过访问代理服务器即可获得远程Web服务器页面上的内容 4.远程We ...

  5. WEB缓存系统之varnish代理以及健康状态检测配置

    前文我们聊了下varnish的缓存项修剪配置,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/12666406.html:今天我来说一下varnish作为代理服务 ...

  6. Nginx 反向代理、负载均衡、页面缓存、URL重写及读写分离详解

    转载:http://freeloda.blog.51cto.com/2033581/1288553 大纲 一.前言 二.环境准备 三.安装与配置Nginx 四.Nginx之反向代理 五.Nginx之负 ...

  7. Nginx反向代理、负载均衡、页面缓存、URL重写及读写分离详解

    大纲 一.前言 二.环境准备 三.安装与配置Nginx 四.Nginx之反向代理 五.Nginx之负载均衡 六.Nginx之页面缓存 七.Nginx之URL重写 八.Nginx之读写分离 注,操作系统 ...

  8. Nginx 反向代理、负载均衡、页面缓存、URL重写以及读写分离

    1.环境准备 前端Nginx:10.160.65.44 后端WEB服务器两台:10.160.65.49/10.160.65.50 2.安装Nginx: 下载nginx-1.9.15.tar.gz,放置 ...

  9. 解决nginx反向代理缓存不起作用的问题

    昨天尝试用nginx搭建nuget镜像服务器,镜像服务器需要两个功能:1)反向代理:2)内容缓存. 用nginx做反向代理,配置非常简单,只需在/etc/nginx/nginx.conf中添加一个包含 ...

随机推荐

  1. Windows API 编程-----DLL编程之禁止加载自己

    和可执行文件一样,动态链接库也有自己的入口地址,如果系统或者当前进程的某个线程调用LoadLibrary函数加载或者使用FreeLibrary卸载该动态链接库的时候,会自动使用3个特定的堆栈参数跳转到 ...

  2. Open images from USB camera on linux using V4L2 with OpenCV

    I have always been using OpenCV's VideoCapture API to capture images from webcam or USB cameras. Ope ...

  3. linux下通过NFS将远程磁盘mount到本地

    最近由于项目原因需要和其他两家公司对接,需要取对方服务器中的图像数据,原本约定是三方都通过http协议来进行通讯,奈何对接方不配合,说文件就在他们服务器放着,怎么取他们不管.所以采取将对方服务器磁盘挂 ...

  4. Codeforces Round #413 A. Carrot Cakes

    A. Carrot Cakes time limit per test   1 second memory limit per test   256 megabytes   In some game ...

  5. ANN神经网络——Sigmoid 激活函数编程练习 (Python实现)

    # ---------- # # There are two functions to finish: # First, in activate(), write the sigmoid activa ...

  6. Java—IO流 字符流

    java的文本(char)是16位无符号整数,是字符的unicode编码(双字节编码). 文件是byte byte byte ... 的数据序列. 文本文件是文本(char)序列按照某种编码方案(uf ...

  7. Data Flow ->> Multiple Excel Sheet Loaded Into One Table

    同个Excel文件中多个Sheet中的数据导入到单张表中,参考了文章:http://www.cnblogs.com/biwork/p/3478778.html 思路: 1) ForEach Loop组 ...

  8. 配置spark集群

    配置spark集群 1.配置spark-env.sh [/soft/spark/conf/spark-env.sh] ... export JAVA_HOME=/soft/jdk 2.配置slaves ...

  9. Python学习---Python下[set集合]的学习

    Set集合[可变]是一个无序的,不重复的数据组合,它的主要作用如下: 1. 去重,把一个列表变成集合,就自动去重了 2. 关系测试,测试两组数据之前的交集.差集.并集等关系 集合(set):把不同的元 ...

  10. 实战开发一个Nginx扩展 (Nginx Module)

    repo地址 https://github.com/wujunze/nginx-http-echo-module nginx_module_echo 使用echo指令输出一个字符串 Nginx 版本 ...