当前位置: 首页 > 编程日记 > 正文

深入探讨Varnish缓存命中率

也许你还在为刚才动态内容获得7336.76 reqs/s的吞吐率感到振奋,等等,理想和现实是有差距的,你要忍受现实的残酷,别忘了,我们压力测试中的动态内容都处于全缓存情况下,也就是每次请求都命中缓存,这在现实中往往是不可能的。
首先,缓存区空间大小是有限的,而我们的站点可能有大量的内容需要被缓存,而不像前边压力测试时只有一个内容。一旦缓存区被装满,那么缓存管理器便会淘汰一些它认为不再需要的缓存内容,比如通过LRU(最近最少使用算法)将使用频率较低的缓存内容淘汰出去,但是,这里判断“不常使用”的标准是不严格的,也许被淘汰的内容就是你将要访问的下一个内容,这便影响了它的命中率。
其次,缓存的过期时间也影响到它的命中率,假如有效期很短,为10秒,那么最少10秒便会有一次无法命中。
还有,有些内容可能根本没有被代理服务器缓存,比如这些内容包含了set-cookie等不可缓存的HTTP头信息,导致反向代理不会缓存它们,并且在浏览器请求它们的时候也不会去缓存区查找。这是影响命中率的一个重要因素,但往往被我们所忽略。
幸运的是,这些问题我们都可以轻松的解决,前提是,我们需要了解反向代理缓存的实时工作状态,比如Varnish便提供了一个命令行的状态监控程序varnishstat,我们打开它,便看到了当前时刻的状态,如下:

