ArthurXF从业10年的CTO,受上海非凡学院邀请,进行PHP,CSS,FREEBSD等网络技能授课培训,有意向参加的,请联系.
prefork模式
这个多路处理模块(MPM)实现了一个非线程型的、预派生的web服务器,它的工作方式类似于Apache 1.3。它适合于没有线程安全库,需要避免线程兼容性问题的系统。它是要求将每个请求相互独立的情况下最好的MPM,这样若一个请求出现问题就不会影响到其他请求。

这个MPM具有很强的自我调节能力,只需要很少的配置指令调整。最重要的是将MaxClients设置为一个足够大的数值以处理潜在的请求高峰,同时又不能太大,以致需要使用的内存超出物理内存的大小。

worker模式
此多路处理模块(MPM)使网络服务器支持混合的多线程多进程。由于使用线程来处理请求,所以可以处理海量请求,而系统资源的开销小于基于进程的MPM。但是,它也使用了多进程,每个进程又有多个线程,以获得基于进程的MPM的稳定性。

控制这个MPM的最重要的指令是,控制每个子进程允许建立的线程数的ThreadsPerChild指令,和控制允许建立的总线程数的MaxClients指令。


prefork和worker模式的切换
1.将当前的prefork模式启动文件改名
mv httpd httpd.prefork
2.将worker模式的启动文件改名
mv httpd.worker httpd
3.修改Apache配置文件
vi /usr/local/apache2/conf/extra/httpd-mpm.conf
找到里边的如下一段,可适当修改负载等参数:

StartServers 2
MaxClients 150
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestsPerChild 0

4.重新启动服务
/usr/local/apache2/bin/apachectl restart
即可换成worker方式启动apache2

处于稳定性和安全性考虑,不建议更换apache2的运行方式,使用系统默认prefork即可。另外很多php模块不能工作在worker模式下,例如redhat linux自带的php也不能支持线程安全。所以最好不要切换工作模式。

prefork和worker模式的比较
prefork模式使用多个子进程,每个子进程只有一个线程。每个进程在某个确定的时间只能维持一个连接。在大多数平台上,Prefork MPM在效率上要比Worker MPM要高,但是内存使用大得多。prefork的无线程设计在某些情况下将比worker更有优势:它可以使用那些没有处理好线程安全的第三方模块,并且对于那些线程调试困难的平台而言,它也更容易调试一些。

worker模式使用多个子进程,每个子进程有多个线程。每个线程在某个确定的时间只能维持一个连接。通常来说,在一个高流量的HTTP服务器上,Worker MPM是个比较好的选择,因为Worker MPM的内存使用比Prefork MPM要低得多。但worker MPM也由不完善的地方,如果一个线程崩溃,整个进程就会连同其所有线程一起”死掉”.由于线程共享内存空间,所以一个程序在运行时必须被系统识别为”每个线程都是安全的”。

总的来说,prefork方式速度要稍高于worker,然而它需要的cpu和memory资源也稍多于woker。

prefork模式配置详解

ServerLimit 256
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 256
MaxRequestsPerChild 0

ServerLimit
默认的MaxClient最大是256个线程,如果想设置更大的值,就的加上ServerLimit这个参数。20000是ServerLimit这个参数的最大值。如果需要更大,则必须编译apache,此前都是不需要重新编译Apache。
生效前提:必须放在其他指令的前面

StartServers
指定服务器启动时建立的子进程数量,prefork默认为5。

MinSpareServers
指定空闲子进程的最小数量,默认为5。如果当前空闲子进程数少于MinSpareServers ,那么Apache将以最大每秒一个的速度产生新的子进程。此参数不要设的太大。

MaxSpareServers
设置空闲子进程的最大数量,默认为10。如果当前有超过MaxSpareServers数量的空闲子进程,那么父进程将杀死多余的子进程。此参数不要设的太大。如果你将该指令的值设置为比MinSpareServers小,Apache将会自动将其修改成”MinSpareServers+1″。

MaxClients
限定同一时间客户端最大接入请求的数量(单个进程并发线程数),默认为256。任何超过MaxClients限制的请求都将进入等候队列,一旦一个链接被释放,队列中的请求将得到服务。要增大这个值,你必须同时增大ServerLimit。

