Apache httpd基础篇03 — MPM三种工作模式

概述

本章,您将了解到 Apache httpd 中 MPM 的三种工作模式,即 event、prework 和 worker。

MPM(Multi-Processing Modules,多处理模块):Apache httpd 中的核心组件之一,目的是为了让 Apache httpd 在不同操作系统上发挥最大化的性能和稳定性,该组件主要实现了网络监听、网络请求处理、调度进程或子进程等功能。因为 Apache httpd 本身是跨平台的,不同操作系统对底层网络的请求处理都不太一样,若强行使用一套统一的代码,就没法发挥各自操作系统的原生优势特性,为了在不同平台环境下实现最佳的网络性能以及稳定性,便诞生了 MPM。

在编译安装 Apache httpd 时,由于未指定 --with-mpm=MPM 选项,则 MPM 默认工作模式为 event 。

Shell > /usr/local/apache2/bin/apachectl -V
Server version: Apache/2.4.68 (Unix)
Server built:   Jun 13 2026 22:40:36
Server's Module Magic Number: 20120211:142
Server loaded:  APR 1.7.6, APR-UTIL 1.6.3, PCRE 10.32 2018-09-10
Compiled using: APR 1.7.6, APR-UTIL 1.6.3, PCRE 10.32 2018-09-10
Architecture:   64-bit
Server MPM:     event
  threaded:     yes (fixed thread count)
    forked:     yes (variable process count)
Server compiled with....
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_PROC_PTHREAD_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=256
 -D HTTPD_ROOT="/usr/local/apache2/"
 -D SUEXEC_BIN="/usr/local/apache2//bin/suexec"
 -D DEFAULT_PIDLOG="logs/httpd.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="conf/mime.types"
 -D SERVER_CONFIG_FILE="conf/httpd.conf"
提示
MPM 的三种工作模式特指 Apache httpd 在 UNIX 或 GNU/Linux 操作系统中的工作模式。对于 Windows 操作系统,Apache httpd 只有 mpm_winnet 这种工作模式。

进程与线程

进程(Process):是一个具有一定独立功能的程序关于某个数据集合的一次运行活动,是系统进行「资源分配和调度」的一个独立单位。从这段话中可知:

  • 进程是程序的「一次执行」,即进程是程序的一个实例(或实体)
  • 进程是程序运行在一个「数据集合」上的过程
  • 进程反映了程序以及数据在处理机上顺序执行后的活动状态
  • 进程是操作系统进行资源分配和调度的一个独立单位(基本单位)

线程(Thread):进程的轻量型实体,是一系列按照顺序执行的指令集合,是一条执行路径,不能单独存在,必须包含在进程中(换言之,一个进程可以包含单个或多个线程)。线程是操作系统中运算调度的最小单位。

每个进程都有自己的内存上下文(资源和地址空间),而来自 同一进程线程 则共享相同的上下文。

在 GNU/Linux 操作系统中,每个进程都有:

  • PID - Process IDentifier,唯一的进程标识符。
  • PPID - Parent Process IDentifier,父进程的唯一标识符

通过连续的隶属关系,init 进程(也就是 systemd,其 pid 为 1 )是所有进程之父。

进程的说明:

  • 进程之间存在父与子的关系
  • 子进程是父进程调用 fork() 原语(primitive,计算机术语)并复制自己的代码来创建子进程的结果
  • 一个进程始终由父进程进行创建
  • 一个父进程可以有多个子进程
  • 子进程的 PID 会返回给父进程,以便父进程与之对话
  • 每个子进程都有父进程的标识符 PPID
  • PID 中的数字代表执行时的进程,当进程结束时,该数字可再次用于另一个进程
  • 多次运行同一命令将每次产生不同的 PID 数字

孤儿进程(orphan process) - 当父进程死亡时,其子进程被称为 孤儿。init 进程(systemd,PID 为 1 )会收养这些特殊状态的进程,并完成状态收集,直到它们被销毁。从概念上讲,孤儿院进程不会造成任何伤害。

僵尸进程(zombie process) - 子进程完成工作并被终止之后,其父进程需要调用信号处理函数 wait() 或 waitpid() 来获取子进程的终止状态。如果父进程没有这样做,虽然子进程已经退出,但它仍然在系统进程表中保留一些退出状态信息,因为父进程无法获取子进程的状态信息,这些进程将持续占用进程表中的资源,我们将这种状态下的进程称为 僵尸

僵尸进程的危害:

  • 占用系统资源并导致机器性能下降
  • 无法生成新的子进程。

prework

prework:稳定优先的多进程模式。这是一种古老但非常可靠的模式,其核心思想是「预先创建子进程」,工作原理如下:

Apache httpd 在启动时,父进程会预先创建(fork)一批子进程,并始终保持一定数量的空闲进程随时待命,之所以要预先创建,是为了减少频繁创建以及销毁进程的开销。每个子进程只有一个线程,互相独立、互不影响,以提高稳定性。在一个时间点内,一个线程只能处理一个请求,并且会根据并发请求数量动态生成更多的子进程,具体生成多少由配置文件决定。

  • 优点 - 稳定且安全
  • 缺点 - 占用更加多的系统资源且并不适合高并发场景

worker

worker:多进程 + 多线程的混合模式。工作原理如下:

