Apache 目前一共有三种稳定的 MPM 模式。它们分别是 prefork/worker 和 event,它们同时也代表 Apache 的演变和发展。今天杜老师就聊下 worker 模式!

worker 模式的工作原理

worker 模式与 prefork 模式相比,采用的是多进程与多线程混合的模式。worker 模式同样会先预派生一些子进程,然后由每个子进程创建若干线程,其中包括一个监听线程,每个请求到来时会被分配到某个线程进行处理。由于线程通过共享父进程的内存空间,相比进程更加轻量,内存占用也更少,在高并发场景下会比 prefork 拥有更多可用线程,表现也更为出色。此外,如果某个线程出现问题,可能会导致同一进程下的其他线程出现问题;如果是多个线程出现问题,也只会影响 Apache 的一部分,而非整体。由于使用了多进程多线程,需要考虑线程安全问题。在使用 keep-alive 长连接时,某个线程可能会被一直占用,即使中间没有请求,也需要等待超时才会被释放。

Apache 总是试图维持一个备用或空闲的服务线程池。这样,客户端无须等待新线程或新进程的建立即可得到处理。在 Unix 系统中,为了能够绑定 80 端口,父进程通常以 root 身份启动,随后 Apache 会以较低权限的用户建立子进程和线程。User 和 Group 指令用于配置 Apache 子进程的权限。虽然子进程必须对其所提供的内容拥有读权限,但应尽可能给予它较少的特权。另外,除非使用了 suEXEC,否则这些指令配置的权限将被 CGI 脚本继承。

worker 模式的安装方法

在编译安装 Apache 的过程中,加入参数–with-mpm=worker 即进行编译安装。

也可以使用–enable-mpms-shared=all,这样在编译的时候会在 modules 目录下自动编译出三个 MPM 文件的 so,然后通过修改 httpd.conf 配置文件更改 MPM 即可。

worker 模式优缺点

优点:占据更少内存,高并发下表现优秀。

缺点:必须考虑线程安全问题,因为多个子线程是共享父进程内存地址的。如使用 keep-alive 的长连接方式,也许中间几乎没有请求,这时就会发生阻塞,线程会被挂起,需要一直等待到超时才会被释放。如果线程过多,被这样的占据,也会导致高并发场景下的无服务线程可用。

worker 模式配置参数说明

配置说明
StartServers 3服务启动时初始进程数,默认是 3
MinSpareThreads 75最小空闲子进程数,默认是 75
MaxSpareThreads 250最大空闲子进程数,默认是 250
ThreadsPerChild 25每个子进程产生的线程数量,默认是 25
MaxRequestWorkers 400限定同一时间内客户端最大接入请求数量,默认是 400
MaxConnectionsPerChild 0每个子进程在其生命周期内允许最大请求数量,如果请求总数已经达到这个数值,子进程将结束,如果设置为 0,子进程将永远不会结束。如该值设置为非 0 值,可以防止运行 PHP 导致的内存泄露