MaxRequestsPerChild
每个子进程在其生存期内允许伺服的最大请求数量,默认为10000.到达MaxRequestsPerChild的限制后,子进程将会结束。如果MaxRequestsPerChild为”0″,子进程将永远不会结束。将MaxRequestsPerChild设置成非零值有两个好处:
1.可以防止(偶然的)内存泄漏无限进行,从而耗尽内存。
2.给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量。

worker模式配置详解

StartServers 2
MaxClients 150
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestsPerChild 0


StartServers
服务器启动时建立的子进程数,默认值是”3″。

MaxClients
允许同时伺服的最大接入请求数量(最大线程数量)。任何超过MaxClients限制的请求都将进入等候队列。默认值是”400″,16(ServerLimit)乘以25(ThreadsPerChild)的结果。因此要增加MaxClients的时候,你必须同时增加ServerLimit的值。

MinSpareThreads
最小空闲线程数,默认值是”75″。这个MPM将基于整个服务器监视空闲线程数。如果服务器中总的空闲线程数太少,子进程将产生新的空闲线程。

MaxSpareThreads
设置最大空闲线程数。默认值是”250″。这个MPM将基于整个服务器监视空闲线程数。如果服务器中总的空闲线程数太多,子进程将杀死多余的空闲线程。MaxSpareThreads的取值范围是有限制的。Apache将按照如下限制自动修正你设置的值:worker要求其大于等于MinSpareThreads加上ThreadsPerChild的和。

ThreadsPerChild
每个子进程建立的常驻的执行线程数。默认值是25。子进程在启动时建立这些线程后就不再建立新的线程了。

MaxRequestsPerChild
设置每个子进程在其生存期内允许伺服的最大请求数量。到达MaxRequestsPerChild的限制后,子进程将会结束。如果MaxRequestsPerChild为”0″,子进程将永远不会结束。将MaxRequestsPerChild设置成非零值有两个好处:
1.可以防止(偶然的)内存泄漏无限进行,从而耗尽内存。
2.给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量。
注意对于KeepAlive链接,只有第一个请求会被计数。事实上,它改变了每个子进程限制最大链接数量的行为。


选择prefork还是worker可以在编译时使用–with-mpm=MPM参数指定,默认为prefork,preforkprefork采用预派生子进程方式,用单独的子进程来处理 不同的请求,进程之间彼此独立。在make编译和make install安装后,使用httpd -l来确定当前使用的MPM是prefork.c。查看httpd-mpm.conf配置文件,里面包含如下默认的配置段:

StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 150
MaxRequestsPerChild 0


prefork 控制进程在最初建立“StartServers”个子进程后,为了满足MinSpareServers设置的需要创建一个进程,等待一秒钟,继续创建两 个,再等待一秒钟,继续创建四个……如此按指数级增加创建的进程数,最多达到每秒32个,直到满足MinSpareServers设置的值为止。这种模式 可以不必在请求到来时再产生新的进程,从而减小了系统开销以增加性能。MaxSpareServers设置了最大的空闲进程数,如果空闲进程数大于这个 值,Apache会自动kill掉一些多余进程。这个值不要设得过大,但如果设的值比MinSpareServers小,Apache会自动把其调整为 MinSpareServers+1。如果站点负载较大,可考虑同时加大MinSpareServers和MaxSpareServers。 MaxRequestsPerChild设置的是每个子进程可处理的请求数。每个子进程在处理了“MaxRequestsPerChild”个请求后将自 动销毁。0意味着无限,即子进程永不销毁。虽然缺省设为0可以使每个子进程处理更多的请求,但如果设成非零值也有两点重要的好处:1、可防止意外的内存泄 漏。2、在服务器负载下降的时侯会自动减少子进程数。因此,可根据服务器的负载来调整这个值。MaxClients是这些指令中最为重要的一个,设定的是 Apache可以同时处理的请求,是对Apache性能影响最大的参数。其缺省值150是远远不够的,如果请求总数已达到这个值(可通过ps -ef|grep http|wc -l来确认),那么后面的请求就要排队,直到某个已处理请求完毕。这就是系统资源还剩下很多而HTTP访问却很慢的主要原因。虽然理论上这个值越大,可以 处理的请求就越多,但Apache默认的限制不能大于256。ServerLimit指令无须重编译Apache就可以加大MaxClients。