Apache httpd 在启动时,父进程会根据配置文件的配置指令预先创建(fork)一定数量的子进程。每个子进程会生成固定数量的线程(包括多个服务线程以及一个监听进程),每个线程处理一个请求。如果某个子进程崩溃,只会影响该子进程内的线程,而其他子进程仍可正常工作,从而保证了服务器的整体稳定性。

  • 优点 - 占用内存低(相比每个请求独占一个进程的 prefork ,worker 在处理大量并发请求时能显著减少内存消耗);并发性能强(线程的创建和切换开销小于进程)
  • 缺点 - 线程安全问题导致的未知错误(由于在同一个进程当中的线程共享相同的内存资源,若使用了非线程安全的模块,可能会导致出现未知错误);Keep-Alive 长连接阻塞问题(当一个线程处理一个 Keep-Alive 连接时,即使中间没有请求,该线程也会一直被占用,直到超时。在高并发场景中,会出现大量线程被空闲连接占据的情况,此时的 Apache httpd 无法服务新的请求,造成资源浪费)
说明
在 Apache httpd 的文档中,父进程(Parent Process)有时也会被称为主控制进程(Master Control Process)‌。

HTTP Keep-Alive 和 TCP Keepalive

众所周知,现如今的互联网根据普遍采用的是 TCP/IP 四层模型,而面向教学时则会称 TCP/IP 五层模型。TCP/IP 模型不像 ISO/OSI 模型那样是先有理论框架再填充协议,而是‌先有协议,后有模型,因此人们也会将 TCP/IP 模型称为 TCP/IP 协议族。

file

  • 应用层的协议:ftp、https、http、dns、smtp、snmp等这些,属于应用层的协议。
  • 传输层的协议:TCP 与 UDP,选择其中之一或者两个都选。
  • 网络层的协议:IP 协议、ICMP 协议、IGMP 协议、ARP 协议
  • 网络接口层协议:ppp 协议,pppoe 拨号协议

file

file

在本文中,Keep-Alive 特指 HTTP Keep-Alive,而不是 TCP Keepalive,两者对比如下:

特性 HTTP Keep-Alive TCP Keepalive
工作层级 应用层 传输层
实现 由应用程序(如浏览器、Web服务器)实现 由操作系统内核实现
目的 复用 TCP 连接,提升效率与性能 检测无效连接,释放服务器资源
触发时机 在一次 HTTP 请求/响应完成后,决定是否保持连接以备下次复用 在一个 TCP 连接长时间空闲(无数据传输)后触发
工作方式 等待一段时间,看是否有新请求 发送探测包,看对方是否响应

TCP Keepalive 的诞生背景:在早期的网络通信中,当客户端和服务器建立连接后,若客户端突然出现死机、崩溃、断电或者网络中断的情况,服务器端往往毫不知情,它会一直傻傻地维护着这个实际上已经失效的连接,而这些失效连接还占用着内存、文件描述符等系统资源。久而久之,大量这样的 "僵尸连接" 会拖垮服务器的性能。于是,人们在 TCP 协议中引入了 ‌Keepalive 机制‌,这种机制相当于为 TCP 连接开启 "心跳包" 监听:

  • 目的 - 让服务器端能快速感知到对方是否还 "活着",从而及时清理无效连接释放资源
  • 工作方式 - 如果连接在一段时间内(通常为 2 小时)没有任何数据传输,服务器就会发送一个探测包。若对方有正常响应,说明连接还处于活跃状态;若多次探测都没有回应,就判定为失效的连接,服务器会主动关闭这个连接并释放资源

HTTP Keep-Alive 的诞生背景:在早期的 ‌HTTP/1.0 时代‌,默认是 "短连接"。这意味着浏览器每请求一个资源(比如一个 HTML 页面、一张图片、一个 CSS 文件),都要经历一次完整的 TCP 连接建立和关闭过程:

  • 三次握手(建立连接)
  • 传输数据
  • 四次挥手(关闭连接)

如果一个网页有 50 张图片,这个过程就要重复 50 次,开销巨大的同时效率还非常低。大约从 ‌1996 年‌开始,一些浏览器和服务器厂商受不了了,开始在 HTTP/1.0 中实验性地扩展支持 ‌Keep-Alive 长连接‌,目的很简单 —— 一次连接,多次使用‌。浏览器和服务器之间只需建立一次 TCP 连接,就可以在这条连接上串行地传输多个 HTTP 请求和响应,直到所有资源都传输完毕或超时后才关闭。后来该特性成为 HTTP/1.1 的默认特性,即现在我们所说的 "持久连接(Persistent Connections)"。

event

event:work 工作模式的变体增强版,主要解决 work 工作模式下 keep-alive 长连接阻塞问题。在配置上,event 兼容 worker 的配置指令。

Avatar photo

关于 陸風睿

GNU/Linux 从业者、开源爱好者、技术钻研者,撰写文档既是兴趣也是工作内容之一。Q - "281957576";WeChat - "jiulongxiaotianci",Github - https://github.com/jimcat8
用一杯咖啡支持我们,我们的每一篇[文档]都经过实际操作和精心打磨,而不是简单地从网上复制粘贴。期间投入了大量心血,只为能够真正帮助到您。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