歡迎您光臨本站 註冊首頁

實現lighttpd-1.5+mod_proxy_core+多 Fastcgi backends 解析PHP負載平衡

2007年3月13日改

在lighttpd.conf 中加入server.network-backend = "linux-aio-sendfile"

歡迎轉載哦,記得保留

作者為wigeboy
郵箱wigeboy<at>gmail.com
CU首發

標題起的比較詭異,呵呵.這裡最主要的想法是多個backends對PHP進行解析,達到負載平衡.

在lighttpd 1.5 已經和之前的版本有了很多新的元素同時也和之前的版本配置上略有不同,下面談談我個人的記錄筆記.
我們先使用一個新的元素linux-aio-sendfile.和之前有什麼不同,我們轉一下lighhtpd BLOG上面的數據

大家可以去http://blog.lighttpd.net/articles/2006/11/12/lighty-1-5-0-and-linux-aio查看詳細數據.


Using Async IO allows lighttpd it overlap file-operations. We send a IO-request for the file and get notified when it is ready. Instead of waiting for the file (as in the normal sendfile()) and blocking the server, we can handle other requests instead.
On the other side we give the kernel to reorder the file-requests as it wants to.
Taking this two improments we can increase the throughput by 80%.
On the other side we don』t spend any time in wait in lighty itself. 64 kernel threads are handling the read()-calls for us in the background which increases the idle-time from 12% to 40%, a improvement of 230% .



1.下載編譯
lighttpd-1.5

先確保有裝 libaio

wget http://www.lighttpd.net/download/lighttpd-1.5.0-r1477.tar.gz

tar -zxvf lighttpd-1.5.0-r1477.tar.gz

cd lighttpd-1.5.0

./configure --prefix=/usr/local/lighttpd --with-linux-aio
沒有出錯的話就

make

make install
LightHttpd 會出現在 /usr/local/lighttpd

為lighttpd 建立 用戶


groupadd lighttpd
useradd -g lighttpd -s /sbin/nologin -d /dev/null lighttpd

mkdir /usr/local/lighttpd/conf
mkdir /usr/local/lighttpd/log

mv ./doc/lighttpd.conf /usr/local/lighttpd/conf/

chown -R lighttpd:lighttpd /usr/local/lighttpd

2.下載編譯PHP
使用--enable-fastcgi 來編譯 這裡不多說了.

記得在php.ini 中把,同時奉上防呆有情提醒,把前面的註釋去掉
cgi.fix_pathinfo = 0  改為 cgi.fix_pathinfo = 1


3.啟動Fastcgi backends

在doc目錄內尋找spawn-php.sh

vi spawn-php.sh

#!/bin/bash
## ABSOLUTE path to the spawn-fcgi binary
SPAWNFCGI="/usr/local/lighttpd/bin/spawn-fcgi"              #<===修改這個,找到你的lighttpd相應目錄中的spawn-fcgi
## ABSOLUTE path to the PHP binary
FCGIPROGRAM="/usr/php/bin/php"                                #<===修改為你的PHP路徑,注意並非目錄
## TCP port to which to bind on localhost
FCGIPORT="1026"                                                       #<===埠,一會多backends需要修改
## number of PHP children to spawn
PHP_FCGI_CHILDREN=10
## maximum number of requests a single PHP process can serve before it is restarted
PHP_FCGI_MAX_REQUESTS=1000
## IP addresses from which PHP should access server connections
FCGI_WEB_SERVER_ADDRS="127.0.0.1"                          #<===如果前台httpd非本機,請填寫前台伺服器相應IP
# allowed environment variables, separated by spaces
ALLOWED_ENV="ORACLE_HOME PATH USER"
## if this script is run as root, switch to the following user
USERID=lighttpd                                                            #<===運行用戶
GROUPID=lighttpd

################## no config below this line
if test x$PHP_FCGI_CHILDREN = x; then
  PHP_FCGI_CHILDREN=5
fi
export PHP_FCGI_MAX_REQUESTS
export FCGI_WEB_SERVER_ADDRS
ALLOWED_ENV="$ALLOWED_ENV PHP_FCGI_MAX_REQUESTS FCGI_WEB_SERVER_ADDRS"
if test x$UID = x0; then
  EX="$SPAWNFCGI -p $FCGIPORT -f $FCGIPROGRAM -u $USERID -g $GROUPID -C $PHP_FCGI_CHILDREN"