ServerLimit 10000
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 10000
MaxRequestsPerChild 0

Worker相对于prefork,worker全新的支持多线程和多进程混合模型的MPM。由于 使用线程来处理,所以可以处理相对海量的请求,而系统资源的开销要小于基于进程的服务器。但是,worker也使用了多进程,每个进程又生成多个线程,以 获得基于进程服务器的稳定性。在configure –with-mpm=worker后,进行make编译、make install安装。在缺省生成的httpd-mpm.conf中有以下默认配置段:

StartServers 2
MaxClients 150
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestsPerChild 0

Worker 由主控制进程生成“StartServers”个子进程,每个子进程中包含固定的ThreadsPerChild线程数,各个线程独立地处理请求。同样, 为了不在请求到来时再生成线程,MinSpareThreads和MaxSpareThreads设置了最少和最多的空闲线程数;而MaxClients 设置了同时连入的clients最大总数。如果现有子进程中的线程总数不能满足负载,控制进程将派生新的子进程。MinSpareThreads和 MaxSpareThreads的最大缺省值分别是75和250。这两个参数对Apache的性能影响并不大,可以按照实际情况相应调节。 ThreadsPerChild是worker MPM中与性能相关最密切的指令。ThreadsPerChild的最大缺省值是64,如果负载较大,64也是不够的。这时要显式使用 ThreadLimit指令,它的最大缺省值是20000。Worker模式下所能同时处理的请求总数是由子进程总数乘以ThreadsPerChild 值决定的,应该大于等于MaxClients。如果负载很大,现有的子进程数不能满足时,控制进程会派生新的子进程。默认最大的子进程总数是16,加大时 也需要显式声明ServerLimit(最大值是20000)。需要注意的是,如果显式声明了ServerLimit,那么它乘以 ThreadsPerChild的值必须大于等于MaxClients,而且MaxClients必须是ThreadsPerChild的整数倍,否则 Apache将会自动调节到一个相应值。

ServerLimit 25
ThreadLimit 200
StartServers 3
MaxClients 2000
MinSpareThreads 50
MaxSpareThreads 200
ThreadsPerChild 100
MaxRequestsPerChild 0


2.要加到多少?

连接数理论上当然是支持越大越好,但要在服务器的能力范围内,这跟服务器的CPU、内存、带宽等都有关系。

查看当前的连接数可以用:
ps aux | grep httpd | wc -l

或:
pgrep httpd|wc -l

计算httpd占用内存的平均数:
ps aux|grep -v grep|awk '/httpd/{sum+=$6;n++};END{print sum/n}'

由于基本都是静态页面,CPU消耗很低,每进程占用内存也不算多,大约200K。

服务器内存有2G,除去常规启动的服务大约需要500M(保守估计),还剩1.5G可用,那么理论上可以支持1.5*1024*1024*1024/200000 = 8053.06368

约8K个进程,支持2W人同时访问应该是没有问题的(能保证其中8K的人访问很快,其他的可能需要等待1、2秒才能连上,而一旦连上就会很流畅)


   ServerLimit         10000
   StartServers          10
   MinSpareServers       10
   MaxSpareServers      20
   MaxClients          10000
   MaxRequestsPerChild  100

注意,MaxClients默认最大为250,若要超过这个值就要显式设置ServerLimit,且ServerLimit要放在MaxClients之前,值要不小于MaxClients,不然重启httpd时会有提示。

重启httpd后,通过反复执行pgrep httpd|wc -l 来观察连接数,可以看到连接数在达到MaxClients的设值后不再增加,但此时访问网站也很流畅,那就不用贪心再设置更高的值了,不然以后如果网站访问突增不小心就会耗光服务器内存,可根据以后访问压力趋势及内存的占用变化再逐渐调整,直到找到一个最优的设置值。

(MaxRequestsPerChild不能设置为0,可能会因内存泄露导致服务器崩溃)

更佳最大值计算的公式:

apache_max_process_with_good_perfermance < (total_hardware_memory / apache_memory_per_process ) * 2
apache_max_process = apache_max_process_with_good_perfermance * 1.5

