Linux Nginx(master-slave)、Apache(woker、prefork) Working Mode Research

catalog

1. Apache工作模式
2. Nginx工作模式

 

1. Apache工作模式

Apache服务器支持三种工作模式(Apache称之为MPM,简写为Multi-Processing Module,译为 多处理模块),分别为

1. prefork模式
2. worker模式
3. event模式
//在旧的版本只支持profork和worker模式, 只有较新的版本才支持event模式
4. WinNT MPM模式

不同的工作模式有不同的优缺点,会影响到Apache的性能和可伸缩性。查看Apache服务器的工作模式,可以使用命令httpd -l

[root@iZ23er0navtZ html]# httpd -l
Compiled in modules:
  core.c
  prefork.c
  http_core.c
  mod_so.c

0x1: prefork MPM(prefork模式)

profork采用了进程处理请求的模式。它适合在没有线程安全库和需要避免线程兼容性的系统中运行。由于进程间互不受影响,因此它可获得很高的稳定性。 但由于进程比较消耗资源,因此在大量请求的服务器中不能获得较高的性能
一个单独的控制进程(父进程)负责产生子进程,这些子进程用于监听请求并作出应答。Apache总是试图保持一些备用的(spare)或是空闲的子进程用于迎接即将到来的请求。这样客户端就无需在得到服务前等候子进程的产生
在Unix系统中,父进程通常以root身份运行以便邦定80端口(注意这里是先绑定再fork的,所以意味着所有的子进程都监听了80端口),而 Apache产生的子进程通常以一个低特权的用户运行。User和Group指令用于配置子进程的低特权用户。运行子进程的用户必须要对他所服务的内容有读取的权限,但是对服务内容之外的其他资源必须拥有尽可能少的权限。
子进程的个数会随着请求量的大小动态调整。调整的策略与perfork的配置息息相关,httpd.conf的配置文件有以下配置:

<IfModule prefork.c>
/*
1. StartServers为Apache默认启动的进程数(至少要大于等于1,小于1时强制设置为1)
这个连接数默认为5,不宜设置过大,可以由Apache根据请求逐渐增加进程数,但是启动进程时会增加耗时
这个参数设置不宜过大还有一个好处: 跟Tomcat进行集群时,可以根绝请求逐渐增加Apache跟Tomcat的连接。所以这个参数不宜设置过大,无谓增加Apache跟Tomcat的连接(Apache一旦跟Tomcat建立连接后,就不会释放,直到Timeout)
*/
StartServers      50

/*
2. MinSpareServers: 最小空闲进程
MinSpareServers指令设置空闲子进程的最小数量。所谓空闲子进程是指没有正在处理请求的子进程。如果当前空闲子进程数少于MinSpareServers ,那么Apache将以第一秒一个,第二秒两个,第三秒四个,按指数递增个数的速度产生新的子进程 
*/
MinSpareServers   100

/*
3. MaxSpareServers: 最大空闲进程
MaxSpareServers指令设置空闲子进程的最大数量。所谓空闲子进程是指没有正在处理请求的子进程。如果当前有超过MaxSpareServers数量的空闲子进程,那么父进程将杀死多余的子进程 
可以调整这两个参数,但是这两个参数的值不能设得太大,否则apache进程太多,会导致性能急剧下降,因为CPU频繁地在进行进程上下文切换调度
*/
MaxSpareServers   200

/*
4. ServerLimit: 在Apache的生命周期内,限制MaxClients的最大值
*/
ServerLimit      1024

/*
5. MaxClients: 最大的并发请求数
*/
MaxClients       1024

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

配置文件对apache行为的影响如下

1. 控制进程(以root权限启动的主进程)先建立"StartServers"个子进程
2. 当空闲进程数小于MinSpareServers时,继续创建子进程,直到满足空闲进程数大于等于MinSpareServers
3. 当并发请求高时而空闲进程数小于MaxSpareServers时会继续创建子进程,最多可以创建MaxClients个 
4. 当并发高峰过去时,空闲进程的数量大于MaxSpareServers时会删除多余的子进程,直到剩MaxSpareServers为止 
5. 当子进程处理的连接数超过MaxRequestsPerChild时,自动关闭,当MaxRequestsPerChild为0时这没有这个限制 

0x2: worker模式

