Varnish

在前端已经设置了缓存时间戳的情况下,后端数据库也已经更新,但是请求接口获取的数据仍然是老数据,排除了304重定向的问题,发现是服务器Varnish设置了缓存。

Varnish是一个http反向代理的缓存,高性能,轻量级,web应用程序加速器。
它通过缓存服务端的输出来减少你的网站/应用/API的加载时间,从而提高性能。
默认监听TCP80端口。

特点:

  • 基础内存进行缓存,重启后数据消失;
  • 利用虚拟内存方式,性能好;
  • 支持设置0-60秒的精确缓存时间;
  • VCL配置管理,比较灵活;
  • 状态机设计巧妙,结构清晰;
  • 后端服务器的负载均衡和健康检查 URL地址重写;
  • 优雅的处理后端服务器宕机的问题;

过程:

  1. varnish从客户端接收请求 然后尝试从缓存中获取数据来响应客户端的请求 ;
  2. 如果varnish不能从缓存中获得数据来响应客户端;
  3. 它将转发请求到后端,获取响应同时缓存到本地 最后交付给客户端;
  4. 如果varnish已经缓存了某个响应,则请求直接从varnish的缓存中获取响应;
  5. 比从后端服务器去获取数据快的多;

在这里插入图片描述
bereq.
由varnish发往服务器的http请求;
beresp.
由服务器响应给varnish的响应报文;
resp.
由varnish响应给client相关;
obj.
只读的,存储在缓存空间中的缓存对象的属性;
在这里插入图片描述

Management管理进程:
	编译VCL并应用新配置、监控varnish、初始化varnish并提供命令行接口CLI;

Child/Cache线程:
    Acceptor:用于接收并连接请求;
    Worker:用于处理并响应用户请求;
    Object expiry:从缓存中清理过期的cache object;
    cache-main:此线程只有一个,用于启动cache;
    banluker:清理指定缓存;
    expire:清理过期缓存
    epoll:线程池管理器;

varnish定义其最大并发连接数是通过线程池模型实现的:
    thread_pools:线程池个数,默认为2;
    thread_pool_max:单线程池内允许启动的最大线程个数;
    thread_pool_min:单线程池内允许启动的最小线程个数;
    thread_pool_timeout:多于thread_pool_min的线程空闲此参数指定的时长后即被purge;

Log file:
	varnish的日志,为保持其高性能,保持在一段共享内存空间中--Shared Memory Log,共享内存日志大小一般为90M,分为两部分:前一部分为计数器,后一部分为客户请求相关的数据,可以计算缓存命中率、分析请求首部、记录响应首部等;

vcl:Varnish Configuration Language
    缓存策略配置工具;
    基于“域”的简单编程语言,意为其所有代码都是写在各“{}”中,且作用范围仅为对应的“{}”,这些“域”称为varnish的状态引擎;

varnish定义其最大并发连接数:线程池模型:
    thread_pools:线程池个数;默认为2;
    thread_pool_max:单线程池内允许启动的最多线程个数;
    thread_pool_min

thread_pool_timeout:多于thread_pool_min的线程空闲此参数指定的时长后即被purge;

实现负载均衡

1、varnish实现调度的方式:

round-robin:加权轮询,每个backend都有它的权重
random:随机
dns:基于DNS解析之后进行调度

2、使用varnish自动清理缓存

使用pruge
 修剪缓存,能够让用户清理所指定的某个特定缓存对象,如果要移除多个缓存对象,对缓存某些内容基于正则方式进行清理的话,可以进行banning这种机制
Banning
通常可以移除指定的缓存对象或者进行匹配某些对象进行处理。

Varnish的缓存策略偏向保守型的(可以通过配置修改),默认缓存get请求和Head请求,不会缓存cookie和认证信息的请求,也不会缓存带有Set-cookie和有变化的头信息的响应。

Varnish会检查和请求响应中的Cache-control头信息,头信息中的一些选项控制缓存行为,当头信息有max-age=n,varnish以此n设置缓存时间,否则,取缓存默认时间default_ttl:120s。

Varnish子程序

vcl_recv:
    接收到客户端请求后执行。返回结果有:
	    pass:直接去后端服务器请求资源,从后端拿到的数据不会被缓存;
	    pipe:直接去后端服务器请求资源,也不会被缓存,并且处理的请求不会被记录日志;
	    hash:进行hash计算检查缓存;
	    purge:在缓存中查找缓存对象并清除;
	    synth:合成http响应报文,通常是错误报文;

