大型網站后臺架構的Web Server與緩存
1.1 Web server
Web server 用來解析HTTP協議。當web服務器接收到一個HTTP請求時,會返回一個HTTP響應,例如送回一個HTML頁面。為了處理一個請求,web服務器可以響應一個靜態頁面或者圖片。進行頁面跳轉,或者把動態響應的產生委托給一些其它的程序完成,比如CGI, JSP, Servlets, ASP.NET,PHP腳本。
當用戶訪問一個網站時,首先用戶通過查詢DNS服務器,得到該域名對應的IP地址,然后使用這個IP地址來進行訪問。用戶的請求是一個url地址,在web服務器端,url地址對應web服務器上的文件系統中的某個網站文件的路徑。Web server的作用就是解析HTTP協議,通過用戶發來請求的url地址從web服務器的文件系統中找到用戶需要的HTML頁面、靜態文件,然后返回給用戶。如果用戶訪問的是動態頁面,則將請求轉發到應用服務器來執行。
1.1.1 FastCGI
1.1.1.1 CGI
CGI(Common Gateway Interface) ,指運行在服務器上,提供同客戶端HTML頁面的接口。多數CGI程序被用來解釋處理來自表單的輸入信息,并在服務器產生相應的處理,或將相應的信息反饋給瀏覽器。
1.1.1.2 FastCGI
FastCGI是語言無關的、可伸縮架構的CGI開放擴展,其主要行為是將CGI解釋器進程保持在內存中并因此獲得較高的性能。而CGI解釋器的反復加載是CGI性能低下的主要原因。如果CGI解釋器保持在內存中并接受FastCGI進程管理器的調度,則可以提供良好的性能、伸縮性能和Fail-over特性等。
FastCGI的工作原理如下:
(1) FastCGI進程管理器自身初始化,啟動多個CGI解釋器進程(多php-cgi進程)并等待來自web server的連接。啟動php-cgi FastCGI進程時,可以配置以TCP和UNIX套接字兩種方式啟動。
(2) 當客戶端請求到達web服務器時,web服務器將請求采用TCP協議或者UNIX套接字方式轉發到FastCGI主進程,FastCGI主進程選擇并連接到一個CGI解釋器(子進程)。Web服務器將CGI環境變量和標準輸入法發送到FastCGI子進程php-cgi。
(3) FastCGI子進程完成處理后,將標準輸出和錯誤信息從同一連接返回web服務器。當FastCGI子進程關閉連接時,請求便告知處理完成。FastCGI子進程接著等待并處理來自FastCGI進程管理器的下一個連接。
FastCGI的優點如下:
(1) 穩定性。FastCGI是以獨立的進程池運行CGI,單獨一個進程死掉,系統可以輕松的丟棄,然后重新分配新的進程。
(2) 安全性。FastCGI和宿主Server完全獨立,FastCGI如果down了,不會影響到Server的性能。
(3) 高性能。FastCGI和宿主Server分開,大負荷的IO處理留給web server進行,比如大量圖片、CSS等靜態文件的IO操作,完全由web server處理完成。[2]
1.1.1.3 Lighttpd服務器
Lighttpd是一個具有非常低的內存開銷,CPU占用率低,性能好的輕量級Web Server。支持FastCGI, CGI, 輸出壓縮,URL重寫,Alias等重要功能。
Lighttpd使用FastCGI方式運行php。
1.1.1.4 Apache服務器
Apache是世界上使用最多的web服務器,市場占有率50%以上。Apache支持SSL技術,支持多個虛擬主機。Apache是以進程為基礎結構,進程相對線程消耗更多系統資源。相對Lighttpd和Nginx,Apache是一款重量級的web服務器。總體來講,Apache web 服務器具有以下特性:
(1) 支持HTTP1.1通信協議。
(2) 支持通用網關接口。
(3) 支持基于ip、域名、端口的虛擬主機。
(4) 支持服務器端包含指令(ssl)。
(5) 支持FastCGI。
(6) 支持url重寫。
1.1.1.5 Nginx服務器
Nginx是俄羅斯人Igor Sysoev編寫的一款高性能HTTP和反向代理服務器。Nginx能夠選擇高效的epoll(Linux 2.6內核)、kqueue(FreeBSD)、eventport(Solaris 10)作為網絡I/O模型,在高連接并發的情況下,Nginx是Apache服務器很好的替代者,因為在同樣并發連接的情況下,Nginx相對Apache占用更少的系統資源。[3]
1.1.1.6 Lighttpd、Apache、Nginx比較
Lighttpd是一個單進程模型的web server,內存使用量很小。Nginx在內存分配方面,表現良好。它使用多線程來處理請求,這使得多個線程之間可以共享內存資源,從而使它的內存使用量大大減少。此外,Nginx使用分階段的內存分配策略,按需分配,及時釋放,所以總體占用內存很小。可以支持較大的并發連接數。Apache在運行時使用較大的內存,Apache是多進程模型。Apache使用基于內存池策略的內存管理方法,這種方法使得Apache在運行開始時便一次性申請大片內存作為內存池,這樣在隨后需要的時候只在內存池中直接獲取,不需要再分配。顯然,Apache很占用內存。根據國內金山技術經理、系統架構師張宴給出的統計信息,2009年的web server使用情況如表4-1-1-5所示。
表4-1-1-5 各種web server市場占有率排名
Web server |
2008.12使用數 |
占有率 |
2009.01使用數 |
占有率 |
占有率變化 |
Apache |
95678052 |
51.24% |
96947298 |
52.26% |
+1.02% |
IIS |
63126940 |
33.81% |
61038371 |
32.91% |
-0.90% |
|
10455103 |
5.60% |
9868819 |
5.32% |
-0.28 |
Nginx |
3354329 |
1.80% |
3462551 |
1.87% |
+0.07% |
Lighttpd |
3046333 |
1.63% |
2989416 |
1.61% |
-0.02% |
1.2 緩存
在計算機系統中,緩存有很多種。比如CPU內部的一級緩存、二級緩存。文件系統的緩存,磁盤的緩存。在大型網站的后臺部署過程中,也靈活運用了各級緩存。主要有客戶端的瀏覽器緩存,服務器端的web server自身緩存,代理緩存,分布式緩存,數據庫自身的緩存等。本節主要分析一下代理緩存和分布式緩存。
1.2.1 代理緩存
在網站后臺架構中,代理緩存主要部署在web server之上,當用戶對網站后臺發起連接請求時,用戶請求先到代理緩存中去查找,如果命中,則將請求返回給用戶,如果沒有命中,則代理緩存將請求發到web server,然后web sever將請求復制一份到代理緩存中,同時把請求返回給客戶。
常用的代理緩存有varnish和squid。如圖4-2-1所示。
圖4-2-1 代理緩存(黃色部分)
1.2.1.1 Squid
Squid是一個高性能的代理緩存服務器,可以用來加快瀏覽網頁的速度,提高客戶機的訪問命中率。Squid不僅支持HTTP協議,還支持FTP、SSL、WAIS等協議。Squid用一個單獨的、非模塊化的、I/O驅動的進程來處理所有的客戶端請求。
Squid的原理如下:
(1) 每一臺Squid代理服務器上存有若干個顆磁盤。每顆磁盤又分割成多個分區,每一個分區又可建立很多目錄,目錄下存放著具體的文件(object)。
(2) Squid通過查詢表的方式來定位某個資源的位置。所查詢的表有兩種,一種是Hash table,一種是Digest table。Hash table記錄著所有Digest table表信息,所以Hash table可以稱之為目錄或者提綱。而Digest table記錄了磁盤上每個分區、每個目錄里存放的緩存摘要,所以Digest table可以稱之為摘要或者索引。所以,Squid接到請求后先查詢Hashtable,根據Hash table所指向的Digest table,再查詢所需要的文件。
(3) Squid服務器存在兩種工作關系,一種為Child-Parent,當Child Squid Server沒有用戶需要的數據時,就向Parent squid Server發送請求,并持續等待,直到Parent Squid Server回應為止;另一種為Sibling,當本地Squid Server沒有用戶請求的數據時,會向Sibling Server發送請求,如果Sibling Server沒有資料則會向上級Sibling或者Internet發送數據請求。
所以,綜上所述,Squid運行模式如下:
當Squid Server沒有資料時,先向Sibling的Squid Server查詢數據,如果Sibling沒有,則跳過它直接向Parent查詢,直到Parent提供資料為止(如果Parent沒有資料,則到后端的web server上獲取,當獲取到數據后返回給用戶的同時,保留一份在自身的緩存中)。如果不存在Parent,則Squid Server自身到后端的web server上獲取數據,當獲取到數據后返回給用戶的同時,保留一份在自身的緩存中。如果還是不能得到數據,則向用戶端回復不能得到數據。
1.2.1.2 Varnish
Varnish是一款高性能的開源HTTP加速器,挪威最大的在線報紙Verdens Gang使用3臺Varnish代替了原來的12臺Squid,性能比以前更好。
Varnish的作者Poul-Henning Kamp是FreeBSD內核開發者之一,他認為現在的計算機比起1975年已經復雜很多。在1975年時,存儲媒介只有兩種:內存與硬盤。但現在計算機系統的內存除了主存外,還包括了CPU內的L1\L2\L3等cache。因此Squid Cache自行處理物件替換的架構不可能得知這些情況而做到最佳化,但操作系統可以。所以這部分的工作應該交給操作系統處理,這就是Varnish cache設計架構[4]。Varnish將所有的HTTP object存于一個單獨的大文件中,該文件在工作進程初始化的時候,將其整個映射到內存中。這樣Varnish在該塊內存中實現一個簡單的文件系統,具有分配、釋放、修剪、合并內存等功能。
Varnish文件緩存的工作流程:
Varnish與一般服務器軟件類似,分為master進程和child進程。其中master進程負責管理,child進程負責cache工作。Master進程讀入命令,進行一些初始化,然后fork并監控child進程。Child進程分配若干線程進行工作,主要包括管理線程和worker線程。如圖4-2-1-2所示。
圖4-2-1-2
主進程fork子進程,主進程等待子進程的信號,子進程退出后,主進程重新啟動子進程,子進程生成若干線程:
(1) Accept線程:接受請求,將請求掛在overflow隊列上。
(2) Work線程:有多個,負責從overflow隊列上摘除請求,對請求進行處理,直到完成,然后處理下一個請求。
(3) Epoll線程:一個請求處理稱為一個session,在session周期內,處理完請求后,會交給Epoll處理,監聽是否還在事件發生。
(4) Expire線程:對于緩存的object,根據過期時間,組織成二叉堆,該線程周期檢查該堆得根,處理過期的文件。對過期的數據進行刪除或重取操作。
Varnish分配緩存機制:
根據所讀到的object大小,創建相應大小的緩存文件。為了讀寫方便,程序將每個object的大小,轉變為最接近其大小的內存頁面倍數。然后從現有的空閑存儲結構體中查找,找到最合適的大小的空閑存儲塊,分配給它。如果空閑塊沒有用完,則把多余的內存再組成一個空閑存儲塊,掛接到管理結構體上。如果緩存已滿,則根據LRU算法,把舊的object釋放掉。
Varnish釋放緩存機制:
Expire線程負責檢測緩存中所有object的生存期(TTL)。如果超過了設定的TTL,該object沒有被訪問,則刪除該object,并釋放內存。釋放的過程會考慮內存的合并等操作。
1.2.2 分布式緩存
1.2.2.1 Memcached
Memcached是以LiveJournal旗下Danga Interactive公司的Brad Fitzpatric為首開發的一款軟件。現在Memcached已成為mixi、hatena、Facebook等公司提高web應用擴展性的重要緩存軟件。許多web應用都將數據保存到RDBMS中,應用服務器從中讀取數據并返回給用戶。但隨著數據量的增大,訪問的集中性,讀寫比例的增大,會使RDBMS增加其系統開銷,相應速度下降,網絡延遲增大。Memcached通過緩存數據庫查詢結果,減少數據庫讀的訪問次數,提高動態網站的響應速度。此外,電子商務網站的客戶端cookie和服務器端session機制也可以利用Memcached解決,比如典型的購物車跟蹤記錄訪問行為、購買問題等。也可以將其信息記錄在后端的Memcached中。典型的應用如圖4-2-2-1-1所示。
圖 4-2-2-1-1
如圖所示,當用戶第一次訪問數據庫時,應用服務器從數據庫中查詢數據返回給用戶,并且在memcached中存儲一份數據。當第二次,應用服務器需要從數據庫中查詢數據時,首先從memcached查詢數據,如果有則得到數據,返回給用戶,如果沒有,則再從數據庫中查找數據。返回給用戶,并拷貝一份數據到memcached中。
Memcached默認情況下采用名為Slab Allocator的機制分配、管理內存。Slab Allocator的基本原理是按照預先規定的大小,將分配的內存分割成特定長度的塊,以完全解決內存碎片問題。
Slab Allocator原理,將分配的內存分割成各種尺寸的塊(chunk),并將尺寸相同的塊分成組(chunk的集合)。如圖4-2-2-1-2所示。
圖 4-2-2-1-2
如圖所示,memcached根據收到的數據的大小,選擇最適合數據大小的slab。Memcached中保存著slab內空閑chunk的列表,根據該列表選擇chunk,然后將數據緩存在其中。如圖4-2-2-1-3所示。
圖4-2-2-1-3
同squid、varnish一樣,memcached同樣使用LRU機制來分配內存,刪除最近最少未使用的數據。
1.3 本文小結
本章主要分析了FastCGI的運行機制,簡單介紹了三種常用的web server —— Lighttpd、Apache、Nginx,對三款常用web server進行了對比。然后又分別介紹了代理緩存Squid和Varnish。最后簡單分析了分布式緩存Memcached。總體而言,這些緩存的應用可以極大加快網站的訪問速度。提升用戶體驗。緩存的應用,在高可用的大型網站中,處處可見。
留言列表