client_conn           9908723        94.05 Client connections accepted
client_drop                 0         0.00 Connection dropped, no sess/wrk
client_req           16433490       155.99 Client requests received
cache_hit             8751732        83.07 Cache hits
cache_hitpass           42592         0.40 Cache hits for pass
cache_miss            7573389        71.89 Cache misses
backend_conn          3889845        36.92 Backend conn. success
backend_unhealthy          220         0.00 Backend conn. not attempted
backend_busy                0         0.00 Backend conn. too many
backend_fail             4536         0.04 Backend conn. failures
backend_reuse         3780212        35.88 Backend conn. reuses
backend_toolate       3866687        36.70 Backend conn. was closed
backend_recycle       7646677        72.58 Backend conn. recycles
backend_unused              0         0.00 Backend conn. unused
fetch_head                 57         0.00 Fetch head
fetch_length           155097         1.47 Fetch with Length
fetch_chunked         7508522        71.27 Fetch chunked
fetch_eof                   0         0.00 Fetch EOF
fetch_bad                   0         0.00 Fetch had bad headers
fetch_close              3982         0.04 Fetch wanted close
fetch_oldhttp               0         0.00 Fetch pre HTTP/1.1 closed
fetch_zero                  0         0.00 Fetch zero len
fetch_failed                0         0.00 Fetch failed
n_sess_mem               1033          .   N struct sess_mem
n_sess                    633          .   N struct sess
n_object              1016443          .   N struct object
n_vampireobject             0          .   N unresurrected objects
n_objectcore          1017564          .   N struct objectcore
n_objecthead           982903          .   N struct objecthead
n_smf                 2647421          .   N struct smf
n_smf_frag             622470          .   N small free smf
n_smf_large                 3          .   N large free smf
n_vbe_conn                 12          .   N struct vbe_conn
n_wrk                    8000          .   N worker threads
n_wrk_create             8000         0.08 N worker threads created
n_wrk_failed                0         0.00 N worker threads not created
n_wrk_max               11021         0.10 N worker threads limited
n_wrk_queue                 0         0.00 N queued work requests
n_wrk_overflow           2441         0.02 N overflowed work requests
n_wrk_drop                  0         0.00 N dropped work requests
n_backend                   4          .   N backends
n_expired             6344546          .   N expired objects
n_lru_nuked            183957          .   N LRU nuked objects
n_lru_saved                 0          .   N LRU saved objects
n_lru_moved           3692170          .   N LRU moved objects
n_deathrow                  0          .   N objects on deathrow
losthdr                    84         0.00 HTTP header overflows
n_objsendfile               0         0.00 Objects sent with sendfile
n_objwrite           15466812       146.81 Objects sent with write
n_objoverflow               0         0.00 Objects overflowing workspace
s_sess                9906155        94.03 Total Sessions
s_req                16433490       155.99 Total Requests
s_pipe                     37         0.00 Total pipe
s_pass                 108252         1.03 Total pass
s_fetch               7667658        72.78 Total fetch
s_hdrbytes         7187255662     68221.35 Total header bytes
s_bodybytes      111592032839   1059230.32 Total body bytes
sess_closed           1905544        18.09 Session Closed
sess_pipeline               0         0.00 Session Pipeline
sess_readahead              0         0.00 Session Read Ahead
sess_linger          15277717       145.02 Session Linger
sess_herd            13547370       128.59 Session herd
shm_records        1028855796      9765.89 SHM records
shm_writes           77957008       739.97 SHM writes
shm_flushes            131005         1.24 SHM flushes due to overflow
shm_cont               144281         1.37 SHM MTX contention
shm_cycles                427         0.00 SHM cycles through buffer
sm_nreq              15306717       145.29 allocator requests
sm_nobj               2024948          .   outstanding allocations
sm_balloc         13595295744          .   bytes allocated
sm_bfree          40091795456          .   bytes free
sma_nreq                    0         0.00 SMA allocator requests
sma_nobj                    0          .   SMA outstanding allocations
sma_nbytes                  0          .   SMA outstanding bytes
sma_balloc                  0          .   SMA bytes allocated
sma_bfree                   0          .   SMA bytes free
sms_nreq                14062         0.13 SMS allocator requests
sms_nobj                    0          .   SMS outstanding allocations
sms_nbytes                487          .   SMS outstanding bytes
sms_balloc            6844837          .   SMS bytes allocated
sms_bfree             6846298          .   SMS bytes freed
backend_req           7668789        72.79 Backend requests made
n_vcl                       1         0.00 N vcl total
n_vcl_avail                 1         0.00 N vcl available
n_vcl_discard               0         0.00 N vcl discarded
n_purge                740577          .   N total active purges
n_purge_add            905392         8.59 N new purges added
n_purge_retire         164815         1.56 N old purges deleted
n_purge_obj_test     13397373       127.17 N objects tested
n_purge_re_test  131875330367   1251759.15 N regexps tested against
n_purge_dups           240655         2.28 N duplicate purges removed
hcb_nolock                  0         0.00 HCB Lookups without lock
hcb_lock                    0         0.00 HCB Lookups with lock
hcb_insert                  0         0.00 HCB Inserts
esi_parse                   0         0.00 Objects ESI parsed (unlock)
esi_errors                  0         0.00 ESI parse errors (unlock)
accept_fail              2553         0.02 Accept failures
client_drop_late            0         0.00 Connection dropped late
uptime                 105352         1.00 Client uptime


看起来很强大,的确,它帮我们获得了很多重要的信息,包括了三个重要的统计项:

N struct object

当前被cache的条目

Client requests received

代表到目前为止,浏览器向反向代理服务器发送的HTTP请求累积次数,由于可能使用长连接,所以它可能会大于上边的Client connections accepted。

Cache hits

代表在这些请求中,反向代理服务器在缓存区中查找并且命中缓存的次数。

Cache misses

代表在这些请求中,反向代理服务器在缓存区中查找但是没有命中缓存的次数。

N expired objects

代表过期的缓存内容个数

N LRU nuked objects

由于cache空间满而不得不扔掉的cache条目,如果这个数字是0,就没必要增加cache的大小了。

N LRU moved objects

代表被淘汰的缓存内容个数

Total header bytes

代表缓存区中所有缓存内容的HTTP头信息长度

Total body bytes