vcl_pass:
    当一个subroutine执行return pass时,跳转到vcl_pass处理,把请求设置为pass模式,返回以下结果:
    fetch:不会被缓存,直接响应给客户端;
    synth:进入vcl_synth合成响应报文;
    restart:从vcl_recv重新开始;

vcl_miss:
    根据缓存命中情况来执行
    fetch:获取服务器响应结果,缓存到本地;
    pass:从后端获取到响应,但本地不缓存;

vcl_hit:
    缓存命中执行。
    deliver:直接将缓存结果返回给客户端;
    pass:丢弃缓存,重新从后端获取数据;

vcl_fetch:
    从后端服务器获取数据之后执行,通过beresp对象访问响应的数据。
    deliver:将数据返回给客户端;
    restart:重新开始这个请求;

vcl_deliver:
	将响应结果返回给客户端,结束请求。

在这里插入图片描述

Varnish配置文件

# 1.定义一个健康监测

vcl 4.0;        #指定版本
import directors;       #加载后端的轮询模块
probe backend_healthcheck {     #设置名为backend_healthcheck的健康监测
    .url = "/index.html";
    .window = 5;      #窗口
    .threshold = 2;   #门槛
    .interval = 3s;
    .timeout  = 1s;
}

# 后端服务器
backend web1 {
    .host = "127.0.0.1";
    .port = "80";
    .probe = backend_healthcheck;
}
backend web2 {
    .host = "127.0.0.1";
    .port = "80";        
    .probe = backend_healthcheck;
}

# 设置后端集群事件

sub vcl_init {
    new img_cluster = directors.round_robin();
    img_cluster.add_backend(web1);
    img_cluster.add_backend(web2);
}
 
acl purgers {    # 定义可访问来源IP,权限控制
        "127.0.0.1";
        "172.17.0.0"/16;
}

# 定义引擎
sub vcl_recv {
    if (req.method == "GET" && req.http.cookie) {
        return(hash);    //处理完recv 引擎,给下一个hash引擎处理
    }
    if (req.method != "GET" &&
        req.method != "HEAD" &&
        req.method != "PUT" &&
        req.method != "POST" &&
        req.method != "TRACE" &&
        req.method != "OPTIONS" &&
        req.method != "PURGE" &&
        req.method != "DELETE") {
            return (pipe);   //除了上边的请求头部,通过通道直接扔后端的pass
    }

# 定义index.php不经过缓存 直接后端请求 
    if (req.url ~ "index.php") {
        return(pass);
    }
# 定义删除缓存的方法
    if (req.method == "PURGE") {   //PURGE请求的处理的头部,清缓存
        if (client.ip ~ purgers) {
          return(purge);
        }
    }
# 为发往后端主机的请求添加X-Forward-For首部
    if (req.http.X-Forward-For) {   
        set req.http.X-Forward-For = req.http.X-Forward-For + "," + client.ip;
    } else {
        set req.http.X-Forward-For = client.ip;
    }
        return(hash);
}

# 定义vcl_hash
sub vcl_hash {
     hash_data(req.url);
}

# 自定义缓存文件的缓存时长,即TTL值
sub vcl_backend_response {    
    if (bereq.url ~ "\.(jpg|jpeg|gif|png)$") {
        set beresp.ttl = 30d;
    }
    if (bereq.url ~ "\.(html|css|js)$") {
        set beresp.ttl = 7d;
    }
    if (beresp.http.Set-Cookie) { //定义带Set-Cookie首部的后端响应不缓存,直接返回给客户端
    set beresp.grace = 30m;  
        return(deliver);
    }
}
 
# 定义vcl_deliver
sub vcl_deliver {
    if (obj.hits > 0) {    //为响应添加X-Cache首部,显示缓存是否命中
        set resp.http.X-Cache = "HIT from " + server.ip;
    } else {
        set resp.http.X-Cache = "MISS";
    }
        unset resp.http.X-Powered-By;   //取消显示php框架版本的header头
        unset resp.http.Via;   //取消显示varnish的header头
}


node-varnish的使用

npm install node-varnish

var Varnish = require('node-varnish');

var client = new Varnish.VarnishClient('127.0.0.1', MANAGEMENT_PORT[, secret]);
client.on('ready', function() {
    client.run_cmd('purge obj.http.X == test', function(){});
});

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值