Apache性能调优mpm

–>

    早在开发Apache2.0版本时,开发人员就打算为Apache建立一个能够在所有平台上运行的处理模块,所有平台
的开发人员就可以使用这个模块的API编程。可是经过几个月的开发之后,开发者发现如果让Apache在所有平台
上运行,需要考虑太多问题,例如各个平台在建立进程和线程时的特性,于是,为了解决这个问题,Apache开发人员开发出
MPM(Mutli-Processing Modules 多通道处理模块),毫不夸张的说MPM的引入是Apache从1.3版本到2.0版本
最重要的变化,它使得Apache能适应更多平台以及不同的工作环境,极大的扩展了Apache的功能,使Apache以更简洁、
更有效的方式支持多种操作系统。同时Apache服务器还可以为一些特定的站点进行定制,例如:需要更好的伸缩性的站点可以选择使用worker或者event,

需要更好的稳定性和兼容性的站点使用prefork。而在支持POSIX线程的UNIX/Linux系统上,Apache可以通过不同的MPM运行在多进程与多线程混合模式下,增强部分配置的可扩充性能。至于Windows系统,可以使用mpm_winnt来代替Apache1.3中使用的POSIX模拟层,已取得更好的性能。

    由于MPM无法被模块化,所以对它的选择只能在编译时选择,并且只能被静态的编译到服务器中,在Apache2.2版本中MPM只能选择一个,同一台服务器无法使用多个MPM模块的(Apache2.4版本以前的版本),在APache2.4版本开始可以通过修改Apache的配置文件来实现MPM模块切换

Apache2.X MPM模块列表
MPM模块名 说  明


BeOS

专门针对BeOS优化过的多路处理模块(MPM),此模块是BeOS系统默认的MPM模块

※在Apache2.4版本的官方文档中去除了此项

mpm_netware 专门为Novell NetWare优化的,线程化的多路处理模块(MPM),此模块是NetWare系统默认的MPM模块
mpm_winnt 专门为Windows NT/2000/XP/系统此模块是是Windows操作系统默认的MPM模块

mpmt_os2

专门针对OS/2优化过的混合多进程、多线程的MPM,此模块是OS/2系统的默认MPM


prefork

prefork是UNIX/Linux平台上默认的MPM,它所采用的预派生子进程方式䦹Apache1.3中采用的模式。prefork本身是不使用线程的,为了保持兼容性,所以在Apache2.0版本中还使用它,另一方面,prefork用单独的子进程来处理不同请求,每个进程之间是独立的,这也使它成为最稳定的MPM之一。


     worker

worker是线程型的MPM,实现一个混合的多线程多处理的MPM,允许一个子进程中包含多个线程,相对于prefork,worker是Apache2.0版本中新增的支持多线程和多进程混合模型的MPM,由于使用多进程,再由每个进程派生出多线程来处理,所以可以处理相对海量请求,而系统资源的开销要小于基于进程的服务器,这种类型MPM工作方式,将是Apache以后的发展趋势。

    

     event

这个模块在Apache2.2版本以后得以增强,但是在Apache2.2版本手册上来看,它还在测试中,在Apache2.4版本中默认使用此模块,如果想要使用event的非阻塞优势,请安装httpd2.4.XX版本。


※在编译安装httpd时可以使用–with-mpm=mpm进行指定,httpd2.4版本以后使用–enable-mpms-shared=all全部安装,在配置文件中修改配置即可。

1、prefork MPM模块:

    prefork模块是一个预派生进程的模块,它在Apache启动之初,就先预派生一些子进程,然后等待连接;可以减少频繁创建和销毁进程的开销,每个子进程只有一个线程,在一个时间点内,只能处理一个请求。这是一个成熟稳定,可以兼容新老模块,也不需要担心线程安全问题,但是一个进程相对占用一些系统资源,在处理高并发请求的场景中,会消耗大量的系统资源。



Prefork模块具有很强的自我调节能力,只需要很少的配置指令调整,即可工作的很好。唯一注意的就是将MaxRequestWorkers参数(Apache2.3.1以前的版本MaxRequestWorkers被称为MaxClients,现在依然支持这个参数)设置为一个合适的数值以处理潜在的请求高峰,MaxRequestWorkers参数,即表示最大只能同时处理多少个请求,如果有更多的请求,则将它们放入到队列中,直到有请求处理完成后的空闲进程。如果服务器繁忙,则需要修改这个数值,但是也不能将这个数值又不能太大,以致于产生太多的进程而导致超出物理内存大小让服务器崩溃。
# 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
# MaxRequestWorkers: maximum number of server processes allowed to start
# MaxConnectionsPerChild: maximum number of connections a server process serves
<IfModule mpm_prefork_module>

  StartServers 5
  MinSpareServers 5
  MaxSpareServers 10
  MaxRequestWorkers 250
  MaxConnectionsPerChild 0