代表缓存区中所有缓存内容的正文长度
通过以上这些统计项,我们还可以知道更多,比如Cache hits和Cache misses的总和代表了反向代理服务器在缓存区中查找内容的总次数;而用Client requests received减去这个总次数,便大概等于没有查找缓存的请求数;Total body bytes和Total body bytes的总和则代表了缓存区当前的空间使用量。
了解了这些后,我们回头看前边的三个问题,都很容易分析和解决。
对于缓存区空间大小的问题,我们可以通过监视它的使用量以及缓存淘汰个数,在必要的时候分配更多的缓存区空间,但是这可能需要重新启动反向代理服务器。当然,我们应该首先根据站点的规模,来估算出大概的缓存区空间,并且分配出大约为它5倍以上的缓存区空间,以适应一段时期内的内容数量增长。
其次,是缓存有效期取值的问题,但这本身不是一个问题,它取决于后端Web服务器的承受能力,以及你对站点内容实时性的要求,我们在前边介绍动态内容缓存的章节中曾经探讨过缓存有效期的取值,实质上是一个寻找“过”与“不及”之间平衡的长期过程,但在动态程序实现的内容缓存机制中,我们还可以通过主动删除缓存的方法来实现缓存到期之前的更新,而基于HTTP协议的反向代理缓存机制则不容易做到这一点,后端的动态程序无法主动删除某个缓存内容,除非我们清空反向代理服务器上的缓存区。
在寻找平衡的过程中,有时候实时性需求可能要向缓存有效期适当让步,当我们的站点面临较大的压力时,我们不得不暂时以牺牲实时性作为代价,适当的延长缓存有效期,直到我们有了成熟的性能扩展方案。
在初步评估缓存有效期的时候,我们可以通过一些量化的计算来得出理论数值,举个例子,假如我们的站点有60000个动态内容处于频繁访问的状态,我们通过Cache-Control将它们在反向代理服务器上的缓存有效期都设置为60秒,这样一样来,后端服务器将必须承受最多每秒处理1000个动态内容的工作量,如果这些动态内容都进行完整的计算,比如访问数据库,那么显然后端服务器是无法承受的,这时候我们可以将缓存有效期延长到300秒,即5分钟,这使得后端服务器只需要每秒处理200个动态内容,大大减少了工作量。
那么,如果从缓存命中率的角度来分析缓存有效期取值的时候,有一点需要明白,当我们看到缓存的命中率非常低时,有时并不代表我们需要马上延长缓存有效期,这时候还要观察当前的站点实际吞吐率,举个极端的例子,假如你发现你的站点1个小时内只有1次访问,而缓存有效期为半个小时,那缓存命中率必然会非常低,但即便是每次缓存都不命中,也不会对后端带来什么压力,实际上如果你的站点只有一台Web服务器,并且站点的实际吞吐率远远低于它的处理能力时,完全没有必要使用反向代理服务器。
最后关于内容没有被缓存的问题,我们也可以在Varnish的状态监视中找到线索,比如有一个用Varnish加速第三方应用wordpress的例子,得到的Varnish状态如下:

4+10:37:44
my.server.com
Hitrate ratio: 1 1 1
Hitrate avg: 0.0364 0.0364 0.0364
2324 0.00 0.01 Client connections accepted
6191 0.00 0.02 Client requests received
12 0.00 0.00 Cache hits
7 0.00 0.00 Cache hits for pass
318 0.00 0.00 Cache misses
6179 0.00 0.02 Backend connections success
0 0.00 0.00 Backend connections not
attempted
0 0.00 0.00 Backend connections too many
0 0.00 0.00 Backend connections failures
4057 0.00 0.01 Backend connections reuses
6151 0.00 0.02 Backend connections recycles
...

我们看到,Varnish一共处理了来自浏览器的6191个请求,其中命中缓存的有12个,真是太少了,而没有命中缓存的有318个,奇怪,剩下的那么多请求根本就没有去缓存区检查,也就是说,Varnish认为那些内容不能被缓存。不能被缓存总是有原因的,你需要根据反向代理缓存的规则,来进一步的检查。而我们这个例子中,都是cookies惹得祸,因为在wordpress中由于我们会安装一些各种各样的插件,有些插件会使得wordpress的每个页面都带有写入cookies的set-cookie标记,而我们前边在vcl_fetch函数中禁止了这类内容的缓存,问题就在这里了,我们希望将这些多余的cookie关闭掉,但是,wordpress自身的登录和管理页面是需要cookies才可以正常工作的,所以我们还需要让反向代理不缓存这些页面,我们使用以下VCL配置:

sub vcl_recv
{
if (!(req.url ~ "wp-(login|admin)"))
{
unset req.http.cookie;
}
}
sub vcl_fetch
{
if (!(req.url ~ "wp-(login|admin)"))
{
unset obj.http.set-cookie;
}
}

可以看到,除了wordpress自身的登录和管理页面以外,我们将其它内容的HTTP头信息中有关cookie的标记全部都清除掉,这使得Varnish可以将大部分内容缓存起来,提高缓存命中率,同时不影响我们登录和管理wordpress。
这个例子给了我们一些启示,对于我们自己的站点,如果从长远考虑,那么在规划的时候就要费点心思,我们可以根据内容是否可以缓存在反向代理服务器上,将它们置于不同的主机,这样便可以在必要的时候将可以缓存的内容快速与反向代理服务器对接,获得较好的加速效果。

相关文章:

网易有道词典笔 —— 73 岁“人类高质量”奶奶梅耶马斯克的中文学习之选

继埃隆马斯克发微博称7000年后英语将不复存在后,他的忠实粉丝,同时也是他的母亲——梅耶马斯克也正式开启了学习新语言行动,值得注意的是,梅耶的语种选择是中文。近日,埃隆马斯克的母亲——梅耶马斯克使用有道词典笔学…

Android类库打包方法探究

为什么80%的码农都做不了架构师?>>> 开发Android应用的时候,对于可用于多个应用的公用的部分,或是打算发布给第三方进行应用集成的部分,要把这部分打包成类库怎么做呢? 众所周知,Android应用使用ADT打包成…

