認識Varnish負載均衡
開源的產品總是會引起不少人的注意和喜愛。那么,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):實際的工作線程,實現主要功能。