else
  EX="$SPAWNFCGI -p $FCGIPORT -f $FCGIPROGRAM -C $PHP_FCGI_CHILDREN"
fi
# copy the allowed environment variables
E=
for i in $ALLOWED_ENV; do
  E="$E $i=${!i}"
done
  
# clean the environment and set up a new one
env - $E $EX


如果想多個backends 那麼只需要copy 多幾個 spawn-php.sh 為 spawn-php.1sh   等等再修改上面的埠為 1027,1028.

假設我需要在本機運行3個backends 分別對應 spawn-php.sh 1026 | spawn-php1.sh 1027 |spawn-php2.sh 1028


./spawn-php.sh
./spawn-php1.sh
./spawn-php2.sh

好了,可以在top 命令下看見PHP的進程了.


4.OK,下面配置lighhtpd

vi /usr/local/lighttpd/conf/lighttpd.conf



#lighttpd configuration file
# use it as a base for lighttpd 1.0.0 and above
#
# $Id: lighttpd.conf,v 1.7 2004/11/03 22:26:05 weigon Exp $
############ Options you really have to take care of ####################
## modules to load
# at least mod_access and mod_accesslog should be loaded
# all other module should only be loaded if really neccesary
# - saves some time
# - saves memory
server.modules              = (
                               "mod_rewrite",
                               "mod_redirect",
#                               "mod_alias",
                                "mod_access",
#                               "mod_cml",
#                               "mod_trigger_b4_dl",
#                               "mod_auth",
#                               "mod_status",
#                               "mod_setenv",
                               "mod_proxy_core",                                                   #<===將幾個需要用到的mod前的#去掉
                              "mod_proxy_backend_http",
                               "mod_proxy_backend_fastcgi",
#                               "mod_proxy_backend_scgi",
#                               "mod_simple_vhost",
#                               "mod_evhost",
#                               "mod_userdir",
#                               "mod_cgi",
#                               "mod_compress",
#                               "mod_ssi",
#                               "mod_usertrack",
#                               "mod_expire",
#                               "mod_secdownload",
#                               "mod_rrdtool",
                                "mod_accesslog" )
## a static document-root, for virtual-hosting take look at the
## server.virtual-* options
server.document-root        = "/var/www/bbs/"                         #<===WEB目錄
## where to send error-messages to
server.errorlog             = "/usr/local/lighttpd//log/lighttpd.error.log"                #<===錯誤日誌
# files to check for if .../ is requested
index-file.names            = ( "index.php", "index.html",
                                "index.htm", "default.htm","index.php" )                          #<===首頁
## set the event-handler (read the performance section in the manual)
# server.event-handler = "freebsd-kqueue" # needed on OS X

# mimetype mapping
mimetype.assign             = (
  ".pdf"          =>      "application/pdf",
  ".sig"          =>      "application/pgp-signature",
  ".spl"          =>      "application/futuresplash",
  ".class"        =>      "application/octet-stream",
  ".ps"           =>      "application/postscript",
  ".torrent"      =>      "application/x-bittorrent",
  ".dvi"          =>      "application/x-dvi",
  ".gz"           =>      "application/x-gzip",
  ".pac"          =>      "application/x-ns-proxy-autoconfig",
  ".swf"          =>      "application/x-shockwave-flash",
  ".tar.gz"       =>      "application/x-tgz",
  ".tgz"          =>      "application/x-tgz",
  ".tar"          =>      "application/x-tar",
  ".zip"          =>      "application/zip",
  ".mp3"          =>      "audio/mpeg",
  ".m3u"          =>      "audio/x-mpegurl",
  ".wma"          =>      "audio/x-ms-wma",
  ".wax"          =>      "audio/x-ms-wax",
  ".ogg"          =>      "application/ogg",
  ".wav"          =>      "audio/x-wav",
  ".gif"          =>      "image/gif",
  ".jpg"          =>      "image/jpeg",
  ".jpeg"         =>      "image/jpeg",
  ".png"          =>      "image/png",
  ".xbm"          =>      "image/x-xbitmap",
  ".xpm"          =>      "image/x-xpixmap",
  ".xwd"          =>      "image/x-xwindowdump",
  ".css"          =>      "text/css",
  ".html"         =>      "text/html",
  ".htm"          =>      "text/html",
  ".js"           =>      "text/javascript",
  ".asc"          =>      "text/plain",
  ".c"            =>      "text/plain",
  ".cpp"          =>      "text/plain",
  ".log"          =>      "text/plain",
  ".conf"         =>      "text/plain",
  ".text"         =>      "text/plain",
  ".txt"          =>      "text/plain",
  ".dtd"          =>      "text/xml",
  ".xml"          =>      "text/xml",
  ".mpeg"         =>      "video/mpeg",
  ".mpg"          =>      "video/mpeg",
  ".mov"          =>      "video/quicktime",
  ".qt"           =>      "video/quicktime",
  ".avi"          =>      "video/x-msvideo",
  ".asf"          =>      "video/x-ms-asf",
  ".asx"          =>      "video/x-ms-asf",
  ".wmv"          =>      "video/x-ms-wmv",
  ".bz2"          =>      "application/x-bzip",
  ".tbz"          =>      "application/x-bzip-compressed-tar",
  ".tar.bz2"      =>      "application/x-bzip-compressed-tar"
)
# Use the "Content-Type" extended attribute to obtain mime type if possible
#mimetype.use-xattr        = "enable"