worker模式采用了多进程多线程的处理方式。使用线程来处理请求(一个线程处理一个请求),因此它可以占用更少的资源而处理比prefork模式更多的请求。 由于它采取N个进程派生N*M个线程的模式,仍然获得了较高的稳定性(一个进程出问题,或导致其子线程出问题)
每个进程能够拥有的线程数量是固定的。服务器会根据负载情况增加或减少进程数量。一个单独的控制进程(父进程)负责子进程的建立
每个子进程能够建立ThreadsPerChild数量的服务线程和一个监听线程,该监听线程监听接入请求并将其传递给服务线程处理和应答
Apache总是试图维持一个备用(spare)或是空闲的服务线程池。这样,客户端无须等待新线程或新进程的建立即可得到处理
在Unix中,为了能够绑定80端口,父进程一般都是以root身份启动,随后,Apache以较低权限的用户建立子进程和线程。User和Group指令用于配置Apache子进程的权限。虽然子进程必须对其提供的内容拥有读权限,但应该尽可能给予他较少的特权。另外,除非使用了suexec ,否则,这些指令配置的权限将被CGI脚本所继承
相对于prefork,worker是2.0版中全新的支持多线程和多进程混合模型的MPM。由于使用线程来处理,所以可以处理相对海量的请求,而系统资源的开销要小于基于进程的服务器。但是,worker也使用了多进程,每个进程又生成多个线程,以获得基于进程服务器的稳定性。这种MPM的工作方式将是Apache 2.0的发展趋势

<IfModule worker.c>
//1. StartServers: 服务器启动时开启的进程数
StartServers        20

//2. ServerLimit: Apache的生命周期内,限制MaxClients的最大值
ServerLimit         40

//3. MaxClients: 最大的并发请求数
MaxClients          1280

//4. MinSpareThreads: 最小的线程空闲数
MinSpareThreads     128

//5. MaxSpareThreads: 最大的线程空闲数
MaxSpareThreads     256

//6. ThreadsPerChild: 每一个进程可以产生的线程数
ThreadsPerChild     64

//7. MaxRequestsPerChild: 一个线程可以处理的最多的请求数(线程复用),如请求超过该设置则杀死线程,0表示永不过期
MaxRequestsPerChild  128000
</IfModule>

0x3: event模式

The event Multi-Processing Module (MPM) is designed to allow more requests to be served simultaneously by passing off some processing work to supporting threads, freeing up the main threads to work on new requests. It is based on the worker MPM, which implements a hybrid multi-process multi-threaded server. Run-time configuration directives are identical to those provided by worker.

0x4: WinNT MPM

Apache httpd 的 Windows 版本现在更有效率了,因为 mpm_winnt 能使用原生网络特性取代在 Apache httpd 1.3 中使用的 POSIX 层。它也可以扩展到其它平台 来使用专用的 MPM

# WinNT MPM
# ThreadsPerChild: constant number of worker threads in the server process
# MaxRequestsPerChild: maximum  number of requests a server process serves
<IfModule mpm_winnt_module>
ThreadsPerChild      150  //修改这个值即可
MaxRequestsPerChild    0
</IfModule>

0x5: apache"惊群"现象与解决方案

无论是上面那个MPM被选择,都有一问题就是主进程先监听80端口,然后又fork出子进程。所以可以知道,fork出来的每个子进程都在监听80端口,如果这时候有请求过来就会出现所有的空闲进程都回来抢这个fd,也就是这些进程都被唤醒了,但是最终只有一个进程能够拿到这个fd进行处理,其他进程因为拿不到进程而再次进入休眠状态,这就是"惊群"现象
apache的prefork模型下的处理方式如下如所示

Linux Nginx(master-slave)、Apache(woker、prefork) Working Mode Research_第1张图片

apache通过在每个accept()函数上 增加互斥锁和条件变量 来解决这个惊群问题。保证每个请求只会被一个线程刚好拿到,不会影响其他线程

1. 条件变量与互斥锁不同,条件变量是用来等待而不是用来上锁的。条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。通常条件变量和互斥锁同时使用
2. 互斥锁提供互斥机制(CPU调度),条件变量提供信号机制 
3. 每次一个新的客户请求过来,正在监听的线程与该请求建立连接,并变为worker工作者线程。让出监听者角色时它同时发送信号到条件变量,并释放锁。这样在空闲(idle)状态的一个线程将被唤醒并获得锁 
4. 也就是说:条件变量保证了其他线程在等待条件变化期间处于睡眠;互斥锁保证一次只有一个线程被唤醒

Relevant Link:

http://httpd.apache.org/docs/2.4/mod/worker.html
http://httpd.apache.org/docs/2.2/mod/worker.html
http://httpd.apache.org/docs/2.4/mod/event.html
http://httpd.apache.org/docs/2.4/mpm.html
http://www.phpernote.com/php-template/1119.html
http://hao.jser.com/archive/8381/
http://oohcode.com/2015/10/09/apache-and-nginx/
http://www.ccvita.com/299.html
http://wwdhks.blog.51cto.com/839773/871694

 

2. Nginx工作模式

关于nginx的工作模式请参阅另一篇文章

Relevant Link:

http://www.cnblogs.com/LittleHann/p/4893028.html

 

Copyright (c) 2015 LittleHann All rights reserved

 

你可能感兴趣的:(Linux Nginx(master-slave)、Apache(woker、prefork) Working Mode Research)