开源的产品总是会引起不少人的注意和喜爱。那么,varnish这个加速产品,熟悉HTTP这块领域的朋友都不会陌生。它的负载均衡应用优势什么样子的呢?这还要我们从它的结构和性能说起,之后才是对于负载均衡的介绍,其中还有一些进程问题,如果大家不能很好的掌握,还需要对这些知识进行一下充电。
Varnish负载均衡的分析
最近分析了varnis-2.0.4的一部分代码,主要侧重于其在负载均衡部分的实现。通过阅读一些参考文献,以及自己的一些见解我分析,将代码分析文档整理于此。
首先将varnish整体工作流程在此进行介绍。
1.Varnish 的总体结构
Varnish 主要有两个进程:管理进程和 cache 子进程。
1)管理进程主要就是对于varnish的整个工作状态进行的调整和设置。编译运行之后,它将建立一个守护进程varnishd。Varnishd不断folk()出cache子进程来处理HTTP请求。它的实现部分在源代码中bin/varnishd/目录中,主要文件有varnishd.c 、mgt.h、mgt_chld.c、mgt_param.c mgt_cli.h、mgt_pool.c 、mgt_vcc.c、mgt_cli.h、mgt_cli.c。
2)下面谈谈cache子进程。
Cache子进程包含了实现命令行加载、请求处理、缓存以及负载均衡的所有线程。分别为:命令行接受处理线程(CLI_Run) ,放牧线程(wrk_herder_thread),放牧超时线程(wrk_herdtimer_thread),请求接受线程(vca_acct),数据接受线程(vca_main),很多工作线程(wrk_thread),HTTP对象超时线程(exp_timer),后台服务器连接探测线程(vbp_wrk_poll_backend)。
主要涉及到的文件有:
cache_lck.c、cache_panic.c、cache_cli.c、cache_fetch.c、cache_center.c、cache_vcl.c、cache_http.c、cache_session.c、cache_backend_cfg.c、cache_backend_pool.c、cache_backend.h、cache_pool.c、cache_expire.c、cache_hash.c、cache_accptor.c
Cache 子进程处理所有具体工作,各个线程的任务包括:
◆命令行接受处理线程(CLI_Run):接受从管理进程通过管道传过来的命令,做出相应决定。其中初始时由管理进程默认产生,三个命令(vcl.load、vcl.use、start)来启动后台服务器连接探测线程 和两个接受线程。
◆放牧线程(wrk_herder_thread):用于产生工作线程池。线程不足时会增加线程池。
◆放牧超时检查线程(wrk_herdtimer_thread):清理一些工作超时的工作线程。
◆请求接受线程(vca_acct):接受 HTTP 初次请求,并叫醒某个工作线程,处理请求。
◆数据接受线程(vca_main):在发送数据以后,继续可能的再次请求,并把请求交给工作线程。
◆工作线程(wrk_thread):不断处理请求,进入状态机。如果缓存没有命中,还需要从后台服务取过数据,存入缓存并回复。然后把该连接通过管道转给数据接受线程并睡去。
◆HTTP 对象超时检查线程(exp_timer):检查二叉堆中 HTTP 超时对象,删除之。
◆后台服务器连接探测线程(vbp_wrk_poll_backend):针对不同的后台服务器组进行轮询,检查存活与否。
各线程的工作流程大致如图一所示
图一:cache子进程各个线程流程图#p#
2.负载均衡实现的分析
就目前分析来看,Cache子进程的代码实现部分主要由cache_main.c这个文件为主要脉络的。Cache_main.c中将cache子进程的各个线程一一初始化。
目前我所关注的重点在于wrk_thread部分,它是实现varnish负载均衡的主要内容。
1)wrk_thread的作用:不断处理请求,进入状态机。如果缓存没有命中,还需要从后台服务取过数据,存入缓存并回复。然后把该连接通过管道转给数据接受线程并sleep。
2)wrk_thread的工作流程:
图二:cache子进程中,wrk_thread线程工作流程
3)Wrk_thread的代码实现分析:wrk_thread线程在cache_main.c文件中初始化(代码:WRK_Init() ,cache_main.c,line 121),具体实现在cache_pool.c文件中出现。
Cache_pool.c文件中主要函数有:
static void
wrk_addpools(const unsigned pools):增添work线程池
static void *
wrk_herder_thread(void *priv) :放牧进程,用于产生工作线程池。线程不足时会增加线程;
static void *
wrk_herdtimer_thread(void *priv):放牧超时检查线程,清理一些工作超时的工作线程。
static void
wrk_breed_flock(struct wq *qp):在需要并且空间允许的情况下,产生新的线程
static void
wrk_decimate_flock(struct wq *qp, double t_idle, struct varnish_stats *vs):检查空闲或者已经执行完的线程,从线程池中清除。
static void *
wrk_thread(void *priv):实际的工作线程,实现主要功能。