## send a different Server: header
## be nice and keep it at lighttpd
# server.tag                 = "lighttpd"
#### accesslog module
accesslog.filename          = "/usr/local/lighttpd/log/access.log"                  #<===日誌
## deny access the file-extensions
#
# ~    is for backupfiles from vi, emacs, joe, ...
# .inc is often used for code includes which should in general not be part
#      of the document-root
url.access-deny             = ( "~", ".inc" )
$HTTP["url"] =~ "\.pdf$" {
  server.range-requests = "disable"
}
##
# which extensions should not be handle via static-file transfer
#
# .php, .pl, .fcgi are most often handled by mod_fastcgi or mod_cgi
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )
######### Options that are good to be but not neccesary to be changed #######
## bind to port (default: 80)
#server.port                = 81
## bind to localhost (default: all interfaces)
#server.bind                = "grisu.home.kneschke.de"
## error-handler for status 404
#server.error-handler-404   = "/error-handler.html"
#server.error-handler-404   = "/error-handler.php"
## to help the rc.scripts
server.pid-file            = "/var/run/lighttpd.pid"                      #<===pid

###### virtual hosts
##
##  If you want name-based virtual hosting add the next three settings and load
##  mod_simple_vhost
##
## document-root =
##   virtual-server-root + virtual-server-default-host + virtual-server-docroot
## or
##   virtual-server-root + http-host + virtual-server-docroot
##
#simple-vhost.server-root   = "/home/weigon/wwwroot/servers/"
#simple-vhost.default-host  = "grisu.home.kneschke.de"
#simple-vhost.document-root = "/pages/"

##
## Format: <errorfile-prefix><status-code>.html
## -> ..../status-404.html for 'File not found'
#server.errorfile-prefix    = "/home/weigon/projects/lighttpd/doc/status-"
## virtual directory listings
#dir-listing.activate       = "enable"
## enable debugging
#debug.log-request-header     = "enable"
#debug.log-response-header    = "enable"
#debug.log-request-handling   = "enable"
#debug.log-file-not-found     = "enable"
#debug.log-condition-handling = "enable"
### only root can use these options
#
# chroot() to directory (default: no chroot() )
#server.chroot              = "/"
## change uid to <uid> (default: don't care)
server.username            = "lighttpd"                                      #<===運行用戶
## change uid to <uid> (default: don't care)
server.groupname           = "lighttpd"                                     #<===運行組
#### compress module
#compress.cache-dir         = "/tmp/lighttpd/cache/compress/"
#compress.filetype          = ("text/plain", "text/html")
#### proxy module
## read proxy.txt for more info
#$HTTP["url"] =~ "\.php$" {
# proxy-core.balancer = "round-robin"
# proxy-core.allow-x-sendfile = "enable"
# proxy-core.protocol = "http"
# proxy-core.backends = ( "192.168.0.101:80" )
# proxy-core.max-pool-size = 16
#}

