Apache
Apache 5:并发调优(MPM)
- Apache 2.0 扩展此模块化设计到最基本的 web 服务器功能。 它提供了可以选择的多处理模块(MPM),用来绑定到网络端口上,接受请求, 以及调度子进程处理请求。 - 在用户看来,MPM 很像其它 Apache 模块。主要是区别是,在任何时间, 必须有一个,而且只有一个 MPM 加载到服务器中。可用的 MPM 列表位于 模块索引页面。 ## 选择 MPM - MPM 必须在编译前夕,配置时指定,然后编译到服务器程序中。 仅当编译器知道使用了线程时,它才有能力优化许多函数。为了使用指定的 MPM,请在执行 configure 时,使用参数 --with-mpm=NAME。NAME 是指定的 MPM 名称。另外,也可以将多个MPM编译为共享模块,configure中的参数为:–enable-mpms-shared=MPM-LIST (如:–enable-mpms-shared=’prefork worker’, –enable-mpms-shared=all)。 - 编译完成后,可以使用 ./httpd -l 来确定选择的 MPM。 此命令会列出编译到服务器程序中的所有模块,包括 MPM。由于MPM只能在编译时指定其中一种,所以列出的静态模块中MPM只有1个 - 另外,“ httpd -t -D DUMP_MODULES ”命令可以查看httpd加载的所有模块(包括静态编译的和动态共享的模块)。 ## 默认 MPM - Apache针对不同的操作系统提供了多个不同的MPM模块,例如:mpm_beos、mpm_event、mpm_netware、mpmt_os2、mpm_prefork、mpm_winnt、mpm_worker。如果条件允许,我们可以根据实际需求将指定的MPM模块编译进我们自己的Apache中(Apache的源码是开放的,允许用户自行编译)。不过,如果在编译时我们没有选择,Apache将按照如下表格根据不同的操作系统自行选择对应的MPM模块,这也是Apache针对不同平台推荐使用的MPM模块。 ## 几种常用MPM模式介绍 #### 1、mpm_prefork模块 - mpm_prefork模块主要应用于Unix/Linux平台的Apache服务器,其主要工作方式是:当Apache服务器启动后,mpm_prefork模块会预先创建多个子进程(默认为5个),当接收到客户端的请求后,mpm_prefork模块再将请求转交给子进程处理,并且每个子进程同时只能用于处理单个请求。如果当前的请求数将超过预先创建的子进程数时,mpm_prefork模块就会创建新的子进程来处理额外的请求。Apache总是试图保持一些备用的或者是空闲的子进程用于迎接即将到来的请求。这样客户端的请求就不需要在接收后等候子进程的产生。 - 由于在mpm_prefork模块中,每个请求对应一个子进程,因此其占用的系统资源相对其他两种模块而言较多。不过mpm_prefork模块的优点在于它的每个子进程都会独立处理对应的单个请求,这样,如果其中一个请求出现问题就不会影响到其他请求。同时,mpm_prefork模块可以应用于不具备线程安全的第三方模块(比如PHP的非线程安全版本),且在不支持线程调试的平台上易于调试。此外,mpm_prefork模块还具有比mpm_worker模块更高的稳定性。 #### 2、mpm_worker模块 - mpm_worker模块也主要应用于Unix/Linux平台的Apache服务器,它可以看作是mpm_prefork模块的改进版。mpm_worker模块的工作方式与mpm_prefork模块类似。不过,由于处理相同请求的情况下,基于进程(例如mpm_prefork)比基于线程的处理方式占用的系统资源要多。因此,与mpm_prefork模块不同的是,mpm_worker模块会让每个子进程创建固定数量的服务线程和一个监听线程,并让每个服务线程来处理客户端的请求,监听线程用于监听接入请求并将其传递给服务线程处理和应答。Apache总是试图维持一个备用或是空闲的服务线程池。这样,客户端无须等待新线程或新进程的建立即可得到处理。 - 与mpm_prefork模块相比,mpm_worker模块可以进一步减少系统资源的开销。再加上它也使用了多进程,每个进程又有多个线程,因此它与完全基于线程的处理方式相比,又增加了一定的稳定性。 #### 3、mpm_event 模块 - event 是worker模式的变种,它把服务进程从连接中分离出来,在开启KeepAlive场合下相对worker模式能够承受的了更高的并发负载。event模式不能很好的支持https的访问(HTTP认证相关的问题)。 - 以上两种稳定的MPM方式在非常繁忙的服务器应用下都有些不足。尽管HTTP的Keepalive方式能减少TCP连接数量和网络负载,但是 Keepalive需要和服务进程或者线程绑定,这就导致一个繁忙的服务器会耗光所有的线程。 Event MPM是解决这个问题的一种新模型,它把服务进程从连接中分离出来。在服务器处理速度很快,同时具有非常高的点击率时,可用的线程数量就是关键的资源限 制,此时Event MPM方式是最有效的。一个以Worker MPM方式工作的繁忙服务器能够承受每秒好几万次的访问量(例如在大型新闻服务站点的高峰时),而Event MPM可以用来处理更高负载。值得注意的是,Event MPM不能在安全HTTP(HTTPS)访问下工作。 #### 4、mpm_winnt模块 - mpm_winnt模块是专门针对Windows操作系统而优化设计的MPM模块。它只创建一个单独的子进程,并在这个子进程中轮流产生多个线程来处理请求。 ## 修改MPM模块配置 #### 1. 启用MPM模块配置文件 - 在Apace安装目录/conf/extra目录中有一个名为httpd-mpm.conf的配置文件。该文件主要用于进行MPM模块的相关配置。不过,在默认情况下,Apache的MPM模块配置文件并没有启用。因此,我们需要在httpd.conf文件中启用该配置文件,如下所示: ```markdown # Server-pool management (MPM specific) Include conf/extra/httpd-mpm.conf (去掉该行前面的注释符号"#") ``` #### 2. 修改MPM模块配置文件中的相关配置 - 在启动MPM模块配置文件后,我们就可以使用文本编辑器打开该配置文件。只有Apache使用对应MPM模块时,对应配置才会生效只有Apache使用对应MPM模块时,对应配置才会生效。此时,我们就需要根据当前Apache服务器所使用的MPM模块,来修改对应<IfModule>节点下的参数配置。 ##### 2.1 mpm_winnt模块配置: - 由于mpm_winnt模块只会创建1个子进程,因此这里对单个子进程的参数设置就相当于对整个Apache的参数设置。 ```markdown <IfModule mpm_winnt_module> ThreadsPerChild 150 #推荐设置:小型网站=1000 中型网站=1000~2000 大型网站=2000~3500 MaxRequestsPerChild 0 #推荐设置:小=10000 中或大=20000~100000 </IfModule> ``` - 对应的配置参数作用如下: ThreadsPerChild : 每个子进程的最大并发线程数。 MaxRequestsPerChild: 每个子进程允许处理的请求总数。如果累计处理的请 - 求数超过该值,该子进程将会结束(然后根据需要确定是否创建新的子进程),该值设为0表示不限制请求总数(子进程永不结束)。 - 该参数建议设为非零的值,可以带来以下两个好处: 可以防止程序中可能存在的内存泄漏无限进行下去,从而耗尽内存。 给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量。 注意:在以上涉及到统计请求数量的参数中,对于KeepAlive的连接,只有第一个请求会被计数 ##### 2.2 mpm_perfork模块配置  - StartServers【默认值 5】 启动Apache时创建的子进程数。 - MinSpareServers 【默认值 5】 处于空闲状态的最小子进程数。 所谓空闲子进程是指没有正在处理请求的子进程。如果当前空闲子进程数少于MinSpareServers,那么Apache将以最大每秒一个的速度产生新的子进程。只有在非常繁忙机器上才需要调整这个参数。此值不宜过大。 - MaxSpareServers 处于空闲状态的最大子进程数。 只有在非常繁忙机器上才需要调整这个参数。此值不宜过大。如果你将该指令的值设置为比MinSpareServers小,Apache将会自动将其修改成MinSpareServers+1。 - MaxRequestsPerChild【默认为10000】 每个子进程在其生存期内允许伺服的最大请求数量,默认为10000.到达MaxRequestsPerChild的限制后,子进程将会结束。如果MaxRequestsPerChild为"0",子进程将永远不会结束。 将MaxRequestsPerChild设置成非零值有两个好处: 1.可以防止(偶然的)内存泄漏无限进行,从而耗尽内存。 2.给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量 - MaxClients 256 限定同一时间客户端最大接入请求的数量(单个进程并发线程数),默认为256。任何超过MaxClients限制的请求都将进入等候队列,一旦一个链接被释放,队列中的请求将得到服务。要增大这个值,你必须同时增大ServerLimit - ServerLimit 【缺省将取默认值20000】 默认的MaxClient最大是256个线程, 如果想设置更大的值,就的加上ServerLimit这个参数。 20000是ServerLimit这个参数的最大值。如果需要更大,则必须重新编译apache, 生效前提:必须放在其他指令的前面 - prefork 控制进程在最初建立“StartServers”个子进程后,为了满足MinSpareServers设置的需要创建一个进程,等待一秒钟,继续创建两 个,再等待一秒钟,继续创建四个……如此按指数级增加创建的进程数,最多达到每秒32个,直到满足MinSpareServers设置的值为止。这种模式 可以不必在请求到来时再产生新的进程,从而减小了系统开销以增加性能。MaxSpareServers设置了最大的空闲进程数,如果空闲进程数大于这个 值,Apache会自动kill掉一些多余进程。这个值不要设得过大,但如果设的值比MinSpareServers小,Apache会自动把其调整为 MinSpareServers+1。如果站点负载较大,可考虑同时加大MinSpareServers和MaxSpareServers。 - MaxRequestWorkers指令集同时将服务请求的数量上的限制。任何连接尝试在MaxRequestWorkerslimit将通常被排队,最多若干基于上ListenBacklog指令。 - 在apache2.3.13以前的版本MaxRequestWorkers被称为MaxClients 。 - (MaxClients是这些指令中最为重要的一个,设定的是 Apache可以同时处理的请求,是对Apache性能影响最大的参数。其缺省值150是远远不够的,如果请求总数已达到这个值(可通过ps -ef|grep http|wc -l来确认),那么后面的请求就要排队,直到某个已处理请求完毕。这就是系统资源还剩下很多而HTTP访问却很慢的主要原因。虽然理论上这个值越大,可以 处理的请求就越多,但Apache默认的限制不能大于256。) ##### 2.3 mpm_worker模块配置:  ```markdown StartServers3 服务器启动时建立的子进程数,默认值是"3"。 MinSpareThreads 处于空闲状态的最小线程数。 mpm_worker的默认值是75。这个MPM将基于整个服务器监视空闲线程数。如果服务器中总的空闲线程数太少,子进程将产生新的空闲线程。 mpm_netware的默认值是10。 既然这个MPM只运行单独一个子进程,此MPM当然亦基于整个服务器监视空闲线程数。mpm_beos和mpmt_os2的工作方式与mpm_netware差不多,mpm_beos的默认值是1;mpmt_os2的默认值是5。 MaxSpareThreads 处于空闲状态的最大线程数。 mpm_worker的默认值是250。这个MPM将基于整个服务器监视空闲线程数。如果服务器中总的空闲线程数太多,子进程将杀死多余的空闲线程。 mpm_netware的默认值是100。 既然这个MPM只运行单独一个子进程,此MPM当然亦基于整个服务器监视空闲线程数。mpm_beos和mpmt_os2的工作方式与mpm_netware差不多,mpm_beos的默认值是50;mpmt_os2的默认值是10。 ThreadsPerChild 每个子进程建立的常驻的执行线程数。默认值是25。 子进程在启动时建立这些线程后就不再建立新的线程了。 MaxRequestsPerChild 每个子进程在其生存期内允许伺服的最大请求数量,默认为10000.到达MaxRequestsPerChild的限制后,子进程将会结束。如果MaxRequestsPerChild为"0",子进程将永远不会结束。 将MaxRequestsPerChild设置成非零值有两个好处: 1.可以防止(偶然的)内存泄漏无限进行,从而耗尽内存。 2.给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量。 MaxRequestWorkers 最大数量的工作线程,等于ServerLimit*ThreadPerChild, 如果按照默认的ServerLimit=16的话,2000>16*50,日志中会报错“MaxRequestWorkers of 1000 would require 20 servers and exceed ServerLimit of 16, decreasing to 800”,这时我们需要通过修改ServerLimit,需要先停止apache服务再启动,直接restart无效。 MaxRequestsPerChild【默认为10000】 每个子进程在其生存期内允许伺服的最大请求数量,默认为10000.到达MaxRequestsPerChild的限制后,子进程将会结束。如果MaxRequestsPerChild为"0",子进程将永远不会结束。 将MaxRequestsPerChild设置成非零值有两个好处: 1.可以防止(偶然的)内存泄漏无限进行,从而耗尽内存。 2.给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量 ``` - Worker 由主控制进程生成“StartServers”个子进程,每个子进程中包含固定的ThreadsPerChild线程数,各个线程独立地处理请求。同样, 为了不在请求到来时再生成线程,MinSpareThreads和MaxSpareThreads设置了最少和最多的空闲线程数; - 而MaxRequestWorkers 设置了同时连入的clients最大总数。如果现有子进程中的线程总数不能满足负载,控制进程将派生新的子进程 - MinSpareThreads和 MaxSpareThreads的最大缺省值分别是75和250。这两个参数对Apache的性能影响并不大,可以按照实际情况相应调节 。 - ThreadsPerChild是worker MPM中与性能相关最密切的指令。ThreadsPerChild的最大缺省值是64,如果负载较大,64也是不够的。这时要显式使用 Thread-limit指令,它的最大缺省值是20000。 - Worker模式下所能同时处理的请求总数是由子进程总数乘以ThreadsPerChild 值决定的,应该大于等于MaxRequestWorkers。如果负载很大,现有的子进程数不能满足时,控制进程会派生新的子进程。默认最大的子进程总数是16,加大时 也需要显式声明ServerLimit(最大值是20000)。需要注意的是,如果显式声明了ServerLimit,那么它乘以 ThreadsPerChild的值必须大于等于MaxRequestWorkers,而且MaxRequestWorkers必须是ThreadsPerChild的整数倍,否则 Apache将会自动调节到一个相应值。 ##### 2.4 mpm_event模块配置  - 查看当前的连接数可以用: ```markdown ps aux | grep httpd | wc -l 或:pgrep httpd|wc -l ``` - 计算httpd占用内存的平均数: ```markdown ps aux|grep -v grep|awk '/httpd/{sum+=$6;n++};END{print sum/n}' ``` - 备注:ServerLimit表示Apache允许创建的最大进程数。 值得注意的是,Apache在编译时内部有一个硬限制ServerLimit 20000(对于mpm_prefork模块为ServerLimit 200000)。你不能超越这个限制。 使用这个指令时要特别当心。如果将ServerLimit设置成一个高出实际需要许多的值,将会有过多的共享内存被分配。如果将ServerLimit和MaxClients设置成超过系统的处理能力,Apache可能无法启动,或者系统将变得不稳定。 - 注意:在配置相关参数时,请先保证服务器具备足够的硬件性能(例如:CPU、内存等)。 如果发现自启动后,随着服务器的运行时间增加,服务器的内存占用也随之增加,可能是程序中出现内存泄露,请向下调整参数MaxRequestsPerChild的值以降低内存泄露带来的影响,然后尽快找出程序中的问题之所在。
顶部
收展
底部
[TOC]
目录
Apache 1:简介安装
Apache 2:配置虚拟主机
Apache 3:安全
Apache 4:性能测试工具ab的应用
Apache 5:并发调优(MPM)
Apache 6 : 性能调优
Apache 7 : 参数调优
相关推荐
Nginx