最近几天一直在看varnish,程序的风格和思路给我冲击不小,总结了一个文档,希望对varnish感兴趣的朋友有帮助。图示就不贴了,需要更详细信息的,请联系我,或code.google.com/p/ncache,参与讨论
Varnish浅析
Varnish介绍
1 Varnishis HTTP accelerator.
2Varnish stores data in virtual memoryand leaves the task of deciding what is stored in memory and whatgets paged out to disk to the operatingsystem
3 TheVarnish web site claims that Varnish is ten to twenty times fasterthan the popular Squid cache on thesame hardware.
4Varnish is heavily threaded
varnish 总体架构
2.1总体流程
主进程fork子进程,主进程等待子进程的信号,子进程退出后,主进程重新启动子进程
子进程生成若干线程。
Expire线程:对于缓存的对象,根据过期时间,组织成二叉堆,该线程周期检查该堆的根,处理过期的文件。
线程之间的关系:
2.1.1accept线程
监听端口,接受连接。
接受后
组织成struct ses(session结构),看是否有空闲的工作线程,如果有,将请求给它,pthread_cond_signal信号通知它
没有空闲线程,如果overflow过大,则放弃该请求。
否则,将其挂在overflow上(需要更多工作线程,发通知)。
继续监听
2.1.2work线程
从overflow队列上摘取请求(struct ses),进入状态机处理,处理结束后,通过pipe通信,将struct ses发送给epoll线程。
2.1.3Epoll线程,得到传过来的struct ses,若还没有过期,将socket放入epoll的事件中,事件发生时,也会将其放入到overflow中进行。
关于Expirethread,比较独立,下面专门介绍。
2.2work线程的处理过程
2.2.1请求的处理过程称为session,主要是由work线程处理的。
请求的是通过进入状态转换机进行分步处理,通过Varnish Configuration Language(VCL)进行定制。
request 进入状态机后的状态变化
对于每种状态,都可以通过VCL进行配置,丰富功能。
状态的基本转换如下图所示:
Work线程处理请求的过程是根据VCL的配置而定制的状态机,典型的处理流程如下
1.
2.
3.
4.
5.
6.
2.2.2Work线程总体工作如下:
接受到请求,按状态机处理,请求结束后,关闭连接或交给Epoll
重新取请求,若没有请求,挂入空闲队列,等待信号唤醒(pthread_cond)
唤醒它有两个途径,除了前面说的accept线程外,还有就是herdtimer线程
如果是accept唤醒的,则继续按照状态机的方式处理请求,如果是herdtimer唤醒的,则自杀
2.3 工作线程的管理
2.3.1 Herd线程
–根据配置生成指定数目的线程(min)
–动态检查线程数目,生成需要的线程
2.3.2 Herdtimer线程
定期检查空闲的线程,对于空闲超过指定时间的线程,通知它可以自杀
工作线程管理的目的是根据请求的数量动态的调整工作线程的数目
2.4 expire线程
对缓存的数据采用二叉堆的方式进行组织,线程检测堆的root,判断是否过期,对过期的数据进行删除或重取,由VCL设置。
对于过期的数据,如果需要重新取,则会调用状态机中的fetch去后台获取,然后更新
Cache 详解
3.1 Hash方式
3.1.1简单hash方式
–单一链表,按key大小排序,通过memcmp比较查找和添加
–缺点:查询效率低
3.1.2 Hash classic
–第一层hash backet(较大的素数)包含锁
–采用CRC32方法,key可配,一般是url + host
–通过链表解决冲突
–优点:查询较快
–值得参考的地方:采用查找和添加分两遍进行
3.2 Storage方式
3.2.1 Malloc
–通过malloc获取内存
–通过free释放
–
–特点:简单
–有什么不好呢?
3.2.2 Mmap file
创建大文件,通过二分法分段映射成1G以内的大块
数据的初始化
B分配,遍历数组,找到满足要求的空闲块,若是前B-2个没有,则从最后一个中满足要求的大块中切出一块。如果找出的块大于需要的容量,则就对其进行拆分,然后将剩下的插入到空闲块中。
C 回收,对于释放的块,看能否和相邻的块进行合并,如果可以,则合并后再重新插入到合适位置。
3.3数据输出
Object结构表示一个请求对象(文件),通过其store链表指出数据块信息
3.3.1采用writev
–将store链表上的数据组成iov,通过writev输出
3.3.2采用sendfile
–通过循环使用sendfile,将store链表中的数据输出
VCL配置
通过vcl脚本对程序进行定制,主要是对请求的定制处理,如过滤某些请求等,脚本配置生成的函数是嵌套在状态机中的。
默认的配置如下
http://varnish.projects.linpro.no/browser/trunk/varnish-cache/bin/varnishd/default.vcl
purge删除配置如下
http://varnish.projects.linpro.no/wiki/VCLExamplePurging
图 4-1 vcl与状态机的关系
分析与总结
varnish比较轻便,总共的代码量不大,功能上有待丰富和加强。
1.
2.
3.
4.
5.
6.
7.
讨论
1.
2.
3.
参考
1 http://varnish.projects.linpro.no/
2 http://en.wikipedia.org/wiki/Varnish_cache
3http://en.wikipedia.org/wiki/Virtual_memory
http://blog.sina.com.cn/s/blog_4ee5959b0100bo45.html