目标重写设置说明
规范化URLRewriteRule ^/~([^/]+)/?(.*) /u/$1/$2 [R] 将/~user重写为/u/user的形式
 RewriteRule ^/([uge])/([^/]+)$ /$1/$2/ [R]将/u/user末尾漏掉的/补上
   
规范化HostNameRewriteCond %{HTTP_HOST} !^fully\.qualified\.domain\.name [NC]域名不合格
 RewriteCond %{HTTP_HOST} !^$不空
 RewriteCond %{SERVER_PORT} !^80$不是80端口
 RewriteRule ^/(.*) http://fully.qualified.domain.name:%{SERVER_PORT}/$1 [L,R]重写
 RewriteCond %{HTTP_HOST} !^fully\.qualified\.domain\.name [NC] 
 RewriteCond %{HTTP_HOST} !^$ 
 RewriteRule ^/(.*) http://fully.qualified.domain.name/$1 [L,R] 
   
URL根目录转移RewriteEngine on 
 RewriteRule ^/$ /e/www/ [R]从/移到/e/www/
   
末尾目录补斜线RewriteEngine on 
(目录范围内)RewriteBase /~quux/ 
 RewriteRule ^foo$ foo/ [R]/~quux/foo是一个目录,补/
   
 RewriteEngine on 
 RewriteBase /~quux/ 
 RewriteCond %{REQUEST_FILENAME} -d如果请文件名是个目录
 RewriteRule ^(.+[^/])$ $1/ [R]URL末尾不是斜线时补上
   
Web集群RewriteEngine on 
 RewriteMap user-to-host txt:/path/to/map.user-to-host用户-服务器映射
 RewriteMap group-to-host txt:/path/to/map.group-to-host组-服务器映射
 RewriteMap entity-to-host txt:/path/to/map.entity-to-host实体-服务器映射
 RewriteRule ^/u/([^/]+)/?(.*) http://${user-to-host:$1|server0}/u/$1/$2用户均衡
 RewriteRule ^/g/([^/]+)/?(.*) http://${group-to-host:$1|server0}/g/$1/$2组均衡
 RewriteRule ^/e/([^/]+)/?(.*) http://${entity-to-host:$1|server0}/e/$1/$2实体均衡
 RewriteRule ^/([uge])/([^/]+)/?$ /$1/$2/.www/ 
 RewriteRule ^/([uge])/([^/]+)/([^.]+.+) /$1/$2/.www/$3\  
   
URL根目录搬迁RewriteEngine on 
 RewriteRule ^/~(.+) http://newserver/~$1 [R,L] 到其它服务器
   
所用户名首字母分RewriteEngine on 
 RewriteRule ^/~(([a-z])[a-z0-9]+)(.*) /home/$2/$1/.www$3 内一层括号为$2
   
NCSA imagemap移RewriteEngine on 
植为mod_imapRewriteRule ^/cgi-bin/imagemap(.*) $1 [PT]  
   
多目录查找资源RewriteEngine on 
 # first try to find it in custom/... 
 RewriteCond /your/docroot/dir1/%{REQUEST_FILENAME} -f 
 RewriteRule ^(.+) /your/docroot/dir1/$1 [L] 
 # second try to find it in pub/... 
 RewriteCond /your/docroot/dir2/%{REQUEST_FILENAME} -f 
 RewriteRule ^(.+) /your/docroot/dir2/$1 [L] 
 # else go on for other Alias or ScriptAlias directives, 
 RewriteRule ^(.+) - [PT]  
   
据URL设置环境变量RewriteEngine on 
 RewriteRule ^(.*)/S=([^/]+)/(.*) $1/$3 [E=STATUS:$2]  
   
虚拟主机RewriteEngine on 
 RewriteCond %{HTTP_HOST} ^www\.[^.]+\.host\.com$基于用户名
 RewriteRule ^(.+) %{HTTP_HOST}$1 [C] 
 RewriteRule ^www\.([^.]+)\.host\.com(.*) /home/$1$2  
   
内外人有别RewriteEngine on 
 RewriteCond %{REMOTE_HOST} !^.+\.ourdomain\.com$基于远程主机
 RewriteRule ^(/~.+) http://www.somewhere.com/$1 [R,L]  
   
