**缓存是要分层的,一般在客户端浏览器上有缓存private cache私有缓存,在中间的代理服务器或者公共缓存上public cache,是可以公开给用户使用的(主要目的不是为了缓存用户的私有数据,这种缓存服务器可能有多级,
CDN一级,到自己站点内部有一级)真正到达原始服务器层级的时候,很有可能我们整个访问流量有百分之8090都被过滤掉了,都直接被前端的代理服务器所响应了
**
有一些动态内容也是可以被缓存的,需要缓存服务器的管理员去定义相关策略,定义得当,自己内部服务器的承载的压力是非常小的
http来进行缓存应用的时候,大致有两套逻辑
1过期时间判断机制 在HTTP1.0 用Expires 告诉客户端缓存在什么时候过期,绝对时间,基于expiress来控制在同一时区,用同一逻辑还好,但是只要在全球站点,就会出现问题
2.条件式请求
通过web服务器请求和响应中的报文首部来进行控制
在2.52.11之前都可以由本地浏览器直接返回给用户,但是绝对时间的格式有可能时区不兼容,而导致失效
为了应对这种情况,
在HTTP1.1协议中,由一个特定首部 cache control来控制 maxage最大生命周期(可以定义时间,如10s,不管时间,反正是10s的长度,因此对于绝对时间控制法就更加容易生效了)
s-maxage可以看做控制公共缓存当中的最大生命周期
既兼容1,0,又兼容1.1,86400一天的时间
过期时间控制逻辑,很死板,因为用户请求时,私有缓存已经缓存下来,只要没有过期,就能给用户直接响应,一旦过期,就只能请求上级,上级服务器也可能没有获取,就能被获取到,如果上级服务器也过期了,就只能到后端服务器RS
后端服务器即便数据没有变化,也会继续响应,B缓存,A缓存,最后到达离客户最近的缓存服务器,这是一种很低效的方法
但是1.0就是只有上面这种控制逻辑,
到 了1.1.以后,加入了条件式请求控制逻辑
(条件式请求,不急于时间来控制,意味着每一个客户端浏览器缓存下来以后都无法确定这个缓存到底有没有用,是否过期,就去找上一级缓存服务器,询问这个缓存的内容最近一次的时间戳是多少原始服务器,如果服务器端没有更新过,就响应给客户端304,意思是没变,可以使用,因此,客户端就从缓存服务加载给客户端使用了)
如果变了就用200响应码响应,更新一下自己的缓存到服务器响应的最新的数据
自己本地从缓存下载下来的缓存项的最近修改的时间戳信息,也可以认为自己加缓存的时间。获得缓存的时间
这是第一次请求,200
304 not modified这个时候就没有响应的具体过程
这就是第一种条件式请求,问题在于基于时间来控制,有可能时间变化的速度非常快,更新时间最小时间是秒钟,现在发出请求,到达服务器,服务器看到时间戳就到秒级,没变,就响应客户端没变,服务器端其实变了好几次了,这个时候就没法判断内容是否真的发生改变,精确度不精确
基于时间戳只是判断数据的修改时间,对里面数据没有关系,如果记录数据的校验码,这样就很精确了,每一次服务器端响应客户端时,直接向客户端告诉这个文件的校验码是什么,客户端也记录下来校验码,然后客户端再次做条件式请求的是,不论时间发生改变,只要校验码没有发生改变,就响应304,如果服务器说校验码发生变化了,就用200来响应
if none-match 你的校验码是否和我的匹配,匹配304,确实不匹配200
Etag 扩展标记,每个文件都有一个扩展标记,客户端发请求时,把自己的Etag请求给对方,而对方响应可以说,我的Etag发生改变,这个Etag照样可以完成控制
这两个都是做条件式验证,选哪个都可以
一种基于文件的修改时间戳来判别(精度不够),一种基于文件的校验码(可能更消耗资源)
能用第一种就不用第二种
下面的两个都用了
请求时告诉服务器Etag是多少而且latsmodified最近修改时间是xxx
哪一种判断不匹配都会返回200,
基于条件式请求也有一个缺陷,每次客户端虽然缓存能响应,但是还得去向服务器去请求判断,这个判断过程虽然不用发送响应报文包含body部分,但这个步骤是少不了的,
加入利用过期时间,就有可能会获取到过期内容,而且没过期的时候还依赖传输,那么该如何?
两者融合在一起使用,把过期时间判断机制和条件式请求合并起来一起使用,
客户端第一次请求,把数据缓存下来了
缓存下来的内容是有过期时间的,因此在过期之前都直接从本地缓存中返回,不会去找服务器,
如果过期,会询问服务器,已经过期,数据改变了没有,服务器表明没有改变,304响应,那缓存服务器又续了一个日期
所以接下来的请求没有过期都能直接访问,过期了,询问服务器,服务器返回200,缓存服务器只要更新就可以了
响应首部
Expires 过期时间
cache-control:maxage 过期时间(多少时间)
cache-control:s-maxage=
第二种是条件式请求
基于文件修改时间戳来判别,另外的是基于文件校验码来判别
这两种方式可以联合起来同时使用
如果想要强制刷新,请求中也可以加入cache -control,no -cache别用缓存响应我(请求报文也可以控制缓存该如何使用)
响应报文中也可以有cache-control
请求报文(告诉服务器如何来响应缓存)
no-cache 不用缓存响应
响应报文 (http1.1协议当中如何使用cache-control来控制响应报文来缓存结果,来响应请求)
public 可以被公共缓存所缓存
private 仅私有缓存做缓存
no-cache 不是不能缓存,而是后端响应请求者无论是浏览器还是反向代理服务器,告诉缓存系统,此内容可缓存,但是缓存下来后Expires是没有用的,意思就是缓存下来,在下次请求的时候,不能直接进行响应(意味着每一次客户端请求时,都需要做重新验证(询问服务器能不能用 revalidation 重新校验,更新了没有),条件式请求,不能结合expires一起使用)
no-store 才表示真正不能缓存,不能存储
must-realidate 跟 no-cache一样,必须重新校验
proxy-relidate 要代理服务器来做重新校验
squid依然宝刀未老,再较重负载下,性能依然出众
varnish很轻量,并发能力很OK,但是负载一旦超载,就性能不稳定了
对应varnish版本变化,配置变化的差别非常大,2。0到3。0你需要重新去学,3。0到4.0也需要重新学
主流现在应该是第4版,epel仓库提供
一般不用最新的,因为epel中的一般都是经过充分测试的
varnish是一个高性能的http服务加速器
红框内容是varnish核心组成内容,management类似nginx的master,child/cache对应worker进程
accept接收请求
logs/stats记录日志和统计数据的
worker threader 服务进程
storeage/hashing 管理存储以及管理存储缓存上的键
command line 命令行接口
backend communication与后端服务器通讯用
object expiry 关于缓存项过期时间的
整个varnish为了性能更好,整个工作的统计数据和工作的日志都没有记录到磁盘上,所有的日志信息都是记录在共享内存中的(shared object)大小大概86M,内存空间使用时是轮转式的,分开记录,记满了把之前覆盖掉,要想留住。就需要定期性的从磁盘上读出来存到磁盘中,如果有这个需要
varnishlog是记录原始格式
varnishncsa 转换成http的格式来记录
要运行守护进程,才能周期性地取记录,产生一条记录一条
varnish的工作程序就是来查看内存中记录的数据的
varnishtop 排序
varnishlist查看历史记录信息的
varnishstat统计数据
都需要跟共享区打交道
**varnish的配置文件有两种,
一种是配置varnish自己的工作特性比如定义worker threads定义最大并发数,定义进程自己的工作特性
2.作为缓存服务器来讲,需要配置缓存功能,哪些缓存,哪些不能缓存,是如何来定义的,这也需要配置文件
对于varnish缓存工作如何工作的配置文件是程序文件(说白了就是用一种编程语法来配置的,这一种编程语言叫VCL
varnish configure langueages,这种语言写的配置文件还不能直接使用,还得先编译,用VCL compiler工具,编译成c语言兼容的格式,再用c编译器来编译,再靠C compiler,c编译器来编译,转换成C代码,编译成一个共享对象,,供各种线程互相使用,作为库文件,给各线程链接加载使用的)
每一次配置文件发生改变,不是配置进程的,而是配置缓存系统的,都需要重新编译,装载去生效才行
所以要学习两种配置,一种是进程该如何配置,二缓存系统该如何配置
而能够去与managerment指挥着它去编译配置新的文件等等,需要一个命令行工具来实现CLI interface。命令行工具是varnishADM,这个工具连接时是需要验证的,(telnet interface不用,web interface 图形接口是需要收费的)
**
**计数器(某一个请求,请求多少次,命中多少次)‘
整个’varnish配置文件有两类
现在演示过程,找一台当varnish,内网网卡链接原始服务器,varnish既能反代也能调度,调度很简单,随即和轮循
**
先同步时间
把服务重启
n2作为内网服务器
配置内网地址
编辑web服务
启动服务
现在看varnish主机该如何配置
查看安装了哪些文件
varnish.params配置进程的(监听哪个地址端口之类的,用什么方式当缓存)
varnish.vcl是用来配置缓存策略的,对不同类的内容进行如何缓存,以及缓存多长时间
主程序/usr/sbin/varnishd
要想获取日志到文件,就需要把varnishlog或者varnishstat启动为守护进程
用内存缓存还是磁盘缓存
既然是缓存服务器,就要指明该如何缓存,而varnish有三种缓存机制
(nginx很简单,数据缓存在磁盘上分几组,原数据即哈希表在内存中)
而对varnish来讲,数据和元数据如何组织的无须关心,但是要知道它的数据能放在哪里有三种位置,
向varnishd传递参数时
-s 来指明用什么方式来进行缓存
-malloc 所有数据都缓存到内存中(varnish不能随意重启,一重启,所有缓存都将失效)
-file 文件缓存,就需要放到磁盘上,路径,大小(varnish是个黑盒,所有的缓存需要放到一个大文件中,二进制文件,不能随意打开看,虽然是文件,但是基于内存索引,一重启,索引没了,缓存也就没用 了)
-persistent 跟file很相似,基于文件来进行存储,黑盒,但重启以后缓存仍然有效,处于实验阶段,无法用
内存不停地的释放回收,会造成很多的碎片,久而久之会非常低效,导致内存空间大部分是非常有效的
内存在分配的时候,很容易产生缝隙,一旦过大,内存其实也不高效,所以建议大家用磁盘缓存而既然缓存性能这么关键,又要用磁盘缓存, 建议使用固态硬盘而且使用pxi-e接口的,高性能固态硬盘,如果用几块固态硬盘做raid是更好的
有一些高性能的固态硬盘IO是非常强悍的IOPS能达到十万,所以基本性能接近于内存了
一般SATA接口的IO一般也就每秒70.100MB
安装程序要的时候有一个jemalloc,malloc是C语言中内存分配的系统调用,内存用完好需要释放free
能够完成并发申请内存,所以基于内存做缓存时,jemalloc还是很重要的
varnish配置有两段,
1,配置进程的工作属性(最大并发数多少,有多少个子进程,配置的主要是传递给varnishd的配置选项,无非是监听地址和端口)
2。vcl,定义缓存策略的
运行时参数,比如修改varnish最大并发连接数多少,varnish是使用线程池来管理的,一个进程有500线程,最大并发就是1000个,这些都是运行时可以修改的,因为varnish服务重启就失效了,这些和配置相关的都可以运行时修改
每一项都用p来定义,如果定以后,不想允许人进行修改,-r设定参数为只读状态
传递运行时参数的
现在打开文件做下简单修改
创建缓存目录
尝试启动进程
访问地址
后端服务器出现了故障
后端服务器。需要在VCL中定义
后端服务器每一个都使用一个backend来定义
重新加载VCL
就成功了
对于varnish管理,应该都是使用命令行工具通过接口来的
-S指定秘钥文件,-T指定地址和端口,
交互式和直接敲命令,两种工作模式
help一下
ping判断服务器是否存活
获得banner信息
停止,启动,查看进程状态
查看,删除,编译,应用VCL
available可用
active 正在使用的,
查看一些配置文件有什么内容
表示装载并编译
切换使用
还有一些可调整的参数param
-l可用列出所有的
只看某一个
默认值2
列出所有的存储
列出后端主机
后端都还没进行健康性检测,需要自己去配置
可以设置后端服务器是否是健康
退出
也可以进行非交互式模式运行
最难理解的部分是VCL
iptables(input,output,forward,prerouting,postrouting)
作为缓存服务器收到请求以后是一样的逻辑
刚收到请求进行处理,有可能是拒绝的,收到请求以后先看这个请求能否查缓存(查缓存用查缓存的逻辑,如果没必要查缓存就用不查缓存的逻辑,如果查缓存,有命中不命中这一说法,查缓存如果命中了该如何去处理,要去后端服务器取,就需要把请求交给控制的上面
跟iptables控制类似,每一步都有自己的控制,所以配置文件只能生效在某一个生效的管卡上,关卡上的配置是专用的,因此我们叫域专有配置语言,c语言格式,
每个判断以后要制定下一关卡是谁(每个状态引擎后面应该有一个return指令,指明return以后下一跳是谁
每个sub定义,每一层都应该有自己相应的配置
虽然这里上面也没有,但是varnish内建的规则是直接生效的
-v显示详细信息
不论怎么修改这些内建配置都会立即生效,这个跟整个系统的安全密切相关
先看简单的2.0时代的版本
请求,收到请求,判断请求如果来自坏蛋ip就拒绝掉,
整个请求方法能否查缓存,如果能交给hash(查到缓存,如果命中了就是hit,没命中就是miss,然后去服务器取fetch
如果不能缓存,fetch(到后端服务器取了
收到请求以后,能查缓存的,看是否命中,hit命中,miss就是没命中,之后就是fetch取数据,取完以后就交给deliver客户端
就查缓存,不能查的就到后面去取
pipe,当请求不是http协议,就转为4层代理,直接转给管道什么也不处理了,pam决定给哪个服务器
4.0的是把前后端分开的
椭圆引擎,菱形判断机制