#### fastcgi module
## read fastcgi.txt for more info
## for PHP don't forget to set cgi.fix_pathinfo = 1 in the php.ini
$HTTP["url"] =~ "\.php$" {                                                                     #<===關鍵,將#去掉.
proxy-core.balancer = "round-robin"
proxy-core.allow-x-sendfile = "enable"                                                        #<===新的元素.
proxy-core.check-local = "enable"                                                              #<===先檢查是否有文件,再發送請求給後台.
proxy-core.protocol = "fastcgi"
proxy-core.backends = ( "127.0.0.1:1026","127.0.0.1:1027","127.0.0.1:1028" )                      #<===對應之前的設的backends
proxy-core.max-pool-size = 16                                                                   #<===別弄大了,死的很慘的><.
}

#### CGI module
#cgi.assign                 = ( ".pl"  => "/usr/bin/perl",
#                               ".cgi" => "/usr/bin/perl" )
#
#### SSL engine
#ssl.engine                 = "enable"
#ssl.pemfile                = "server.pem"
#### status module
#status.status-url          = "/server-status"
#status.config-url          = "/server-config"
#### auth module
## read authentication.txt for more info
#auth.backend               = "plain"
#auth.backend.plain.userfile = "lighttpd.user"
#auth.backend.plain.groupfile = "lighttpd.group"
#auth.backend.ldap.hostname = "localhost"
#auth.backend.ldap.base-dn  = "dc=my-domain,dc=com"
#auth.backend.ldap.filter   = "(uid=$)"
#auth.require               = ( "/server-status" =>
#                               (
#                                 "method"  => "digest",
#                                 "realm"   => "download archiv",
#                                 "require" => "user=jan"
#                               ),
#                               "/server-config" =>
#                               (
#                                 "method"  => "digest",
#                                 "realm"   => "download archiv",
#                                 "require" => "valid-user"
#                               )
#                             )
#### url handling modules (rewrite, redirect, access)
#url.rewrite                = ( "^/$"             => "/server-status" )
#url.redirect               = ( "^/wishlist/(.+)" => "http://www.123.org/$1" )
#### both rewrite/redirect support back reference to regex conditional using %n
#$HTTP["host"] =~ "^www\.(.*)" {
#  url.redirect            = ( "^/(.*)" => "http://%1/$1" )
#}
#
# define a pattern for the host url finding
# %% => % sign
# %0 => domain name + tld
# %1 => tld
# %2 => domain name without tld
# %3 => subdomain 1 name
# %4 => subdomain 2 name
#
#evhost.path-pattern        = "/home/storage/dev/www/%3/htdocs/"
#### expire module
#expire.url                 = ( "/buggy/" => "access 2 hours", "/asdhas/" => "access plus 1 seconds 2 minutes")
#### ssi
#ssi.extension              = ( ".shtml" )
#### rrdtool
#rrdtool.binary             = "/usr/bin/rrdtool"
#rrdtool.db-name            = "/var/www/lighttpd.rrd"
#### setenv
#setenv.add-request-header  = ( "TRAV_ENV" => "mysql://user@host/db" )
#setenv.add-response-header = ( "X-Secret-Message" => "42" )
## for mod_trigger_b4_dl
# trigger-before-download.gdbm-filename = "/home/weigon/testbase/trigger.db"
# trigger-before-download.memcache-hosts = ( "127.0.0.1:11211" )
# trigger-before-download.trigger-url = "^/trigger/"
# trigger-before-download.download-url = "^/download/"
# trigger-before-download.deny-url = "http://127.0.0.1/index.html"
# trigger-before-download.trigger-timeout = 10
## for mod_cml
## don't forget to add index.cml to server.indexfiles
# cml.extension               = ".cml"
# cml.memcache-hosts          = ( "127.0.0.1:11211" )
#### variable usage:
## variable name without "." is auto prefixed by "var." and becomes "var.bar"
#bar = 1
#var.mystring = "foo"
## integer add
#bar += 1
## string concat, with integer cast as string, result: "www.foo1.com"
#server.name = "www." + mystring + var.bar + ".com"
## array merge
#index-file.names = (foo + ".php") + index-file.names
#index-file.names += (foo + ".php")
#### include
#include /etc/lighttpd/lighttpd-inc.conf
## same as above if you run: "lighttpd -f /etc/lighttpd/lighttpd.conf"
#include "lighttpd-inc.conf"
#### include_shell
#include_shell "echo var.a=1"
## the above is same as:
#var.a=1


