Apache的3种工作模式
工作模式
称为MPM(multi processing module,多进程处理模块),分别位prefork、work和event
配置文件的位置
在子配置的文件夹下/usr/local/apache2/etc/extra/httpd-mpm.conf
为什么会有这三种模式
因为Apache作为老牌的服务器的应用,在不断的发展,三种模式有各自的有点与缺点,后面会详细的讲解到。
查看方式
指定方式
prefork
关键字:多进程,每个进程只产生一个线程。且每个线程只能处理一个请求。
优点:成熟,可以兼容所有新老模块。进程之间完全独立,使得它非常稳定
缺点:一个进程相对会占用更多的资源,消耗更多的内存。而且,不适合处理高并发请求,在这种情形下会将请求放入队列中,一直等到有可用的进程,请求才会被处理。
httpd-mpm.conf 中的相关配置
<IfModule mpm_prefork_module> #服务器启动时建立的子进程数量 StartServers 5 #空闲子进程的最小数量,默认5;如果当前空闲子进程数少于MinSpareServers ,那么Apache将会产生新的子进程。此参数不要设的太大。 MinSpareServers 5 #空闲子进程的最大数量,默认10;如果当前有超过MaxSpareServers数量的空闲子进程,那么父进程会杀死多余的子进程。此参数也不需要设置太大,如果你将其设置比 MinSpareServers 小,Apache会自动将其修改为MinSpareServers+1。 MaxSpareServers 10 #限定服务器同一时间内客户端最大接入的请求数量,默认是150;任何超过了该限制的请求都要进入等待队列,一旦一个个连接被释放,队列中的请求才将得到服务。 MaxClients 150 #每个子进程在其生命周期内允许最大的请求数量,如果请求总数已经达到这个数值,子进程将会结束,如果设置为0,子进程将永远不会结束。若该值设置为非0值,可以防止运行PHP导致的内存泄露。 MaxRequestsPerChild 0 </IfModule>
work MPM
多进程+多线程(多个进程中每一个进程都会创建多个线程,每个线程对应一个请求)
Apache总是试图维持一个备用(spare)或是空闲的服务线程池。这样,客户端无须等待新线程或新进程的建立即可得到处理。在Unix中,为了能够绑定80端口,父进程一般都是以root身份启动,随后,Apache以较低权限的用户建立子进程和线程。User和Group指令用于配置Apache子进程的权限。虽然子进程必须对其提供的内容拥有读权限,但应该尽可能给予他较少的特权。另外,除非使用了suexec ,否则,这些指令配置的权限将被CGI脚本所继承。
线程比起进程会更轻量,因为线程通常会共享父进程的内存空间,因此,内存的占用会减少一些,在高并发的场景下,表现得比 prefork模式好。
有些人会觉得奇怪,那么这里为什么不直接使用多线程呢(即在一个进程内实现多进程),还要引入多进程?
原因主要是需要考虑稳定性,如果一个线程异常挂了,会导致父进程连同其他正常的子线程都挂了(它们都是同一个进程下的)。多进程+多线程模式中,各个进程之间都是独立的,如果某个线程出现异常,受影响的只是Apache的一部分服务,而不是整个服务。其他进程仍然可以工作。
优点:占用更少的内存,高并发表现比prefork更优秀
缺点:需要考虑线程安全问题,因为多个子进程是共享父进程的内存地址的。使用keep-alive长连接的方式,也许中间没有请求,但是线程一直连着没有被释放,此时就会发生阻塞,直到超时才被释放。就可能在高并发下无服务线程可以用。
keep-alive长连接是指:为了让socket通信复用上一次创建的连接,从而减少连接的创建和销毁的系统开销,但是一直保持持连接会让某个进程或线程一直处在等待状态(基于TCP/IP协议,我的另一篇博客里面有讲到),即使此时数据没没有返回。
<IfModule mpm_worker_module> #服务器启动时建立的子进程数量 StartServers 2 #限定服务器同一时间内客户端最大接入的请求数量,默认是150;任何超过了该限制的请求都要进入等待队列,一旦一个个连接被释放,队列中的请求才将得到服务。 MaxClients 150 #空闲子进程的最小数量 MinSpareThreads 25 #空闲子进程的最大数量 MaxSpareThreads 75 #每个子进程产生的线程数量 ThreadsPerChild 25 #每个子进程在其生命周期内允许最大的请求数量,如果请求总数已经达到这个数值,子进程将会结束,如果设置为0,子进程将永远不会结束。将该值设置为非0值,可以防止运行PHP导致的内存泄露。 MaxRequestsPerChild 0 </IfModule>
event
多线程+多线程+epoll(事件处理)
其通过进程产生多线程的时候有一个单独的管理keep-alive长连接的线程,原理是只有真实的请求进来的时候才会给服务线程,此时不会被挂起,不允许被释放,这样一个线程可以处理好几个请求了,实现了异步非阻塞。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】