</IfModule> 
# StartServers:  默认初始化预派生的进程数
# MinSpareServers:  最小空闲子进程数
# MaxSpareServers:  最大空闲子进程数
# ServerLimit: 最大派生的进程数(MaxRequestWorkers的上限值,最大不能超过这个值可以等于)
# MaxRequestWorkers:  最大程请求数(最大并发数)

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

2、worker MPM模块:
    worker模块是使用线程来响应请求的,它在高并发时在内存使用方面处理的很好。在多路复用模块中,需要的进程数较少,因为它不像Prefork那样需要为每个请求创建一个进程,Worker模式会在进程中创建线程,请求进入的连接通过一个进程中的不同线程来处理。worker模式中,新的连接只需要等待空闲的线程即可,而不是像Prefork中那样需要等待空闲进程。
优点:适用高并发场景,因为线程共享子进程的内存,所以内存占用较少。
缺点:如果一个线程出现问题,也会导致同一子进程下的其他线程出现问题。


# worker MPM
# StartServers: initial number of server processes to start
# MinSpareThreads: minimum number of worker threads which are kept spare
# MaxSpareThreads: maximum number of worker threads which are kept spare
# ThreadsPerChild: constant number of worker threads in each server process
# MaxRequestWorkers: maximum number of worker threads
# MaxConnectionsPerChild: maximum number of connections a server process serves
<IfModule mpm_worker_module>
StartServers 3
MinSpareThreads 75
MaxSpareThreads 250 
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 0
</IfModule>

# StartServers:  默认初始化开始的子进程数
# MinSpareThreads:  最小空闲线程数
# MaxSpareThreads:  最大空闲线程数
# ThreadsPerChild:  每个子进程产生的线程数
# MaxRequestWorkers:  最大请求子进程数
# MaxConnectionsPerChild:  每个子进程处理多少个请求后被杀死
ThreadsPerChild是worker MPM中与性能相关最密切的指令。ThreadsPerChild的最大缺省值是64,如果需要设置为64以上,那就需要在这个参数前添加ThreadLimit参数,它的最大缺省值是20000
Worker的MaxRequestWorkers参数和perfork的MaxRequestWorkers参数一样,如果需要设置为256以上,则在这个参数前还需要添加参数ServerLimit并且指定最大请求子进程数。

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

3、event MPM模块:
    event模式是非常新的。事实上,它只在Apache2.4版本中被作为稳定版发布。event模式和Worker模式工作原理相同,它也是使用进程和线程。它们最大的区别在与event模式会为每个请求创建一个线程,而不是为一个http连接创建一个线程
有一种情况那就是当你喜欢使用线程但是有一个应用程序,这个应用程序使用了较长的keepalive超时时间时这种模式很适用。在Worker MPM中,线程是和连接绑定的,并且无论http请求是否被处理都保持被占用状态。
在event MPM中,如果处理连接的线程只是用来处理当前请求并且会在请求处理完成后立即释放,不管被父进程处理的http连接的情况。同时,当线程在请求被处理完成立即释放后可以被用来处理其他请求。这意味着需要更少的线程!
    event就是worker模式的变种,他解决的keep-alive长连接的时候占用线程资源被浪费的问题,在event模式中会有一些专门的线程用来管理这些keep-alive类型的线程,当有真实请求过来的时候,将请求传递给服务器的线程,执行完毕后,又允许它释放。这增强了在高并发场景下的请求处理。
缺点:event模式不能很好的支持https的访问(HTTP认证相关的问题)。

# event MPM
# StartServers: initial number of server processes to start
# MinSpareThreads: minimum number of worker threads which are kept spare
# MaxSpareThreads: maximum number of worker threads which are kept spare
# ThreadsPerChild: constant number of worker threads in each server process
# MaxRequestWorkers: maximum number of worker threads
# MaxConnectionsPerChild: maximum number of connections a server process serves
<IfModule mpm_event_module>
StartServers 3
MinSpareThreads 75
MaxSpareThreads 250
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 0
</IfModule> 

# StartServers:  默认初始化开始的子进程数
# MinSpareThreads:  最小空闲线程数
# MaxSpareThreads:  最大空闲线程数
# ThreadsPerChild:  每个子进程产生的线程数
# MaxRequestWorkers:  最大请求子进程数
# MaxConnectionsPerChild:  每个子进程处理多少个请求后被杀死

附录:进程与线程的区别
线程是指进程内的一个执行单元,也是进程内的可调度实体,与进程的区别:
(1)地址空间:进程内的一个执行单元;进程至少有一个线程;它们共享进程的地址空间;而进程有自己独立的地址空间;
(2)资源拥有:进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源
(3)线程是处理器调度的基本单位,但进程不是.
(4)二者均可并发执行.
进程和线程都是由操作系统的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于:
   简而言之,一个程序至少有一个进程,一个进程至少有一个线程. 线程的划分尺度小于进程,使得多线程程序的并发性高。 
    另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。 
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。 
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。 一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行。

本文来源 互联网收集,文章内容系作者个人观点,不代表 本站 对观点赞同或支持。如需转载,请注明文章来源,如您发现有涉嫌抄袭侵权的内容,请联系本站核实处理。

© 版权声明

相关文章