错误重定向RewriteEngine on 
 RewriteCond /your/docroot/%{REQUEST_FILENAME} !-f不是regular文件
 RewriteRule ^(.+) http://webserverB.dom/$1  
   
程序处理特殊协议RewriteRule ^xredirect:(.+) /path/to/nph-xredirect.cgi/$1 \Xredirect协议
 [T=application/x-httpd-cgi,L]  
   
最近镜像下载RewriteEngine on 
 RewriteMap multiplex txt:/path/to/map.cxan顶级域名与最近ftp服务器映射
 RewriteRule ^/CxAN/(.*) %{REMOTE_HOST}::$1 [C] 
 RewriteRule ^.+\.([a-zA-Z]+)::(.*)$ ${multiplex:$1|ftp.default.dom}$2 [R,L] 据顶级域名不同提供不同的FTP服务器
   
基于时间重写RewriteEngine on 
 RewriteCond %{TIME_HOUR}%{TIME_MIN} >0700 
 RewriteCond %{TIME_HOUR}%{TIME_MIN} <1900 
 RewriteRule ^foo\.html$ foo.day.html白天为早晚7点间
 RewriteRule ^foo\.html$ foo.night.html 其余为夜间
   
向前兼容扩展名RewriteEngine on 
 RewriteBase /~quux/ 
 # parse out basename, but remember the fact 
 RewriteRule ^(.*)\.html$ $1 [C,E=WasHTML:yes] 
 # rewrite to document.phtml if exists 
 RewriteCond %{REQUEST_FILENAME}.phtml -f如果存在$1.phtml则重写
 RewriteRule ^(.*)$ $1.phtml [S=1] 
 # else reverse the previous basename cutout 
 RewriteCond %{ENV:WasHTML} ^yes$如果不存在$1.phtml,则保持不变
 RewriteRule ^(.*)$ $1.html  
   
文件改名(目录级)RewriteEngine on内部重写
 RewriteBase /~quux/ 
 RewriteRule ^foo\.html$ bar.html  
   
 RewriteEngine on重定向由客户端再次提交
 RewriteBase /~quux/ 
 RewriteRule ^foo\.html$ bar.html [R]  
   
据浏览器类型重写RewriteCond %{HTTP_USER_AGENT} ^Mozilla/3.* 
 RewriteRule ^foo\.html$ foo.NS.html [L] 
 RewriteCond %{HTTP_USER_AGENT} ^Lynx/.* [OR] 
 RewriteCond %{HTTP_USER_AGENT} ^Mozilla/[12].* 
 RewriteRule ^foo\.html$ foo.20.html [L] 
 RewriteRule ^foo\.html$ foo.32.html [L]  
   
动态镜像远程资源RewriteEngine on 
 RewriteBase /~quux/ 
 RewriteRule ^hotsheet/(.*)$ http://www.tstimpreso.com/hotsheet/$1 [P]利用了代理模块
   
 RewriteEngine on 
 RewriteBase /~quux/ 
 RewriteRule ^usa-news\.html$ http://www.quux-corp.com/news/index.html [P] 
   
反向动态镜像RewriteEngine on 
 RewriteCond /mirror/of/remotesite/$1 -U  
 RewriteRule ^http://www\.remotesite\.com/(.*)$ /mirror/of/remotesite/$1  
   
负载均衡RewriteEngine on利用代理实现round-robin效果
 RewriteMap lb prg:/path/to/lb.pl 
 RewriteRule ^/(.+)$ ${lb:$1} [P,L] 
   
 #!/path/to/perl 
 $| = 1; 
 $name = "www"; # the hostname base 
 $first = 1; # the first server (not 0 here, because 0 is myself)  
 $last = 5; # the last server in the round-robin 
 $domain = "foo.dom"; # the domainname 
 $cnt = 0; 
 while (<STDIN>) { 
 $cnt = (($cnt+1) % ($last+1-$first)); 
 $server = sprintf("%s%d.%s", $name, $cnt+$first, $domain); 
 print "http://$server/$_"; 
 } 
 ##EOF## 
   
静态页面变脚本RewriteEngine on 
 RewriteBase /~quux/ 
 RewriteRule ^foo\.html$ foo.cgi [T=application/x-httpd-cgi]  
   
