Varnish 介绍
什么是 Varnish , 和通常的缓存加速工具有何不同,在 Varnish 文档中有如下描述:
1. Varnish is a reverse HTTP proxy, sometimes referred to as a HTTP accelerator or a web accelerator.
2. Varnish stores files or fragments of files in memory, allowing them to be served quickly.
3. Varnish is essentially a key/value store, that usually uses the URL as a key.
4. Varnish is designed for modern hardware, modern operating systems and modern work loads.
下面从 Varnish 的工作流程以及取数据流程两个方面对 Varnish 的总体工作机制进行介绍。
Varnish的工作流程
Varnish 主要有两个进程,下面是 Varnish 的基本进程结构
![v2-332c5d3ccd876fa3a481ea7508c96822_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/67170a3fe21757374953d57507053899.jpeg)
如上图示,Varnish 主要存在两个进程:manage 进程及 child 进程,其中:
- manage 进程:更新配置,vcl 文件编译,varnish 监控,初始化 varnish 及提供 varnish 管理接口。
- child 进程:主要进行请求任务的处理,接受请求等。
相当于 child 进程实际是提供 Varnish 主体功能的进程,线程结构如下图示:
![v2-cc350c39d5cd52628c04eb599082c67a_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/885ee1a6c19ab651863d22dba5e16771.jpeg)
child 进程中各线程的处理任务如下所示:
- accept 线程: 监听端口,接受连接;接受连接后组成 session 结构,查看是否有空闲线程,若有则分配给其处理,若无,则检查等待队列 overflow 的大小,若过大,则抛弃请求,否则加入 overflow 队列。
- work 线程: 从 overflow 队列中获取任务, 走 Varnish 状态机流程处理任务,完成后通过 pipe 的线程通信,传递给 epoll 线程,等待下一个事件触发。
- epoll 线程:将事件发送时对应的 session , 放入 overflow 队列,以供 work 线程从中取出继续处理。当然,在等待事件发送时,会检查该 session 是否过期。
- expire 线程:对以二叉树形式组织的缓存对象,进行过期检查,对过期的对象进行处理(更新或者弃用)。
Varnish 中主要是在 work 线程中完成对请求的处理,而处理请求的逻辑主要是依据 varnish vcl 配置文件来决定对不同的请求采取的处理方式。vcl 配置文件主机涉及 vcl 的状态转换相关的配置,下面主要讲 vcl 处理流程。
vcl 的处理流程
vcl 的处理流程,主要是由 Varnish 的状态机决定,可以通过 vcl 配置文件来对 varnish 状态机各个步骤所做的操作进行配置。
vcl 的状态机如下图示:
![v2-768e6756becc73afaebec94faafefeb5_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/ff5775f776bf9466c99f965d3fb86e63.jpeg)
上面的状态图,主要对 Varnish 处理 http 请求时各个步骤及决策方式进行了描述,下面对其中的各个状态进行介绍。
vcl_recv
vcl_recv 是 http 请求到达后进入的第一个状态,在这个状态中,可以对请求进行以下的一些处理:
1. 修改 client 请求,以减少缓存决策时的差异性。
2. 根据 client 请求,决定缓存策略。
3. 重定向请求
4. 决定处理请求的 backend(即后端 webserver )
在 vcl_recv 可以进入 vcl_pass, vcl_pipe,vcl_lookup,vcl_error.
vcl_pipe
若连接存活期间其请求被 vcl_recv 传递至 vcl_pipe ,那么这请求后的所有请求,将直接经 vcl_recv 到达 backend,Varnish 不再查找,及存储及请求的对象,就如同 client 与 backend 直接通信一样, 不会记录任何通信的日志。
vcl_pass
进入 vcl_pass 的请求,请求会直接发送至 backend , 但不会缓存, 可进入 restart , 会增加 restart 计数。
vcl_hash
根据请求的特征,构建 hash 值,通常是以 host+url 的形式建立 Hash 值,可进入 vcl_hit 及 vcl_miss .
vcl_hit
可进入 vcl_pass 及v cl_deliver,vcl_restart
vcl_miss
可进入 vcl_pass 及 vcl_fetch,vcl_restart
vcl_fetch
将请求传递至 backend, 决定是是否缓存,可进入 hit_for_pass: 仅vcl_fetch 可进入,与 pass 功能类似,不过其会利用 beresp 建立一个 hitforpass 对象,以防止同一对象被缓存,在 hitforpass 对象存在期间,同一请求的结果都不会被缓存,请求会直接进入 pass。
deliver:缓存取到的对象,并发送至服务端,也可进入 restart , 增加 restart 计数,当 restart 计数大于 max_restarts 时会报错。
vcl_deliver
在缓存数据将要发送到客户端时调用
vcl_error
出错时调用,以上的各状态通常情况下都可进入 vcl_error
对于以上状态的转换,具体的转换原因,也可如下图示:
![v2-d3796e53422a3fb144790d4fc5f4f365_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/374b86e1bcf8c873914d721fb8a33426.jpeg)
vcl中的变量
vcl 内置的公共变量可以用在不同的 vcl 函数中,下面根据使用的不同阶段进行介绍
表 1. 请求到达时可用公共变量
![v2-87a009e37294ae3ae9d7929044cecd56_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/5402d76f92e79d48e9ee894bca4fd8e1.jpeg)
表 2. 向后端主机请求时可用公共变量
![v2-2c26df9171325a49355ca45aa82619a0_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/155287cdefec7940236da8f4398bbe3f.jpeg)
表 3. 后端主机获取内容时可使用公共变量
![v2-d4411a0b6d51d16a4bee00c4b188856f_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/47ba66503682c80d6069fe1db4200377.jpeg)
表 4. 对客户端相应时可使用公共变量
![v2-9eabd2f128916bb4f5723cedc42b5501_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/27b3b87ff20cd480d7c6fc7d4d875bd4.jpeg)
本文作者:高志刚
文章看完啦,不如来官网看看?滴滴云3-5折活动聚惠来袭!
与其看教程,不如实际操作下?
滴滴云-为开发者而生