大叔也说并行和串行`性能提升N倍(N由操作系统位数和cpu核数决定)

并行是.net4.5主打的技术,同时被封装到了System.Threading.Tasks命名空间下,对外提供了静态类Parallel,我们可以直接使用它的静态方法,它可以并行一个委托数组,或者一个IEnumerable的迭代,而今天主要通过一…

这7个开源技术,支撑起整个互联网时代

转载自 钛媒体 - 这7个开源技术,支撑起整个互联网时代 开源软件现在成为整个互联网时代的支撑技术,你可能已经无法离开由开源软件构建起来的网络世界了。下面我们就来看看一些最重要的开源技术。 为互联网而生的操作系统linux Linux是一款免费的操作系统…

WebDriver 识别反爬虫的原理和破解方法~

作者|志斌来源|python笔记有时候我们在爬取动态网页的时候,会借助渲染工具来进行爬取,这个“借助”实际上就是通过使用相应的浏览器驱动(即WebDriver)向浏览器发出命令。但是有时候使用浏览器驱动来爬取网页时,会遇到这种情况这时&#xff0c…

Linux下文件如果没有权限不能被Apache访问

通过 apache的网站 php和图片都可以显示 就是 Htm页面不行 报错 Forbidden You dont have permission to access /me/1.html on this server. 其实是权限设置问题 可以 到文件所在目录 使用命令查看权限 #ls -al 再使用chmod命令给予足够权限即可 #chmod 0644 文件名…

html标签的显示模式(块级标签,行内标签,行内块标签)(转)

html标签的显示模式(块级标签,行内标签,行内块标签) 今天讲课的时候,讲到了html中的标签的显示模式,大致分为块级标签和行内标签。那么初学者在刚使用标签的时候会发现有些属性在一些标签上不起作用&#x…

RT-thread内核之进程间通信

一、进程间通信机制 rt-thread操作系统的IPC(Inter-Process Communication,进程间同步与通信)包含有中断锁、调度器锁、信号量、互斥锁、事件、邮箱、消息队列。其中前5个主要表现为线程间同步,邮箱与消息队列表现为线程间通信。本…

Linux内核学习四库全书

关于内核学习我建议不要上来就读内核而是先了解内核的构成和特性,然后通过思考发现疑问这时再去读内核源码。即先了解概貌在读局部细节。而且内核分成好多部分,不要只是按照顺序去读,应该针对某一部分比如内存管理或进程管理横向读几本书&…

46W 奖金池等你来战!微众银行第三届金融科技高校技术大赛火热报名中!

青春是什么?张爱玲曾说过,青春是个奇形怪状的玩意儿,短短的身子偏偏拖了一个长长的尾巴,像翅膀一样的招摇着,久久不肯离去。对于你我而言,青春是什么?青春也许是大学里点点滴滴的记忆&#xff1…

spring cloud快速搭建

为什么80%的码农都做不了架构师&#xff1f;>>> 一&#xff1a;注册中心 服务提供者&#xff08;简单&#xff09; 注册中心本身就可以是服务提供者&#xff0c;如果有需求可以分开。 1&#xff1a;pom.xml <?xml version"1.0" encoding"UTF-8…

ubuntu操作系统下载

原文网址&#xff1a;http://www.cyberciti.biz/linux-news/download-ubuntu-14-4-cd-dvd-iso-images/ Download of the day: Ubuntu Linux 14.04 LTS CD / DVD ISO by NIXCRAFT on APRIL 17, 2014 5 COMMENTS LAST UPDATED APRIL 17, 2014 in LINUX NEWS, OPEN SOURCE Ubuntu…

Linux内核模块编程入门

针对2.6内核的Linux系统&#xff0c;需要你的机器上已经安装了kernel-devel这个包&#xff0c;也就是编译模块所必须的东西&#xff1a;内核的头文件和一些Makefile。 一&#xff0c;Hello World程序&#xff1a; [code:1:fbc83fc10a]/*file: hello.c*/ #ifndef __KERNEL__ #…

2021中国国际消费电子博览会和青岛国际软件融合创新博览会盛大开幕

9月24日&#xff0c;备受瞩目的2021中国国际消费电子博览会(简称“电博会”)和青岛国际软件融合创新博览会(简称“软博会”)在青岛国际会展中心盛大开幕。国家工信部原副部长杨学山&#xff0c;国家工信部信息技术发展司副司长江明涛&#xff0c;中国机电产品进出口商会秘书长郭…

oracle 11g wm_concat 、 listagg 函数的使用(合并数据)

方法一 wn_concat() 函数 1、把以下图中Name一样的数据合并为一条&#xff0c;而且NO的值要这样显示如 C.1,C.2 2、实现这种效果的操作如下&#xff0c;先把Name的值进行分组&#xff08;group by&#xff09;&#xff0c;再把NO的值用 wm_concat()函数合并起来&#xff08;注意…

使用Cacti监控你的网络Cacti的安装

声明&#xff1a;本系列文档出自石头记&#xff0c;如若转载请注明出处&#xff0c;本人保留文档的所有权&#xff0c;并欢迎转载。本系列文档的其他部分链接如下&#xff1a;一、概述及Cacti的工作流程二、Cacti的安装三、Cacti的使用四、Cacti脚本及模板五、Cacti插件六、Cac…

AI 被当做炒作工具?

编译 | 禾木木 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 上班路上由于高峰期&#xff0c;眼看就要迟到了&#xff0c;这个时候会想“如果汽车能自动完成这种高度重复的动作&#xff0c;我就可以在路上参加我的会议了”。但是你必须每几秒踩一次油门&#xff0…

毕业五年后差距

毕业五年后差距正如"打工皇帝"唐骏说&#xff1a;"我觉得有两种人不要跟别人争利益和价值回报。第一种人就是刚刚进入企业的人&#xff0c;头5年千万不要说你能不能多给我一点儿工资&#xff0c;最重要的是能在企业里学到什么&#xff0c;对发展是不是有利……&…

我的新技术博客

我是一个技术小白&#xff0c;我开启一片新的空间转载于:https://blog.51cto.com/13526168/2048988

Varnish使用小结

文章原始出处和作者信息及 本声明http://iyubo.blogbus.com/logs/35085709.html此日志会随时更新&#xff0c;当然&#xff0c;是随着我的应用积累:) 实现静态文件压缩 Varnish itself does not compress or decompress objects, although that has been on our wish list fo…

EF 通用数据层类

EF 通用数据层父类方法小结 转载&#xff1a;http://www.cnblogs.com/yq-Hua/p/4165344.html MSSql 数据库 数据层 父类 增删改查&#xff1a; using System; using System.Collections.Generic; using System.Data; using System.Data.Entity; using System.Data.Entity.Infra…

最新的B站弹幕和评论爬虫,你们要的冰冰来啦!

作者 | 周萝卜 来源 | 萝卜大杂烩 最近想爬下B站的弹幕和评论&#xff0c;发现网上找到的教程基本都失效了&#xff0c;毕竟爬虫和反爬是属于魔高一尺、道高一丈的双方&#xff0c;程序员小哥哥们在网络的两端斗智斗勇&#xff0c;也是精彩纷呈。 当然了&#xff0c;对于爬虫…

K:java中的序列化与反序列化

Java序列化与反序列化是什么&#xff1f;为什么需要序列化与反序列化&#xff1f;如何实现Java序列化与反序列化&#xff1f;以下内容将围绕这些问题进行展开讨论。 Java序列化与反序列化 简单来说Java序列化是指把Java对象转换为字节序列的过程&#xff1b;而Java反序列化是指…

千万级并发HAproxy均衡负载系统介绍

Haproxy介绍及其定位 HAProxy提供高可用性、负载均衡以及基于TCP和HTTP应用的代理&#xff0c;支持虚拟主机&#xff0c;它是免费、快速并且可靠的一种解决方案。根据官方数据&#xff0c;其最高极限支持10G的并发。 HAProxy特别适用于那些负载特大的web站点&#xff0c; 这些…

中国的“Databricks”们:打造AI基础架构,我们是认真的

AI落地最大的驱动因素是基础架构的升级。 近年来&#xff0c;大数据分析、AI等领域一直备受关注&#xff0c;常有引人关注的融资事件发生。美国数据科学公司Databricks刚刚在今年8月底完成了16亿美元H轮融资&#xff0c;其最新估值高达380亿美元&#xff0c;相比7个月前G轮融资…

更改git bash默认的路径

在打开git bash时&#xff0c;每次都是在C:\Uer路径下&#xff0c;每次都需要先用cd命令转换到自己需要工作的路径&#xff08;cd /f/dss&#xff09;。修改打开git bash 时的默认的路径就可以不用每次都使用cd命令转换到需要管理的目录。 修改默认路径方法&#xff1a;右击Gi…

Gradle入门系列(4):创建二进制发布版本

本文由 伯乐在线 - JustinWu 翻译。未经许可&#xff0c;禁止转载&#xff01; 英文出处&#xff1a;petrikainulainen。欢迎加入翻译组。 在创建了一个实用的应用程序之后&#xff0c;我们可能想将其与他人分享。其中一种方式就是创建一个可以从网站上下载的二进制文件。 这篇…

什么是A记录、MX记录、CNAME记录

什么是A记录&#xff1f; A (Address) 记录是用来指定主机名&#xff08;或域名&#xff09;对应的IP地址记录。用户可以将该域名下的网站服务器指向到自己的web server上。同时也可以设置域名的子域名。通俗来说A记录就是服务器的IP,域名绑定A记录就是告诉DNS,当你输入域名的…

Graph + AI 2021中国峰会:TigerGraph与行业共探图与AI应用前景

由企业级可扩展图分析平台TigerGraph主办的第二届“Graph AI中国峰会”将于10月20日线上举办&#xff0c;本届主题为“图创未来无界精彩”。作为全球唯一一个专注于图技术的行业峰会&#xff0c;“Graph AI峰会”自开办以来&#xff0c;受到数据行业专家及应用领域伙伴的持续…

rrdtool数据备份与迁移

rrdtool 显示错误ERROR: This RRD was created on another architecture rrdtool数据备份与迁移1.在原服务器生成xml文件 …