阻击机器人RewriteCond %{HTTP_USER_AGENT} ^NameOfBadRobot.*  
 RewriteCond %{REMOTE_ADDR} ^123\.45\.67\.[8-9]$ 
 RewriteRule ^/~quux/foo/arc/.+ - [F]  
   
阻止盗连你的图片RewriteCond %{HTTP_REFERER} !^$  
 RewriteCond %{HTTP_REFERER} !^http://www.quux-corp.de/~quux/.*$ [NC]自己的连接可不能被阻止
 RewriteRule .*\.gif$ - [F] 
   
 RewriteCond %{HTTP_REFERER} !^$  
 RewriteCond %{HTTP_REFERER} !.*/foo-with-gif\.html$ 
 RewriteRule ^inlined-in-foo\.gif$ - [F] 
   
拒绝某些主机访问RewriteEngine on 
 RewriteMap hosts-deny txt:/path/to/hosts.deny 
 RewriteCond ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND} !=NOT-FOUND [OR] 
 RewriteCond ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND} !=NOT-FOUND 
 RewriteRule ^/.* - [F]  
   
用户授权RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend1@client1.quux-corp\.com$  
 RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend2@client2.quux-corp\.com$  
 RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend3@client3.quux-corp\.com$  
 RewriteRule ^/~quux/only-for-friends/ - [F]  
   
外部重写程序模板RewriteEngine on 
 RewriteMap quux-map prg:/path/to/map.quux.pl 
 RewriteRule ^/~quux/(.*)$ /~quux/${quux-map:$1} 
   
 #!/path/to/perl 
 $| = 1; 
 while (<>) { 
 s|^foo/|bar/|; 
 print $_; 
 } 
   
搜索引擎友好RewriteRule ^/products$ /content.php  
 RewriteRule ^/products/([0-9]+)$ /content.php?id=$1  
 RewriteRule ^/products/([0-9]+),([ad]*),([0-9]{0,3}),([0-9]*),([0-9]*$) /marso/content.php?id=$1&sort=$2&order=$3&start=$4

Tags: ,
  我们都知道,在windows下的apache系统在访问网址时,最后的地址是个目录,apache系统能够自动加个/线,而Linux下的apache不能自动加。

例如:
http://biweb.cn/bbs
转换为
http://biweb.cn/bbs/

在windows下是可以自动转换的,但是在liunx下或者UNix下是不行的,或报404错误。

那么我们怎么在liunx下修正这个问题呢。只需要在apache的httpd.conf中加入下面的代码,前提是
LoadModule rewrite_module modules/mod_rewrite.so要打开。
代码如下:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/])$ $1/ [R]

加入之后,重启apache,就可以正常访问了。是不是挺方便?呵呵。请访问biweb.cn,下载史上最强的WMS系统建网站,你会觉得无比轻松。
Tags: ,
apxs是一个为Apache HTTP服务器编译和安装扩展模块的工具,用于编译一个或多个源程序或目标代码文件为动态共享对象,使之可以用由mod_so提供的LoadModule指令在运行时加载到Apache服务器中。

因此,要使用这个扩展机制,你的平台必须支持DSO特性,而且Apache httpd必须内建了mod_so模块。apxs工具能自动探测是否具备这样的条件,你也可以自己用这个命令手动探测:

$ httpd -l

该命令的输出列表中应该有mod_so模块。如果所有这些条件均已具备,则可以很容易地借助apxs安装你自己的DSO模块以扩展Apache服务器的功能:

$ apxs -i -a -c mod_foo.c
gcc -fpic -DSHARED_MODULE -I/path/to/apache/include -c mod_foo.c
ld -Bshareable -o mod_foo.so mod_foo.o
cp mod_foo.so /path/to/apache/modules/mod_foo.so
chmod 755 /path/to/apache/modules/mod_foo.so
[activating module 'foo' in /path/to/apache/etc/httpd.conf]
$ apachectl restart
/path/to/apache/sbin/apachectl restart: httpd not running, trying to start
[Tue Mar 31 11:27:55 1998] [debug] mod_so.c(303): loaded module foo_module
/path/to/apache/sbin/apachectl restart: httpd started
$ _

