Lighttpd+Squid+Apache搭建高效率Web服務器

架構原理
Apache通常是開源界的首選Web服務器,因為它的強大和可靠,已經具有了品牌效應,可以適用于絕大部分的應用場合。但是它的強大有時候卻顯得笨重,配置文件得讓人望而生畏,高并發情況下效率不太高。而輕量級的Web服務器Lighttpd卻是后起之秀,其靜態文件的響應能力遠高于Apache,據說是Apache的2-3倍。Lighttpd的高性能和易用性,足以打動我們,在它能夠勝任的領域,盡量用它。Lighttpd對PHP的支持也很好,還可以通過Fastcgi方式支持其他的語言,比如Python。

畢竟Lighttpd是輕量級的服務器,功能上不能跟Apache比,某些應用無法勝任。比如Lighttpd還不支持緩存,而現在的絕大部分站點都是用程序生成動態內容,沒有緩存的話即使程序的效率再高也很難滿足大訪問量的需求,而且讓程序不停的去做同一件事情也實在沒有意義。首先,Web程序是需要做緩存處理的,即把反復使用的數據做緩存。即使這樣也還不夠,單單是啟動Web處理程序的代價就不少,緩存最后生成的靜態頁面是必不可少的。而做這個是 Squid的強項,它本是做代理的,支持高效的緩存,可以用來給站點做反向代理加速。把Squid放在Apache或者Lighttpd的前端來緩存 Web服務器生成的動態內容,而Web應用程序只需要適當地設置頁面實效時間即可。

即使是大部分內容動態生成的網站,仍免不了會有一些靜態元素,比如圖片、JS腳本、CSS等等,將Squid放在Apache或者Lighttp前端后,反而會使性能下降,畢竟處理HTTP請求是Web服務器的強項。而且已經存在于文件系統中的靜態內容再在Squid中緩存一下,浪費內存和硬盤空間。因此可以考慮將Lighttpd再放在Squid的前面,構成 Lighttpd+Squid+Apache的一條處理鏈,Lighttpd在最前面,專門用來處理靜態內容的請求,把動態內容請求通過proxy模塊轉發給Squid,如果Squid中有該請求的內容且沒有過期,則直接返回給Lighttpd。新請求或者過期的頁面請求交由Apache中Web程序來處理。經過Lighttpd和Squid的兩級過濾,Apache需要處理的請求將大大減少,減少了Web應用程序的壓力。同時這樣的構架,便于把不同的處理分散到多臺計算機上進行,由Lighttpd在前面統一把關。

在這種架構下,每一級都是可以進行單獨優化的,比如Lighttpd可以采用異步IO方式,Squid可以啟用內存來緩存,Apache可以啟用MPM 等,并且每一級都可以使用多臺機器來均衡負載,伸縮性很好。

實例講解
下面以daviesliu.net和rainbud.net域下面的幾個站點為例來介紹一下此方案的具體做法。daviesliu.net域下有幾個用 mod_python實現的blog站點,幾個php的站點,一個mod_python的小程序,以后可能還會架設幾個PHP和Django的站點。而服務器非常弱,CPU為Celeron 500,內存為PC 100 384M,因此比較關注Web服務器的效率。這幾個站點都是采用虛擬主機方式,開在同一臺機器的同一個端口上。

Lighttpd服務于80端口,Squid運行在3128端口,Apache運行在81端口。

Lighttpd的配置
多個域名采用/var/www/domain/subdomain 的目錄結構,用evhost模塊配置document-root如下:

evhost.path-pattern        =  var.basedir + "/%0/%3/"

FtpSearch中有Perl腳本,需要啟用CGI支持,它是用來做ftp站內搜索的,緩存的意義不大,直接由lighttpd的mod_cgi處理:

$HTTP["url"] =~ "^/cgi-bin/" { # only allow cgi's in this directory
    dir-listing.activate = "disable"    # disable directory listings
    cgi.assign = ( ".pl"   =>  "/usr/bin/perl", ".cgi"  =>  "/usr/bin/perl" )
}

bbs使用的是phpBB,訪問量不大,可以放在lighttpd(fastcgi)或者apache(mod_php)下,暫時使用 lighttpd,設置所有.php的頁面請求有fastcgi處理:

fastcgi.server = ( ".php" =>  ( (  "host"  => "127.0.0.1", "port"=> 1026,  "bin-path"  =>  "/usr/bin/php-cgi"  )  ) )

