原讨论帖:http://www.iteye.com/topic/267429
dango的fastcgi模式有如下几个重要参数:
# protocol=PROTOCOL fcgi, scgi, ajp, ... (default fcgi) # host=HOSTNAME hostname to listen on.. # port=PORTNUM port to listen on. # socket=FILE UNIX socket to listen on. # method=IMPL prefork or threaded (default prefork) # maxrequests=NUMBER number of requests a child handles before it is # killed and a new child is forked (0 = no limit). # maxspare=NUMBER max number of spare processes / threads # minspare=NUMBER min number of spare processes / threads. # maxchildren=NUMBER hard limit number of processes / threads # daemonize=BOOL whether to detach from terminal. # pidfile=FILE write the spawned process-id to this file. # workdir=DIRECTORY change to this directory when daemonizing. # outlog=FILE write stdout to this file. # errlog=FILE write stderr to this file. # umask=UMASK umask to use when daemonizing (default 022).
protocol=PROTOCOL fcgi, scgi, ajp, ... (default fcgi) host=HOSTNAME hostname to listen on.. port=PORTNUM port to listen on. socket=FILE UNIX socket to listen on. method=IMPL prefork or threaded (default prefork) maxrequests=NUMBER number of requests a child handles before it is killed and a new child is forked (0 = no limit). maxspare=NUMBER max number of spare processes / threads minspare=NUMBER min number of spare processes / threads. maxchildren=NUMBER hard limit number of processes / threads daemonize=BOOL whether to detach from terminal. pidfile=FILE write the spawned process-id to this file. workdir=DIRECTORY change to this directory when daemonizing. outlog=FILE write stdout to this file. errlog=FILE write stderr to this file. umask=UMASK umask to use when daemonizing (default 022).
很多参数和tomcat中是一样的,主要有一个host,port,socket需要讲解一下,host和port我们知道应该是成对出现的,那么socket是什么呢,其实他们都是socket,只不过,host+port模式是tcp sock,而socket是unix sock,他们都是套接字,一个是操作系统本地的,一个是网络套接字而已。
在django中,lighttpd是不能去控制fcgi进程的产生或者消亡,这些工作都是flup,也就是python manager.py funfcgi 这个命令来产生一个父进程,然后,根据请求由这个父进程来动态的spawn子进程,不过,如果maxspare和minspare如果够大,比如说和maxchilden一样大,都是50 ,那么最大子进程数就是50,最大空闲进程数也是50,最小空闲进程数也是50,这样,父进程就不会不停的销毁和创建子进程了。这样其实也算是避免了动态的spawn
进程没有轻量不轻量的区别,你fork的时候开销都一样大。
所谓父子进程共享数据无非就是copy-on-write而已,这样仅仅可以节省一些物理内存,其他的好处并不大。
mod_rails就是采取这种方式,但这种方式的缺点我前面讲过了。
就我的观察来看,FastCGI进程内存开销最的部分还是内存堆,动辄100-200MB,甚至更多,你copy-on-write节省的共享代码段内存非常有限,也就10-20MB的样子
轻量级进程允许父子经常共享在内核中的数据结构,这些数据结构占的空间有限,应该不会有10-20m,所以一个是cow进程,父子进程读相同的物理页,这些fastcgi进程的物理页差不多应该是10m多
1、动态spawn进程的缺陷不在于worker进程撑死不撑死,而在于黑客可以很容易的通过瞬间发起大量请求来消耗干净CPU资源,让服务器失去响应,严重的甚至无法远程ssh上去。尽管你可能有一定的spare进程,但是这个在黑客的大量请求面前没什么效果。而静态spawn的好处就在于碰到这种情况最多网站动态请求无法响应,其他一切照常,你有充足的时间查看lighttpd的并发连接情况,找出肇事IP,然后从容的远程ssh上去封掉它。
事实上litespeed也可以通过lsapi来支持Ruby进程的动态spawn,但是经过我测试,是存在上述问题的。当然Apache的mod_rails也存在上述问题,而且更严重一些,特别是像一个比较大型的Rails应用,初始化的过程非常长,要初始化加载的数据很多,启动的时候CPU消耗是非常大的,这就是我为什么抛弃动态spawn的根本原因。
2、动态spawn超出请求数就自动销毁重起我觉得没什么意义
尽管这种自动重起机制可以一定程度上减轻内存泄漏带来的痛苦,但是如果我进程没有内存泄漏,跑的好好的,你干吗非要给我定期重起呢? 所以这种按照计数机制进行定期重起,还远不如我根据资源监控的状况来决定释放重起,如果你进程内存泄漏到一定程度,我就重起你,如果你不泄漏,我自然就不会重起你,这样的机制更合理。