其中的参数files可以是任何C源程序文件(.c)、目标代码文件(.o)、甚至是一个库(.a)。apxs工具会根据其后缀自动编译C源程序或者连接目标代码和库。但是,使用预编译的目标代码时,必须保证它们是地址独立代码(PIC),使之能被动态地加载。如果使用GCC编译,则应该使用 -fpic 参数;如果使用其他C编译器,则应该查阅其手册,为apxs使用相应的编译参数。

有关Apache对DSO的支持的详细信息,可以阅读mod_so文档,或者直接阅读src/modules/standard/mod_so.c源程序。

语法
apxs -g [ -S name=value ] -n modname

apxs -q [ -S name=value ] query ...

apxs -c [ -S name=value ] [ -o dsofile ] [ -I incdir ] [ -D name=value ] [ -L libdir ] [ -l libname ] [ -Wc,compiler-flags ] [ -Wl,linker-flags ] files ...

apxs -i [ -S name=value ] [ -n modname ] [ -a ] [ -A ] dso-file ...

apxs -e [ -S name=value ] [ -n modname ] [ -a ] [ -A ] dso-file ...

选项
一般选项
-n modname
它明确设置了 -i(安装)和 -g(模板生成)选项的模块名称。对 -g 选项,它是必须的;对 -i 选项,apxs工具会根据源代码判断,或(在失败的情况下)按文件名推测出这个模块的名称。
查询选项
-q
查询某种apxs设置的信息。该选项的query参数可以是下列一个或多个字符串:CC, CFLAGS, CFLAGS_SHLIB, INCLUDEDIR, LD_SHLIB, LDFLAGS_SHLIB, LIBEXECDIR, LIBS_SHLIB, SBINDIR, SYSCONFDIR, TARGET 。
这个参数用于手动查询某些设置。比如,要手动处理Apache的C头文件,可以在Makefile中使用:

INC=-I`apxs -q INCLUDEDIR`

