Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1233107
  • 博文数量: 135
  • 博客积分: 10576
  • 博客等级: 上将
  • 技术积分: 1670
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-11 20:49
个人简介

不疯魔,不成活! --疯魔老杨(Crazy.LaoYang) http://www.inotes.cn/

文章分类

全部博文(135)

文章存档

2014年(4)

2012年(13)

2011年(5)

2010年(30)

2009年(56)

2008年(27)

分类: 系统运维

2012-09-10 13:26:53

Apache的工作模式有:beos,event,worker,prefork,mpmt_os2,但最常用的有两种:prefork和worker

prefork,是unix平台上默认MPM(MPM,Multi Processing Modules,多道处理模块。),使用多个子进程,每个子进程只有一个线程。每个进程在某个确定的时间只能维持一个连接,在大多数平台上,Prefork MPM在效率上要比Worker MPM要高,但是内存占用比较大。prefork的无线程设计在某些情况下将比worker更有优势:它可以使用那些没有处理好线程安全的第三方模块,并且对于那些线程调试困难的平台而言,它也更容易调试一些。
Prefork的工作原理是,控制进程在最初建立“StartServers”个子进程后,为了满足MinSpareServers设置的需要创建一个进程,等待一秒钟,继续创建两个,再等待一秒钟,继续创建四个......如此按指数级增加创建进程数,最大达到每秒32个,直到满足MinSpareServers设置为止。这就是预派生(prefork)的由来。这种模式可以不必在请求到来时再产生新的进程,从而减少系统开销以增加性能。
MaxSpareServers设置了最大的空闲进程数,如果空闲进程数大于这个值,Apache会自动kill掉一些多余进程。这个值不要设置得过大,但如果设的值比MinSpareServers小,Apache会自动将其调整为MinSpareServers+1.如果站点负载较大,可考虑同时加大MinSpareServers和MaxSpareServers。
MaxRequestsPerChild设置的是每个子进程可处理的请求数。每个子进程在处理了“MaxRequestsPerChild”个请求后将自动销毁。0意味着无限,最子进程永不销毁。虽然缺省设为0可以使每个子进程处理更多的请求,但如果设置成非零值也有两点重要的好处:1)可以防止意外的内存泄露;2)在服务器负载下载时会自动减少子进程数。

worker,使用多个子进程,同时每个子进程又有多个线程,每个线程在某个确定的时间只能维持一个连接,内存占用比较少,适合高流量的http服务器。缺点是假如一个线程崩溃,整个进程就会连同其相关联所有线程一起“死掉”,由于线程共享内存空间,所以要保证一个程式在运行时必须被系统识别为“每个线程都是安全的”。
worker的工作原理是,由主控制进程生成“StartServers”个子进程,每个子进程中包含固定的ThreadsPerChild线程数,各个线程独立地处理请求。同样,为了不在请求到来时再生成线程,MinSpareThreads和MaxSpareThreads设置了最少和最多的空闲线程数;而MaxClients设置了所有子进程中的线程总数。如果现有子进程中的线程总数不能满足负载,控制进程将派生新的子进程。

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

查看apache的工作模式方式:
1)httpd -l 或 apachectl -l
# apachectl -l
Compiled in modules:
  core.c
  prefork.c
  http_core.c
  mod_so.c
可以看到prefork.c 说明现在在用prefork模式。
2)httpd -V 或 apachectl -V
# apachectl -V
Server version: Apache/2.2.15 (Unix)
Server built:   Dec  8 2011 18:07:26
Server's Module Magic Number: 20051115:24
Server loaded:  APR 1.3.9, APR-Util 1.3.9
Compiled using: APR 1.3.9, APR-Util 1.3.9
Architecture:   32-bit
Server MPM:     Prefork
  threaded:     no
    forked:     yes (variable process count)
可以看到Server MPM: Prefork, 说明现在在用prefork模式

