######夜深了#######
#################
一、Varnish进程的工作模式
varnish启动会产生两个进程,root身份产生manger主(管理mangerment)进程,然后fork一个worker子进程(varnish身份)
manger进程作用:读入(更新)配置,vcl 文件编译,varnish监控,初始化 varnish 及提供 varnish 管理接口。 Management进程会每隔几秒钟探测一下Child进程以判断其是否正常运行,如果在指定的时长内未得到Child进程的回应,Management将会重启此Child进程。
child进程作用:主要接受请求,进行请求任务的处理,分配线程进行cache工作!
ps -ef 测试命令(也可以 ps -axjf 数形结构查看)
user PID PPID
root 2120 1 0 09:07 ? 00:00:00 /usr/sbin/varnishd -P /var/run/varnish.pid -f /etc/varnish/default.vcl -a :80 -T 127.0.0.1:6082 -S /et
varnish 2121 2120 0 09:07 ? 00:00:00 /usr/sbin/varnishd -P /var/run/varnish.pid -f /etc/varnish/default.vcl -a :80 -T 127.0.0.1:6082 -S /et
说明:从上面可以清晰的看到两个进程的关系!
补充1:management管理进程的启动文件(服务)
vim /usr/lib/systemd/system/varnish.service
补充2:cd /proc/pid/ 看此进程在内存中的状态等!
二、作用机理
(1)child进程主线程初始化过程中,将存储的大文件整个加载到内存中,如果该文件超出系统的虚拟内存,则会减少原来配置mmap大小,然后继续加载,这时候创建并初始化空闲存储结构体,放在存储管理的struct中,等待分配。
(2)接着varnish某个负责接受新http连接的accept线程开始等待用户,如果有新的http连接,但是这个线程只负责接收,然后唤醒等待线程池中的work线程,进行请求处理。
(3)worker线程读入uri后,将会查找(从缓存中查找还是直接从后台fetch取决于VCL设置)已有的object(缓存中lookup此对象),命中(hit)直接返回,没有命中(miss)则会从后端服务器中(backend)取(fetch)出来,放到缓存中。如果缓存已满(expire),会根据LRU算法,释放旧的object。对于释放缓存,有一个超时线程会检测缓存中所有object的生命周期,如果缓存过期(ttl),则删除、释放相应的存储内存。
三、child开启的多种类型的子线程
accept 线程:监听端口,接受请求;接受请求后组成 session 结构,查看是否有空闲线程,若有则分配给其处理,若无则检查等待队列 overflow 的大小,若过大,则抛弃请求,否则加入 overflow 队列。
work 线程: 从 overflow 队列中获取任务, 走Varnish状态机流程处理任务,完成后通过 pipe 的线程通信,传递给 epoll 线程,等待下一个事件触发。
Worker线程:处理请求,child子进程会为每一个用户请求(如果需要处理)启一个worker线程,所以它单线程、单响应的(即是每一个请求用一个独立的线程响应的)
epoll 线程:将事件发送时对应的session , 放入 overflow 队列,以供 work 线程从中取出继续处理。当然在等待事件发送时,会检查该 session 是否过期。
expire 线程:对以二叉树形式组织的缓存对象,进行过期检查,对过期的对象进行处理(更新或者弃用)
明确1:进程是由以用户身份开启的,虽然不一定是你主动开启的,因为一个进程的具有的权限与用户的身份息息相关!
明确2:worker进程中的开启的多个线程是处理用户请求的,换句话说是真正干活的!
注意:select、poll、epoll之间的区别、select的缺陷
四、一张图
补充:在执行 vcl 时,varnish 就把 VCL 转换成二进制代码,然后用C去编译,然后运行!
五、varnish的存储方式
三种存储方式
1、file:存储在磁盘空间,但是在varnish重启后会被清除;其通过mmap()系统调用将缓存文件映射到内存空间!
2、malloc:存储在内存空间,其通过malloc()库调用在varnish启动时申请置顶大小的内存空间(256M)用于存储缓存对象!
3、persistent:与file一样,但是可以永久存储缓存文件,测试中!
/etc/varnish/varnish.params: 配置varnish服务进程的工作特性(参数),例如监听的地址和端口,缓存机制;
VARNISH_STORAGE="malloc,256M" #核心
VARNISH_LISTEN_PORT=80 #处理http请求的tcp监听端口(默认是8081)
mmap:memory mapper -->内存映射
#################
六、VCL
(1)核心配置文件
/etc/varnish/default.vcl:配置各Child/Cache线程的缓存策略
常见:处理真实请求的后端server :转发
说明:接受请求的端口已经在参数配置文件中配置
(2)VCL模块的介绍
VCL:区域配置语言( varnish configuration language)
强调:VCL只是配置语言,并不是真正的编程语言,所以没有循环和自定义变量!
借鉴了Perl和C:perl中的子程序(sub)和正则,感兴趣的可以参考我的perl相关讲解!
在讲解VCL各个子模块之前的时候我们再来回顾一下上上章节所讲的流程图
随手附上一张官方的流程图
vcl的工作方式是基于状态引擎(state engine)来实现的
vcl_recv(开始)如果可以查询缓存并可以识别,那就要到vcl_hash这步了;如果无法识别那就通过pipe(管道)送给vcl_pipe;如果能识别,但不是一个可缓存的对象,那就通过pass送到vcl_pass去,vcl_hash之后就可查看缓存中有没有了,有这个请求的对象就表示命中 (vcl_hit),如果没有那就表示未命中(vcl_miss),如果命中的就可以直接通过deliver直接送给vcl_deliver响应了(给客户端),如果未命中就通过fetch交给vcl_fatch去后端服务器上去取数据,取回数据之后如果数据可以缓存就缓存(cache),本地缓存完之后再构建响应, 如果不可以缓存就不做缓存(缓存和缓存看配置文件的配置)交给vcl_deliver响应了;而如果命中了交给vcl_pass,交给pass之后就要到Fetch objet from backend后端服务器上去取数据了,这是因为这个命中的对象可能是过期或者是要做单独立额外的处理的!
补充
VCL用于让管理员定义缓存策略,而定义好的策略将由varnish的management进程分析、转换成代码、编译成二进制程序并连接至child进程。varnish内部有几个所谓的状态(state),在这些状态上可以附加通过VCL定义的策略以完成相应的缓存处理机制,因此VCL也经常被称作“域专用”语言或状态引擎,“域专用”指的是有些数据仅出现于特定的状态中。
(3)VCL各个子程序的介绍
讲解顺序:以请求响应的角度来理解VCL的各个内置模块的功能!
1)预定义(后续补充)
2)vcl_recv模块
作用:是第一道关卡,用于接收用户请求,当成功接收用户请求后被调用,通过某种动作来决定如何处理请求。
通俗理解:通过动作(静态配置),控制行为(运行)!
应用场景:后台服务器的调度,缓存的处理!
return 的动作
(1)pass:表示请求不在本地缓存中查找,直接进入pass模式,并将处理请求控制权交给vcl_pass函数
(2)pipe:表示请求不在本地缓存中查找,且进入pipe模式,并将请求控制权交给vcl_pipe函数
说明:此模式下不会对客户端做任何的检查或操作,而是在客户端和后端服务器"直接建立"管道,并将数据直接在这个管道中传输-->
此时,keep-alive连接中后续的数据也会通过管道进行传输,并且不会出现在任何日志中!
(3)error code [reason]:表示把错误标识返回给客户端,并放弃处理该请求。错误标识包括200、405等,"reason"是对错误的提示信息
(4)lookup:表示在缓存中查找请求的对象(默认),并根据查找的结果将请求控制权交给vcl_hit或vcl_miss函数
说明:如果查找不到,则默认调用pass函数从后端服务器调用数据
3)vcl_pass模块
特点:即表示此模块表示当请求被pass后,用于将请求直接传递至后端应用服务器(不从缓存中查找),后端应用服务器在接收请求后将数据发送给客户端,但不进行任何数据的缓存,在当前连接下每次都返回最新的内容。
说明:只是当前的请求!
pass:传递
return执行动作
(1)error code reason:返回错误代码并丢弃该请求
(2)pass:表示从后端服务器获取数据,并将请求控制权交给vcl_fetch函数(默认)
(3)restart:重启整个vcl,并且该请求重新进行检查
即该请求重新接受vcl_recv函数的检查。执行restart动作后,会计算重启计数,当超过max_restarts最大重启计数会返回错误信息!
4)pipe函数
特点:在进入pipe模式时该函数被调用,用于将客户端请求直接传递给后端服务器,在请求和返回的内容没有改变的情况下,将不变的内容直接返回给客户端,直到这个连接关闭。
执行动作:error code reason:返回错误代码并丢弃该请求
5)vcl_hit函数
特点:该函数在执行lookup命令后,如果在缓存中找到请求数据,则自动调用该函数。
return动作
(1)deliver:表示从缓存中找到的数据返回给客户端,并将控制权交给vcl_deliver函数(默认)
(2)pass:进入pass模式,并将控制权交给vcl_fetch
说明:这种模式下,虽然在缓存中找到了数据,但是不使用缓存中的数据,而是从后端服务器获取
(3)error code reason:返回错误代码并丢弃该请求
(4)restart:重启整个vcl,并且该请求重新接受vcl_recv函数的检查
说明:执行restart动作后,会计算重启计数,当超过max_restart最大计数器后会返回错误信息
6)vcl_miss函数
特点:该函数在执行lookup命令后,如果在缓存中没有找到请求数据,则自动调用该函数
执行动作
(1)Fetch:表示从后端服务器获取请求数据,并叫控制权交给vcl_fetch
(2)Pass::进入pass模式,并将控制权交给vcl_pass
(3)Error code reason:表示返回错误代码和信息并丢弃该请求
(4)Restart:重启整个vcl,并且该请求重新接受vcl_recv函数的检查
说明:执行restart动作后,会计算重启计数,当超过max_restart最大计数器后将返回错误信息。
7)vcl_fetch函数
说明:当想从后端服务器获取数据或更新缓存时该函数被调用,并且根据某种动作来判断获取的数据是否被缓存,还是直接返回给客户端
动作
(1)deliver:表示从后端服务器获取到的资源或数据进行缓存。并将控制权交给vcl_deliver函数。
(2)hit_for_pass:表示从后端服务器获取到的数据或资源不进行缓存,且将控制权交给vcl_deliver函数-->
并且后续对该对象的请求直接交给vcl_pass函数。
(3)error code reason:表示返回错误代码和信息并丢弃该请求。
(4)restart:重启整个vcl,并且该请求重新接受vcl_recv函数的检查-->
执行restart动作后,会计算重启计数,当超过max_restart最大计数器后将返回错误信息
8)vcl_deliver函数
特点:将请求的数据返回给客户端调用此函数。
执行动作:error code reason
强调:varnish只是一个加速器,不具有HTTP服务器的特性!
VCL配置文件的执行
(1)文件被分为多个子程序,不同的子程序在不同的时间里执行;
比如:一个子程序在接到请求时执行,另一个子程序在接收到后端服务器传送的文件时执行,子程序只有在调用的时候才执行,并且当执行完成后就退出。
(2)如果到最后您也没有调用您的子进程中的功能,varnish 将执行一些内建的 VCL 代码,这些代码就是 default.vcl 中被注释的代码。
#####################################
七、中场休息
明确:各个模块的功能(在请求响应的过程中的阶段)!
何时需要return?以及return的含义!
感想
了解:服务器软件所依赖的语言(top排行榜的前20语言都有必要学习一下)!
Ruby、Perl、PHP、Python--->了解基本语法(不一定要深入掌握)。保证可以看懂就可以,在需求的过程中学习!
三、思考
问题1:使用 varnish 后,web应用程序是否加速?
分析:varnish只是一个策略,跟硬件配置有关,除此之外,如果您的程序的每个会话都使用 cookies 或者您每个程序都需要三次握手认证,这样 varnish 就不能缓存更多的数据!
问题2:高速缓存的原因
Varnish的核心功能是能能将后端web服务器返回的结果缓存起来,如果发现后续有相同的请求,Varnish将不会将这个请求转发到web服务器,而是返回缓存中的结果。这将有效的降低web服务器的负载,提升响应速度,并且每秒可以响应更多的请求。Varnish速度很快的另一个主要原因是其缓存全部都是放在内存里的,这比放在磁盘上要快的多。诸如此类的优化措施使得Varnish的相应速度超乎想象。但考虑到实际的系统中内存一般是有限的,所以需要手工配置一下缓存的空间限额,同时避免缓存重复的内容。
varnish是工作在用户层(应用层-->HTTP协议所在的层)
理解:varnish是一个媒介,感觉可以起一个防火墙的功能(可以过滤),阻挡攻击!