配置选项
-S name=value
此选项可以改变apxs的上述设置。
模板生成选项
-g
此选项生成一个名为name的子目录(见选项 -n)和其中的两个文件:一个是名为mod_name.c的样板模块源程序,可以用来建立你自己的模块,或是学习使用apxs机制的良好开端;另一个则是对应的Makefile ,用于编译和安装此模块。
DSO编译选项
-c
此选项表示需要执行编译操作。它首先会编译C源程序(.c)files为对应的目标代码文件(.o),然后连接这些目标代码和files中其余的目标代码文件(.o和.a),以生成动态共享对象dsofile 。如果没有指定 -o 选项,则此输出文件名由files中的第一个文件名推测得到,也就是默认为mod_name.so 。
-o dsofile
明确指定所建立的动态共享对象的文件名,它不能从files文件列表中推测得到。如果没有明确指定,则其文件名将为mod_unknown.so 。
-D name=value
此选项直接传递到给编译命令,用于增加自定义的编译变量。
-I incdir
此选项直接传递到给编译命令,用于增加自定义的包含目录。
-L libdir
此选项直接传递到给连接命令,用于增加自定义的库文件目录。
-l libname
此选项直接传递到给连接命令,用于增加自定义的库文件。
-Wc,compiler-flags
此选项用于向编译命令 libtool --mode=compile 中附加compiler-flags ,以增加编译器特有的选项。
-Wl,linker-flags
此选项用于向连接命令 libtool --mode=link 中附加linker-flags ,以增加连接器特有的选项。
DSO的安装和配置选项
-i
此选项表示需要执行安装操作,以安装一个或多个动态共享对象到服务器的modules目录中。
-a
此选项自动增加一个LoadModule行到httpd.conf文件中,以激活此模块,或者,如果此行已经存在,则启用之。
-A
与 -a 选项类似,但是它增加的LoadModule命令有一个井号前缀(#),即此模块已经准备就绪但尚未启用。
-e
表示需要执行编辑操作,它可以与 -a 和 -A 选项配合使用,与 -i 操作类似,修改Apache的httpd.conf文件,但是并不安装此模块。
举例
假设有一个扩展Apache功能的模块mod_foo.c ,使用下列命令,可以将C源程序编译为共享模块,以在运行时加载到Apache服务器中:

$ apxs -c mod_foo.c
/path/to/libtool --mode=compile gcc ... -c mod_foo.c
/path/to/libtool --mode=link gcc ... -o mod_foo.la mod_foo.slo
$ _

然后,必须修改Apache的配置,以确保有一个LoadModule指令来加载此共享对象。为了简化这一步骤,apxs可以自动进行该操作,以安装此共享对象到"modules"目录,并更新httpd.conf文件,命令如下:

$ apxs -i -a mod_foo.la
/path/to/instdso.sh mod_foo.la /path/to/apache/modules
/path/to/libtool --mode=install cp mod_foo.la /path/to/apache/modules ... chmod 755 /path/to/apache/modules/mod_foo.so
[activating module 'foo' in /path/to/apache/conf/httpd.conf]
$ _

如果配置文件中尚不存在,会增加下列的行:

LoadModule foo_module modules/mod_foo.so

如果你希望默认禁用此模块,可以使用 -A 选项,即:

$ apxs -i -A mod_foo.c

要快速测试apxs机制,可以建立一个Apache模块样板及其对应的Makefile :

$ apxs -g -n foo
Creating [DIR] foo
Creating [FILE] foo/Makefile
Creating [FILE] foo/modules.mk
Creating [FILE] foo/mod_foo.c
Creating [FILE] foo/.deps
$ _

然后,立即可以编译此样板模块为共享对象并加载到Apache服务器中:

$ cd foo
$ make all reload
apxs -c mod_foo.c
/path/to/libtool --mode=compile gcc ... -c mod_foo.c
/path/to/libtool --mode=link gcc ... -o mod_foo.la mod_foo.slo
apxs -i -a -n "foo" mod_foo.la
/path/to/instdso.sh mod_foo.la /path/to/apache/modules
/path/to/libtool --mode=install cp mod_foo.la /path/to/apache/modules ... chmod 755 /path/to/apache/modules/mod_foo.so
[activating module 'foo' in /path/to/apache/conf/httpd.conf]
apachectl restart
/path/to/apache/sbin/apachectl restart: httpd not running, trying to start
[Tue Mar 31 11:27:55 1998] [debug] mod_so.c(303): loaded module foo_module
/path/to/apache/sbin/apachectl restart: httpd started
$ _
Tags: ,
# prefork MPM
# StartServers: number of server processes to start
# MinSpareServers: minimum number of server processes which are kept spare
# MaxSpareServers: maximum number of server processes which are kept spare
# MaxClients: maximum number of server processes allowed to start
# MaxRequestsPerChild: maximum number of requests a server process serves

StartServers     10
MinSpareServers   10
MaxSpareServers   15
ServerLimit     2000
MaxClients      2000
MaxRequestsPerChild 10000

  查看httpd进程数(即prefork模式下Apache能够处理的并发请求数):

  Linux命令:

ps -ef | grep httpd | wc -l

  返回结果示例:

  1388

  表示Apache能够处理1388个并发请求,这个值Apache可根据负载情况自动调整,我这组服务器中每台的峰值曾达到过2002。

  查看Apache的并发请求数及其TCP连接状态:

  Linux命令:

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’

  (这条语句是从新浪互动社区事业部技术总监王老大那儿获得的,非常不错)

  返回结果示例:

  LAST_ACK 5

  SYN_RECV 30

  ESTABLISHED 1597

  FIN_WAIT1 51

  FIN_WAIT2 504

  TIME_WAIT 1057

  其中的SYN_RECV表示正在等待处理的请求数;ESTABLISHED表示正常数据传输状态;TIME_WAIT表示处理完毕,等待超时结束的请求数。

  关于TCP状态的变迁,可以从下图形象地看出:

  状态:描述

  CLOSED:无连接是活动的或正在进行

  LISTEN:服务器在等待进入呼叫

  SYN_RECV:一个连接请求已经到达,等待确认

  SYN_SENT:应用已经开始,打开一个连接

  ESTABLISHED:正常数据传输状态

  FIN_WAIT1:应用说它已经完成

  FIN_WAIT2:另一边已同意释放

  ITMED_WAIT:等待所有分组死掉

  CLOSING:两边同时尝试关闭

  TIME_WAIT:另一边已初始化一个释放

  LAST_ACK:等待所有分组死掉
Tags: , ,
分页: 2/3 第一页 上页 1 2 3 下页 最后页 [ 显示模式: 摘要 | 列表 ]