blog.daviesliu.net 和 blog.rainbud.net 是用mod_python編寫的blogxp程序,所有靜態內容都有擴展名,而動態內容沒有擴展名。blogxp是用python程序生成XML格式的數據再交由mod_xslt轉換成HTML頁面,只能放在Apache下運行。該站點采用典型Lighttpd+Squid+Apache方式處理:

$HTTP["host"] =~ "^blog" {
    $HTTP["url"] !~ "." {     
        proxy.server = ( "" => ( "localhost" => ( "host"=> "127.0.0.1", "port"=> 3128 ) ) )  #3128端口為
    }
}

share中有靜態頁面,也有用mod_python處理的請求,在/cgi/下:

$HTTP["host"] =~ "^share" {
    proxy.server = (
        "/cgi" => ( "localhost" => ( "host"=> "127.0.0.1", "port"=> 3128 )  ) 
    )
}

Squid的配置
只允許本地訪問:

http_port   3128
http_access allow localhost
http_access deny all

啟用反向代理:

 httpd_accel_host 127.0.0.1
 httpd_accel_port 81                   #apache的端口
 httpd_accel_single_host on
 httpd_accel_with_proxy on          #啟用緩存
 httpd_accel_uses_host_header on #啟用虛擬主機支持

此方向代理支持該主機上的所有域名。

Apache的配置
配置/etc/conf.d/apache2,讓其加載mod_python、mod_xslt、mod_php模塊:

APACHE2_OPTS="-D PYTHON -D XSLT -D PHP5"

所有網站的根目錄:

<Directory "/var/www">
   AllowOverride All     #允許.htaccess覆蓋
    Order allow,deny
    Allow from all
</Directory>

基于域名的虛擬主機:

<VirtualHost *:81>
ServerName blog.daviesliu.net
DocumentRoot /var/www/daviesliu.net/blog
</VirtualHost>

這里明顯沒有lighttpd的evhost配置方便。

blog.daviesliu.net下的.htaccess設置(便于開發,不用重啟Apache):

SetHandler mod_python
PythonHandler blogxp.publisher
PythonDebug On
PythonAutoReload On

<FilesMatch ".">
    SetHandler None        #靜態文件直接由Apache處理
</FilesMatch>

<IfModule mod_xslt.c>
    AddType text/xsl .xsl  #防止對xsl文件進行轉化
    AddOutputFilterByType mod_xslt text/xml
    XSLTCache off
    XSLTProcess on
</IfModule>
Header set Pragma "cache"
Header set Cache-Control "cache"

在blogxp.publisher里面,還需要設置返回的文檔類型和過期時間:

    req.content_type = "text/xml"
    req.headers_out['Expires'] = formatdate( time.time() + 60 * 5 )

經過這樣的配置,所有站點都可以通過80、3128、81三個端口進行正常訪問,80端口用作對外的訪問,以減少負荷。81端口可以用作開發時的調試,沒有緩存的困擾。

性能測試
由于時間和精力有限,下面只用ab2做一個并不規范的性能對比測試(每項都測多次取平均),評價指標為每秒鐘的請求數。
測試命令,以測試lighttpd上并發10個請求 scripts/prototype.js 為例:

ab2 -n 1000 -c 10 http://blog.daviesliu.net:80/scripts/prototype.js

靜態內容:prototype.js (27kB)

Con
 Lighttpd(:80)
 Squid(:3128)
 Apache(:81)
 
1
 380
 210
 240
 
10
 410
 215
 240
 
100
 380
 160
 230
 
可見在靜態內容上,Lighttpd表現強勁,而Squid在沒有配內存緩存的情況下比另兩個Web服務器的性能要差些。

動態頁面:/rss (31kB)

Con
 Lighttpd(:80)
 Squid(:3128)
 Apache(:81)
 
1
 103
 210
 6.17
 
10
 110
 200
 6.04
 
100
 100
 100
 6.24
 

 

在動態內容上,Squid的作用非常明顯,而Lighttpd受限于Squid的效率,并且還要低一大截。如果是有多臺Squid來做均衡的話,Lighttpd的功效才能發揮出來。
在單機且靜態內容很少的情況下,可以不用Lighttpd而將Squid置于最前面。

發表評論

(required)

This site uses Akismet to reduce spam. Learn how your comment data is processed.