【简介】
lighttpd提供了一种外部程序调用的接口,即FastCGI接口。这是一种独立于平台和服务器的接口,它介于Web应用程序和Web服务器之间。关于FastCGI接口的具体内容可以在其官网上找到。
这就意味着能够在Apache服务器上运行的FastCGI程序,也一定可以无缝的在lighttpd上使用。
【FastCGI广告时间】
1 就像CGI一样,FastCGI也是独立于编程语言的。
2 就像CGI一样,FastCGI程序运行在完全独立于核心Web Server之外的进程中,和API方式相比,提供了很大的安全性。(API会将程序代码与核心Web Server挂接在一起,这就意味着基于问题API的应用程序可能会使整个Web Server或另一个应用程序崩溃;一个恶意API还可以从核心Web Server或另一个应用程序中盗取安全密钥)
3 虽然FastCGI不能一夜之间复制CGI的所有功能,但是FastCGI一直宣扬开放,这也使得我们拥有很多免费的FastCGI应用程序库(C/C++、Java、Perl、TCL)和免费的Server模块(Apache、ISS、Lighttpd)。
4 就像CGI一样,FastCGI并不依附于任何Web Server的内部架构,因此即使Server的技术实现变动,FastCGI仍然非常稳定;而API设计是反映Web Server内部架构的,因此,一旦架构改变,API要随之变动。
5 FastCGI程序可以运行在任何机器上,完全可以和Web Server不在一台机器上。这种分布式计算的思想可以确保可扩展性、提高系统可用性和安全性。
6 CGI程序主要是对HTTP请求做计算处理,而FastCGI却还可以做得更多,例如模块化认证、授权检查、数据类型转换等等。在未来,FastCGI还会有能力扮演更多角色。
7 FastCGI移除了CGI程序的许多弊端。例如,针对每一个新请求,WebServer都必须重启CGI程序来处理新请求,这导致WebServer的性能会大受影响。而FastCGI通过保持进程处理运行状态并持续处理请求的方式解决了该问题,这就将进程创建和销毁的时间节省了出来。
8 CGI程序需要通过管道(pipe)方式与Web Server通信,而FastCGI则是通过Unix-Domain-Sockets或TCP/IP方式来实现与Web Server的通信。这确保了FastCGI可以运行在Web Server之外的服务器上。FastCGI提供了FastCGI负载均衡器,它可以有效控制多个独立的FastCGI Server的负载,这种方式比load-balancer+apache+mod_php方式能够承担更多的流量。
【fastcgi模块】
若要lighttpd支持fastcgi,则需要配置如下内容:
在fastcgi.conf中配置
server.modules += ( "mod_fastcgi" )
及
在module.conf中配置
include "conf.d/fastcgi.conf"
【fastcgi配置选项】
lighttpd通过fastcgi模块的方式实现了对fastcgi的支持,并且在配置文件中提供了三个相关的选项:
1 fastcgi.debug
可以设置一个从0到65535的值,用于设定FastCGI模块的调试等级。当前仅有0和1可用。1表示开启调试(会输出调试信息),0表示禁用。例如:
fastcgi.debug = 1
2 fastcgi.map-extentsions
同一个fastcgi server能够映射多个扩展名,如.php3和.php4都对应.php。例如:
fastcgi.map-extensions = ( ".php3" => ".php" )
or for multiple
fastcgi.map-extensions = ( ".php3" => ".php", ".php4" => ".php" )
3 fastcgi.server
这个配置是告诉Web Server将FastCGI请求发送到哪里,其中每一个文件扩展名可以处理一个类型的请求。负载均衡器可以实现对同一扩展名的多个对象的负载均衡。
fastcgi.server的结构语法如下:
( <extension> => ( [ <name> => ] ( # Be careful: lighty does *not* warn you if it doesn't know a specified option here (make sure you have no typos) "host" => <string> , "port" => <integer> , "socket" => <string>, # either socket or host+port "bin-path" => <string>, # optional "bin-environment" => <array>, # optional "bin-copy-environment" => <array>, # optional "mode" => <string>, # optional "docroot" => <string> , # optional if "mode" is not "authorizer" "check-local" => <string>, # optional "max-procs" => <integer>, # optional - when omitted, default is 4 "broken-scriptfilename" => <boolean>, # optional "kill-signal" => <integer>, # optional, default is SIGTERM(15) (v1.4.14+) ), ( "host" => ... ) ) )
其中:
如果bin-path被设置了,那么:
【举例】
多个文件扩展名对应一台主机:
fastcgi.server = ( ".php" => (( "host" => "127.0.0.1", "port" => 1026, "bin-path" => "/usr/local/bin/php" )), ".php4" => (( "host" => "127.0.0.1", "port" => 1026 )) )
使用前缀来对应主机:
fastcgi.server = ( "/remote_scripts/" => (( "host" => "192.168.0.3", "port" => 9000, "check-local" => "disable", "docroot" => "/" # remote server may use # it's own docroot )) )
如果有一个请求“http://my.example.org/remote_scripts/test.cgi”,那么server会将其转发给192.168.0.3的9000端口,并且SCRIPT_NAME会被赋值为“/remote_scripts/test.cgi”。如果所设置的handler的末尾不是“/”,那么会被认为是一个文件。
【负载均衡】
FastCGI模块提供了一种在多台FastCGI服务器间负载均衡的方法。
例如:
fastcgi.server = ( ".php" => ( ( "host" => "10.0.0.2", "port" => 1030 ), ( "host" => "10.0.0.3", "port" => 1030 ) ) )
为了更好的理解负载均衡实现的原理,建议你置fastcgi.debug为1。即使对于本机的多个FastCGI,你也会获得如下输出:
proc: 127.0.0.1 1031 1 1 1 31454 proc: 127.0.0.1 1028 1 1 1 31442 proc: 127.0.0.1 1030 1 1 1 31449 proc: 127.0.0.1 1029 1 1 2 31447 proc: 127.0.0.1 1026 1 1 2 31438 got proc: 34 31454 release proc: 40 31438 proc: 127.0.0.1 1026 1 1 1 31438 proc: 127.0.0.1 1028 1 1 1 31442 proc: 127.0.0.1 1030 1 1 1 31449 proc: 127.0.0.1 1031 1 1 2 31454 proc: 127.0.0.1 1029 1 1 2 31447
上述信息显示出了IP地址,端口号、当前链接数(也就是负载)(倒数第二列)、进程ID(倒数第一列)等等。整个输出信息总是以负载域来从小到大排序的。
【FastCGI和PHP】
在你编译PHP时,需要去除类似“–with-apxs/–with-apxs2”等选项,而要加入如下选项:
$ ./configure \ --enable-fastcgi \ --enable-force-cgi-redirect \ ...
这样,PHP才会支持CGI方式。在安装结束后,可以这样检查:
$ php -v PHP 4.3.3RC2-dev (cgi-fcgi) (built: Oct 19 2003 23:19:17)
其中最重要的部分是(cgi-fcgi)
在lighttpd中配置fastcgi.server时,可以有多种选择:
最简方法:
fastcgi.server = ( ".php" => (( "socket" => "/tmp/php-fastcgi.socket", "bin-path" => "/usr/local/bin/php" )) )
中等方法(可以通过两个环境变量来控制workder的数量,以及一个workder可以承受的请求数目):
fastcgi.server = ( ".php" => (( "socket" => "/tmp/php-fastcgi.socket", "bin-path" => "/usr/local/bin/php", "bin-environment" => ( "PHP_FCGI_CHILDREN" => "16", "PHP_FCGI_MAX_REQUESTS" => "10000" ) )) )
安全方法(可以在环境变量方面加强安全性):
fastcgi.server = ( ".php" => (( "socket" => "/tmp/php-fastcgi.socket", "bin-path" => "/usr/local/bin/php", "bin-environment" => ( "PHP_FCGI_CHILDREN" => "16", "PHP_FCGI_MAX_REQUESTS" => "10000" ), "bin-copy-environment" => ( "PATH", "SHELL", "USER" ) )) )
如果你希望在PHP编程中使用到PATH_INFO和PHP_SELF两个全局变量,那么你需要做两件事,
第一,在php.ini中设置:
cgi.fix_pathinfo = 1
第二,在fasctcgi.server中添加设置broken-scriptfilename:
fastcgi.server = ( ".php" => (( "socket" => "/tmp/php-fastcgi.socket", "bin-path" => "/usr/local/bin/php", "bin-environment" => ( "PHP_FCGI_CHILDREN" => "16", "PHP_FCGI_MAX_REQUESTS" => "10000" ), "bin-copy-environment" => ( "PATH", "SHELL", "USER" ), "broken-scriptfilename" => "enable" )) )
【python FastCGI和flup】
配置如下:
fastcgi.server = ( ".py" => ( "python-fcgi" => ( "socket" => socket_dir + "fastcgi.python.socket", "bin-path" => "test.py", "check-local" => "disable", "max-procs" => 1, ) ))
而test.py内容如下:
#!/usr/bin/python2.5 def myapp(environ, start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) return ['Hello World!\n'] if __name__ == '__main__': from flup.server.fcgi import WSGIServer WSGIServer(myapp).run()
[参考文献]
http://redmine.lighttpd.net/projects/1/wiki/Docs:ModFastCGI
http://www.fastcgi.com
谢谢!
roc