微服务架构 Varnish优化
Varnish优化
- 核心优化,通过VCL优化配置
- 通过硬件负载均衡到多台varnish分流
Varnish介绍
-
Varnish一款开源的、高性能HTTP加速器和反向代理服务器
-
Varnish主要通过缓存来实现web访问加速
-
Varnish主要基于内存进行缓存、支持精确缓存时效,性能高效
其 VCL配置管理比较灵活,支持后端服务器负载和健康检查,内部实现负载均衡轮询调用服务器 -
varnish主要由两个进程,管理进程和子进程
管理进程主要负责(配置变更、编译VCL、监控运行、初始化),定期检查子进程、子进程挂了会kill后重新开启。
子进程包括(worker线程、aceptor线程、expiry线程清除旧内容),使用workspace工作区来减少多个线程间对于内存的竞争
Varnish 安装
- 安装gcc
- 安装pcre 正规表达式
- 安装libedit-dev yum install libedit-dev*
https://www.varnish-cache.org/ 下载,解压源码,进入包根目录 (tar zxvf varnish-3.0.5.tar.gz),安装pcre后需要设置路径 cd varnish-3.0.5
export PKG_CONFIG_PATH=/usr/local/pcre/lib/pkgconfig
配置varnish属性文件到指定路径
./configure --prefix=/usr/common/varnish
编译/安装
make、make install
安装完后关掉防火墙
/sbin/service iptables stop
Varnish 启动
- 核心配置 default.vcl /etc/varnish目录
- cd /varnish/sbin/
- 运行./varnished -f /usr/common/varnish/etc/varnish/default.vcl -s malloc,32M -T 127.0.0.1:2000 -a 0.0.0.0:2222
-s malloc 存储类型和容量
-T 127.0.0.1:9000 指定管理ip和端口
-a 0.0.0.0:2222 对外界提供web服务的ip和端口
运行demo
http://192.168.0.102:2222/zachary/demo/showtime 通过varnish代理
http://192.168.0.102:9021/zachary/demo/showtime 直接访问tomcat
Varnish 关闭
- cd /varnish/sbin
- 运行pkill varnished
Varnish 结构图
核心配置default.vcl讲解
probe tz1{
.url="/demo/xxxx.index.html";//检查后端健康页面
.timeout=0.3s;//过期时间
.window=8;//检查后端服务次数
.threshod=3;// 检查后端8次访问,成功3次认为是存活的
.initial=3;//varnish启动,确保多少个probe正常
.expected_response=200; //期望expected code,默认是200
.interval=6;//定义probe多久检查一次后端,默认5s
}
backend zachary{
.host="127.0.0.1";
.port="2222";
.connect_timeout=1s;
.first_byte_timeout=5s;
.between_byte.timeout=2s;
.max_connections=1000;
.probe=tz1;
}
backend resource{
.host="127.0.0.1";
.port="8099";
.connect_timeout=1s;
.first_byte_timeout=5s;
.between_byte.timeout=2s;
}
director zachary random{ //随机
.retries=5;//查找可用后端次数
{
.backend=zachary;//引用已存在backend
.weight=6;
}
{
.backend=resource;//引用已存在backend
.weight=2; //类似nginx 权重
}
{
.backend={//定义新的backend
}
.weight=2;
}
}
director zachary round-robin{ //轮询
{
.backend=zachary;//引用已存在backend
}
{
.backend=resource;//引用已存在backend
}
{
.backend={//定义新的backend
}
}
}
#权限访问控制列表
acl purgeallow {
"127.0.0.1";
!"192.168.0.102"
}
sub vcl_recv{
if(!req.backend.healthy){
set req.grace=30m;//varnish缓存时间+50分钟返回给客户端
}else{
set req.grace=5s;
}
if(req.request== "PURGE"){
(!client.ip ~ purgeallow){
error 405 "not allowed";
}
return(lookup);
}
if(req.http.host ~ "^(www.)?zachary.cn$"){
set req.backnd=zachary1;
}
if(req.request== "GET" req.url ~ "\.(jpg|png|gif|swf|flv|ico|jpeg)$"){
unset req.http.cookie;
}
if(req.request== "GET" req.url ~ "(?i)\.jsp($|\?)"){
set req.backnd=resource;
return pass(pass);
}
}
sub vcl_fetch{
set beresp.grace=30m;//后端服务器返回varnish缓存时间+50分钟
if(req.request== "GET" req.url ~ "\.(jpg|png|gif|swf|flv|ico|jpeg)$"){
set beresp.ttl=1d;
}
if(req.url ~ "^.*/zachary/demo/.*"){
set beresp.ttl=1d;
return(deliver);
}
}
sub vcl_hit{
std.log("url hit,your need to check it; it's url ="+req.url);
if(req.request=='PURGE'){
set obj.ttl=0s;//清除缓存
error 200 "Purged.";
}
return(fetch);
}
sub vcl_miss{
std.log("url miss,your need to check it; it's url ="+req.url);
if(req.request=='PURGE'){
error 200 "Purged.";
}
return(fetch);
}
参数讲解
- backend 可以配置多个,1个请求对应1个backnd,里面配置连接后端服务,connect_timeout连接后端超时时间,first_byte_timeout传输第一个字节时间,between_byte.timeout第二个和第一个中间传输时间,max_connections连接后端服务最大限制数
- 可以单独配置多个backend,可以配置单个backend分发多个策略如(随机、循环、DNS参考 以上director配置)
- probe配置健康检查
- acl权限列表设置,可配置相关ip
- Grace模式
1.当多个客户端请求同时访问一个页面。varnish只会发送一次请求到达后端,其它请求会被挂起等待返回结果,体验不好
2.服务器请求流量高,比如秒杀、数千万点击率等。用户不可能挂起等待结果
3.针对以上问题,varnish提供了Grace模式延长缓存失效时间,上次过期数据结果在失效时间之后延期多长时间,时间需根据系统斟酌设置
当后端服务器出现问题,负载过高后,varnish不访问后端直接返回旧缓存数据给客户端; - VCL返回策略
return(pass)//不缓存,直接调用服务器
return(lookup)//先从缓存获取,没有数据再从服务器获取
return(pipe)当前连接未关闭前,所有的请求都直接请求服务器,varnish不处理
return(deliver)请求目标被缓存,然后返回给客户端
Varnish优化手段
- varnish默认缓存策略很保守,默认只缓存GET、head请求,不缓存带cookie和认证信息请求,可以更改配置调整
- 提搞varnish命中,可以仔细规划请求和应答,并自定义缓存策略,通过VCL缓存自己想缓存内容,并主动设置对象过期时间,尽量不依赖http header
- 查看日志varnishtop -i txurl,请求后端url,对比策略,让需要缓存url缓存,不需要缓存剔除
- backend 超时时间需要根据应用情况适当调整
- 通过日志辅助分析 varnish -I log,分析哪些希望命中却没有命中缓存连接
Varnish问题列表分析
- 1.Varnish需要缓存哪些内容?分析思考
- 2.Varnish缓存多少大小?分析思考
- 3.后端发生变化后,如何主动通知Varnish更新缓存?
- 4.Nginx和Varnish如何一起使用?
针对以上问题笔者分析结果
问题1
- 所有请求,按照应用模块一块块分析,静态资源和动态资源
- 动态资源可以缓存(一部分放到CDN,一部分可以缓存在varnish)
- 动态内容 大部分不会变动、少部分会变动,可以缓存部分内容
- 动态内容 有些业务实时需要处理数据,不能缓存的
问题2
- 应用热门数据有多大?
- 用户使用点击率最高 如 首页、连接出去相关页面 需要缓存,大小?
- 缓存对象分类,如图片、静态页面、数据集合,根据分类预估大小?
- 使用varnishstat监控工具,监控其内存使用情况?
- varnish每个对象额外开销是1k,如果缓存中有很多小对象,花销很大
问题3
- 如果是人工非程序更新内容,可以到varnish后台管理把相关url清除掉,下次会重新获取内容
curl -x PURGE http://localhost:8080/demo/query - 如果是程序自动更新服务端内容,方案如下
1.varnish提供PURGE清除缓存接口,程序方可以远程调用接口清除缓存
2.书写shell脚本,程序方调用shell脚本,传入需要清除url,shell脚本主动调用varnish的admin后台管理清除,程序和脚本需要自写
问题4
- nginx (动静)所有内容反向代理到varnish,varnish根据缓存策略,获取缓存或者反向代理到tomcat获取数据 返回客户端
- nginx存储静态资源,动态内容代理到varnish获取
笔者建议使用第二种,毕竟代理一次到varnish以及返回到nginx需要网络传输。
总结:
- 优先使用浏览器缓存,如浏览器未缓存到,考虑结合使用Nginx和Varnish,取长补短,高效设置缓存策略,使用varnish之前优先考虑以上问题,进行提前规划方案后再使用。笔者建议针对系统复杂情况综合考虑使用
作者简介:张程 技术研究
更多文章请关注微信公众号:zachary分解狮 (frankly0423)