好了,我們現在運行lighttpd吧


/usr/local/lighttpd/sbin/lighttpd -f /usr/local/lighttpd/conf/lighttpd.conf

關閉就用

ps -A

查PID, 對應的kill掉


當然對應的proxy-core.balancer = "round-robin" 這個負載平衡還有其他幾種不同的.不過數RR這個最簡單.第一個給A1 第二個給A2,第三個給A3,第四個又給回A1.

這裡只羅列單伺服器的多個backends,多伺服器只需要修改相應的IP即可.



歡迎給小弟的email 來信探討 wigeboy<at>gmail.com,或QQ 558857

[ 本帖最後由 wigeboy 於 2007-3-13 18:35 編輯 ]
《解決方案》

thanks
《解決方案》

有個問題
記得在php.ini 中把cgi.fix_pathinfo = 0  改為 cgi.fix_pathinfo = 1
但是在php.ini裡面.cgi.fix_pathinfo這段是被註解起來的.也就是沒有發生作用.那改不改有差別嗎?還是要把前面";"給去掉?


PS:實際投入運作之後發現.lighttpd會自動退出.也許還是還有bug.也許是上述說明只是安裝成功.但還要加上微調參數才能穩定吧?希望樓主繼續測試.謝謝

[ 本帖最後由 j9595 於 2007-2-24 17:48 編輯 ]
《解決方案》

另外再問一個問題.如果使用三個backends.埠分別使用的是1206,1027,1028.那防火牆這3個port要打開嗎?
《解決方案》

頂樓主,不過lighttpd有其優點但至少在今日其穩定性,安全性,維護成本和apache這名將還有差距,如果比較商業化的運用,大多數人都還是會選apache的吧,如果有多伺服器的話合理配置優化好SQUID+apache架構,足夠WEB應用了,有更大負載可以使用LVS對緩存伺服器等進行集群式管理.LVS站點:   http://zh.linuxvirtualserver.org/
《解決方案》

請問lighttpd支持c語言程序的fastcgi嗎?
《解決方案》

原帖由 j9595 於 2007-2-23 23:25 發表
有個問題
記得在php.ini 中把cgi.fix_pathinfo = 0  改為 cgi.fix_pathinfo = 1
但是在php.ini裡面.cgi.fix_pathinfo這段是被註解起來的.也就是沒有發生作用.那改不改有差別嗎?還是要把前面";"給去掉 ...
當然需要去掉註解拉
《解決方案》

原帖由 j9595 於 2007-2-25 02:08 發表
另外再問一個問題.如果使用三個backends.埠分別使用的是1206,1027,1028.那防火牆這3個port要打開嗎?
這個也是必須的,特別是在有多台server的情況下
《解決方案》

原帖由 dream8888 於 2007-3-3 21:11 發表
頂樓主,不過lighttpd有其優點但至少在今日其穩定性,安全性,維護成本和apache這名將還有差距,如果比較商業化的運用,大多數人都還是會選apache的吧,如果有多伺服器的話合理配置優化好SQUID+apache架構,足夠WEB應用了 ...
如果這樣的話,http://www.youtube.com/ 不就完蛋了嘛?特別是在小RAM的server中 lighty非常適合,具體情況具體分析,不要說的那麼絕對。

[ 本帖最後由 wigeboy 於 2007-3-13 18:27 編輯 ]
《解決方案》

原帖由 dream8888 於 2007-3-3 21:11 發表
頂樓主,不過lighttpd有其優點但至少在今日其穩定性,安全性,維護成本和apache這名將還有差距,如果比較商業化的運用,大多數人都還是會選apache的吧,如果有多伺服器的話合理配置優化好SQUID+apache架構,足夠WEB應用了 ...


你是沒用過吧?不要老說apache.換個腦袋嘗試看看再說.apache誰沒用過阿.當然是覺得有缺點才嘗試其他的阿.話不要說得太早

[火星人 ] 實現lighttpd-1.5+mod_proxy_core+多 Fastcgi backends 解析PHP負載平衡已經有1217次圍觀

http://coctec.com/docs/service/show-post-40528.html