关于两种模式的区别,根据官方文档:

  • The MPM uses multiple child processes with many threads each. Each thread handles one connection at a time. Worker generally is a good choice for high-traffic servers because it has a smaller memory footprint than the prefork MPM.
  • The MPM uses multiple child processes with one thread each. Each process handles one connection at a time. On many systems, prefork is comparable in speed to worker, but it uses more memory. Prefork’s threadless design has advantages over worker in some situations: it can be used with non-thread-safe third-party modules, and it is easier to debug on platforms with poor thread debugging support.
可以看到,这些主要和进程和线程有关,对于内存有限逻辑简单,不太考虑线程安全的网站,worker模式显然更加适合。

进程与线程区别与联系
  1. 划分尺度:线程更小,所以多线程程序并发性更高;
  2. 资源分配:进程是资源分配的基本单位,同一进程内多个线程共享其资源;
  3. 地址空间:进程拥有独立的地址空间,同一进程内多个线程共享其资源;
  4. 处理器调度:线程是处理器调度的基本单位;
  5. 执行:每个线程都有一个程序运行的入口,顺序执行序列和程序的出口,但线程不能单独执行,必须组成进程,一个进程至少有一个主线程。简而言之,一个程序至少有一个进程,一个进程至少有一个线程.
prefork配置解释
# 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
# ServerLimit: maximum value for MaxClients for the lifetime of the server
# MaxClients: maximum number of server processes allowed to start
# MaxRequestsPerChild: maximum number of requests a server process serves


StartServers       8        
#指定服务器启动时建立的子进程数量,ps -aux|grep httpd命令查看到进程就是这里的8个。

MinSpareServers    5        
#指定空闲子进程的最小数量,假如当前空闲子进程数少于MinSpareServers ,那么Apache将创建一个进程,等待一秒钟,继续创建两个,再等待一秒钟,继续创建四个......如此按指数级增加创建进程数,最大达到每秒32个,直到满足MinSpareServers设置为止。此参数不宜设的太大

MaxSpareServers   20      
#配置空闲子进程的最大数量,假如当前有超过
MaxSpareServers数量的空闲子进程,那么父进程将杀死多余的子进程。此参数不宜设的太大。假如您将该指令的值配置为比MinSpareServers小,Apache将会自动将其修改成"MinSpareServers+1"。

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

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

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

在该工作模式下,服务器启动后起动8个httpd进程(加父进程共9个,通过ps -ax|grep httpd命令可以看到)。当有用户连接时,apache会使用一个空闲进程为该连接服务,同时父进程会fork一个子进程。直到内存中的空闲进程达到MaxSpareServers。

perchild:
如果httpd -l列出perchild.c,则需要对下面的段进行配置:
NumServers 5 #服务器启动时启动的子进程数
StartThreads 5 #每个子进程启动时启动的线程数
MinSpareThreads 5 #内存中的最小空闲线程数
MaxSpareThreads 10 #最大空闲线程数
MaxThreadsPerChild 2000 #每个线程最多被请求多少次后退出。0不受限制
MaxRequestsPerChild 10000 #每个子进程服务多少次后被重新fork。0表示不受限制。
该模式下,子进程的数量是固定的,线程数不受限制。当客户端连接到服务器时,又空闲的线程提供服务。 如果空闲线程数不够,子进程自动产生线程来为新的连接服务。该模式用于多站点服务器。

一个典型的prefork配置和解释如下:

StartServers 20 # 启动服务数,对应启动进程数
MinSpareServers 50 # 最小空闲服务(提高响应能力),当前进程数 > 最小空闲服务 + 工作进程
MaxSpareServers 100 # 最大空闲服务(合理释放资源),当前进程数 < 最大空闲服务 + 工作进程
MaxClients 200 # 最大客户端,对应最大进程数
MaxRequestsPerChild 20000 # 每个服务最多处理的请求数量,设定一个有限值可以避免内存泄漏,但会消耗进程创建和销毁的资源

prefork是用起来最方便的设置,apache的默认设置也是如此。但该模式最内存资源消耗巨大。举例来说:
一般情况下,一个PHP网站中,每个server需要30M左右内存。按照前文的配置,最多将占用6G左右的内存。
如果资源不足,就会引发频繁的page fault,大量的SWAP,系统产生大量IO,导致宕机。

Prefork工作模式有两个主要的参数,MaxClients代表了最大线程数,也就是最大并发连接数。ServerLimit表示连接数上限,默认的MaxClient最大 是256个线程,假如想配置更大的值,就的加上ServerLimit这个参数。20000是ServerLimit这个参数的最大值。假如需要更大,则 必须编译apache,此前都是无需重新编译Apache。

worker配置解释

ServerLimit   50      
#服务器允许配置的进程数上限。这个指令和ThreadLimit结合使用配置了MaxClients最大允许配置的数值。任何在重启期间对这个指令的改变都将被忽略,但对MaxClients的修改却会生效。

ThreadLimit 64      
#每个子进程可配置的线程数上限。这个指令配置了每个子进程可配置的线程数ThreadsPerChild上限。任何在重启期间对这个指令的改变都将被忽略,但对ThreadsPerChild的修改却会生效。默认值是"64".

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

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

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

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

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

MaxRequestsPerChild 0    
#配置每个子进程在其生存期内允许伺服的最大请求数量。到达MaxRequestsPerChild的限制后,子进程将会结束。假如MaxRequestsPerChild为"0",子进程将永远不会结束。对于KeepAlive链接,只有第一个请求会被计数。事实上,他改变了每个子进程限制最大链接数量的行为。 



StartServers 15 # 启动的服务,对应进程

ServerLimit 15 # 最大服务限制 应满足 ServerLimit > MaxClients / ThreadsPerChild

MaxClients 256 # 最大客户端数量
ThreadLimit 256 # 最大线程数量
MinSpareThreads 30 # 最小空闲线程(提高响应能力),当前线程数 > 最小空闲服务 + 工作线程
MaxSpareThreads 305 # 最大空闲线程(合理释放资源),当前线程数 < 最大空闲服务 + 工作线程
ThreadsPerChild 255 # 每个子进程对应对线程数
MaxRequestsPerChild 0 # 每个进程处理的最大请求数量,达到即销毁新建进程

worker模式是介于纯进程的prefork和纯线程的event模式直接的方式,在稳定性和资源上有一个取舍。

类似的,我们也主要关注其并发响应能力和资源占用情况。

上面的配置可以支持256的并发,内存占用约大于 15 * 30M = 450M 左右,算上线程的开销,大致小于500M。

其他建议

并发和性能与很多东西相关,不是简单计算能够解决的。

这里的配置主要是避免系统瓶颈,同时保护服务器不要超过应用能力。

实际情况中,和磁盘性能,网络,CPU等都有关系,建议在对硬件的充分理解上,结合性能测试工具不断调优


再说一下SYN_RECV连接状态。
如果Apache的连接数达到了极限,则有可能出现大量的SYN_RECV状态。
可以用
ps -ef|grep httpd|wc -l
来查看Apache的进程数。
netstat -an | grep SYN_RECV
来查看SYN_RECV连接状态。

好吧!万一真的是Apache不堪负重了,出现了SYN_RECV 怎么办?
我这里提供一个优化方法可能会化解这个问题,那就是设置
KeepAlive Off

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表示处理完毕,等待超时结束的请求数。

状态:描述

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

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

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

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

ESTABLISHED:正常数据传输状态

FIN_WAIT1:应用说它已经完成

FIN_WAIT2:另一边已同意释放

ITMED_WAIT:等待所有分组死掉

CLOSING:两边同时尝试关闭

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

LAST_ACK:等待所有分组死掉


阅读(1333) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~