15%

全场主机优惠15%

测试技能,享折扣

使用代码:

Skills
开始使用
01.11.2024
1 +1

VPS 上的 PHP 模式:mod_php vs FastCGI vs PHP-FPM — 完整指南

PHP 为互联网上超过 80% 的网站提供支持,但最容易被忽视的性能决策之一是选择正确的 PHP 执行模式。选择错误的模式,你会面临缓慢的加载时间、过度的 RAM 消耗和流量激增时的服务器崩溃。选择正确的模式,你的应用程序可以轻松扩展,即使在高并发负载下也是如此。

本指南详细介绍了三种主要的 PHP 执行模式 — mod_phpFastCGIPHP-FPM — 包括真实的性能背景、配置示例和针对不同用例的明确建议。无论你运行的是个人博客还是高流量电子商务平台,理解这些模式是充分利用服务器环境的基础。

目录

  1. 什么是 PHP 执行模式?
  2. mod_php — 经典 Apache 模块
  3. FastCGI — 将 PHP 与 Web 服务器解耦
  4. PHP-FPM — 高性能的现代标准
  5. 并排比较
  6. 如何在 VPS 上设置 PHP-FPM (Ubuntu/Debian)
  7. PHP-FPM 与 Nginx
  8. PHP-FPM 与 Apache
  9. 生产环境中的 PHP-FPM 池调优
  10. 你应该选择哪种 PHP 模式?
  11. 结论

什么是 PHP 执行模式? {#what-are-php-execution-modes}

PHP 执行模式定义了你的 Web 服务器如何解释和运行 PHP 脚本。它确定了 Web 服务器进程(Apache、Nginx、LiteSpeed)和 PHP 解释器之间的关系 — 具体来说,它们是否共享同一进程、通过协议通信,还是作为完全独立的托管服务运行。

三种主要模式是:

模式架构最适合
mod_phpPHP 嵌入在 Apache 中简单的共享环境
FastCGIPHP 作为独立进程中等流量网站
PHP-FPM托管 PHP 进程池高流量、生产应用

选择正确的模式直接影响内存使用请求吞吐量隔离可扩展性。在 VPS 主机环境中,资源是专用的且可配置的,你可以完全自由地实现最适合你工作负载的任何模式。

mod_php — 经典 Apache 模块 {#mod_php}

什么是 mod_php?

mod_php 是一个 Apache 模块,它将 PHP 解释器直接嵌入到 Apache Web 服务器进程中。这是运行 PHP 最古老且历史上最常见的方法。

mod_php 如何工作

当 Apache 收到对 .php 文件的请求时,它在内部处理执行 — 不会生成外部进程,不会发生套接字通信。PHP 存在于 Apache 内部。

Apache Process (PID 1234)
├── PHP Interpreter (loaded once)
├── Request 1 → PHP execution
├── Request 2 → PHP execution
└── Request 3 → PHP execution

性能特征

对于低流量网站和开发环境,mod_php 的性能是充分的。因为 PHP 已经加载到 Apache 的内存中,每个请求没有进程生成开销。

但是,这种架构有一个关键缺陷:每个 Apache 工作进程都在内存中携带完整的 PHP 解释器,无论它是在提供 PHP 文件还是提供静态资产(如图像或 CSS 文件)。

mod_php 的缺点

  • 高内存消耗:每个 Apache 工作进程(即使是提供静态文件的进程)都在 RAM 中保存完整的 PHP 运行时。
  • 无每个站点的隔离:所有虚拟主机共享同一 PHP 进程和用户上下文,这在多租户服务器上是一个安全问题。
  • 配置灵活性有限:你无法为不同的虚拟主机运行不同的 PHP 版本,除非进行重大的变通。
  • 与 Nginx 不兼容:mod_php 仅限于 Apache;它不能与 Nginx 或 LiteSpeed 一起使用。
  • 在负载下的可扩展性差:在高并发下,内存耗尽成为真正的风险。

何时使用 mod_php

  • 本地开发环境
  • 非常低流量的个人网站
  • 无法重新配置的遗留应用程序

FastCGI — 将 PHP 与 Web 服务器解耦 {#fastcgi}

什么是 FastCGI?

FastCGI 是一种协议,允许 Web 服务器与外部 PHP 进程通信,而不是将 PHP 嵌入到自身中。这是相对于 mod_php 的重大架构改进。

FastCGI 如何工作

Web 服务器(Apache 或 Nginx)通过 Unix 套接字或 TCP 端口将 PHP 请求传递给持久的 FastCGI 进程。PHP 进程处理执行并返回结果。

Apache Process          PHP Process
│                      │
├─ Request 1 ────────→ ├─ PHP execution
├─ Request 2 ────────→ ├─ PHP execution
└─ Request 3 ────────→ └─ PHP execution
(via Unix socket or TCP)

这里的关键词是持久的:与原始协议 CGI 不同,FastCGI 进程在请求之间保持活动,消除了为每个单独请求生成新进程的开销。

性能特征

与 mod_php 相比,FastCGI 显著降低了内存开销,因为静态文件请求完全由 Web 服务器处理,不涉及 PHP。PHP 进程仅在真正需要时调用。

FastCGI 的缺点

  • 配置复杂性:与 mod_php 相比需要额外的设置,包括套接字或端口配置。
  • 进程管理有限:基本 FastCGI 缺乏生产环境所需的高级池管理功能。
  • 被 PHP-FPM 取代:在大多数现代部署中,PHP-FPM(基于 FastCGI 构建)优于基本 FastCGI 实现。

何时使用 FastCGI

  • 中等流量网站
  • PHP-FPM 不可用的环境
  • 从 mod_php 迁移的过渡设置

PHP-FPM — 高性能的现代标准 {#php-fpm}

什么是 PHP-FPM?

PHP-FPM(FastCGI 进程管理器)是 FastCGI 协议的高级、功能丰富的实现。它是在生产环境中运行 PHP 的事实标准,也是任何严肃 Web 应用程序的推荐模式。

PHP-FPM 如何工作

PHP-FPM 管理一个PHP 工作进程池。Web 服务器通过 Unix 套接字或 TCP 连接将 PHP 请求转发给 PHP-FPM。PHP-FPM 根据当前流量动态管理活跃工作进程的数量,在负载下启动新工作进程,在安静期间释放它们。

Nginx Process           PHP-FPM Master
│                      │
├─ Request 1 ────────→ ├─ Worker 1 (PHP execution)
├─ Request 2 ────────→ ├─ Worker 2 (PHP execution)
├─ Request 3 ────────→ ├─ Worker 3 (PHP execution)
└─ Request 4 ────────→ └─ Worker 4 (PHP execution)
(via Unix socket)       (dynamic scaling)

PHP-FPM 的主要优势

#### 1. 动态进程管理

PHP-FPM 支持多种进程管理策略:

  • static:固定数量的工作进程(可预测,适合高流量)
  • dynamic:工作进程根据需求在最小值和最大值之间扩展
  • ondemand:工作进程仅在请求到达时生成(对低流量内存高效)

#### 2. 每个池的配置

每个应用程序或虚拟主机都可以有自己的 PHP-FPM 池,具有独立的设置:

  • 独立的 Unix 用户/组(改进的安全隔离)
  • 每个池的不同 PHP 版本
  • 每个应用程序的自定义 php.ini 值
  • 单独的资源限制

#### 3. 慢请求日志

PHP-FPM 可以记录超过定义的执行时间阈值的请求,这对于识别性能瓶颈非常宝贵。

#### 4. 资源效率

因为 PHP 进程与 Web 服务器分开管理,静态资产的提供没有任何 PHP 开销。内存仅由活跃的 PHP 工作进程消耗。

#### 5. 兼容性

PHP-FPM 与 NginxApache(通过 mod_proxy_fcgi)和 LiteSpeed 无缝协作。与 Nginx 或 LiteSpeed 结合时,性能提升是巨大的 — 与 Apache 的 mod_php 相比,在并发负载下通常快 5–10 倍。

并排比较 {#comparison}

功能mod_phpFastCGIPHP-FPM
架构嵌入在 Apache 中外部进程托管进程池
内存效率中等
静态文件开销
并发请求处理优秀
每个站点的 PHP 版本有限
安全隔离中等优秀
Nginx 兼容性
配置复杂性中等中等
生产就绪部分
慢请求日志

如何在 VPS 上设置 PHP-FPM (Ubuntu/Debian) {#setup}

以下说明适用于 Ubuntu 22.04 LTS 和 Debian 11/12。如果你在 VPS 主机计划上运行你的应用程序,你将拥有完整的 root 访问权限来执行这些命令。

步骤 1:更新你的系统并安装 PHP-FPM

sudo apt update && sudo apt upgrade -y
sudo apt install php-fpm -y

要安装特定的 PHP 版本(例如 PHP 8.2):

sudo apt install php8.2-fpm -y

步骤 2:验证 PHP-FPM 正在运行

sudo systemctl status php-fpm

你应该在输出中看到 active (running)。如果没有,启动并启用它:

sudo systemctl start php-fpm
sudo systemctl enable php-fpm

步骤 3:确认套接字路径

PHP-FPM 通过 Unix 套接字通信。验证其位置:

sudo find /run -name "php*.sock" -type s

PHP-FPM 与 Nginx {#nginx}

Nginx 是与 PHP-FPM 配对最常见的 Web 服务器,原因充分 — Nginx 的事件驱动、非阻塞架构完美补充了 PHP-FPM 的进程池模型。

安装 Nginx

sudo apt install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx

配置 Nginx 服务器块

编辑你的站点配置文件:

sudo nano /etc/nginx/sites-available/example.com

添加以下配置:

server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.php index.html;
    location ~ .php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php-fpm.sock;
}
    location ~ /.ht {
deny all;
}
}

启用站点并重启 Nginx

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

PHP-FPM 与 Apache {#apache}

如果你更喜欢 Apache — 或者如果你的应用程序依赖于 .htaccess 文件 — 你仍然可以通过 Apache 的 mod_proxy_fcgi 模块使用 PHP-FPM。

启用所需的 Apache 模块

sudo a2enmod proxy
sudo a2enmod proxy_fcgi
sudo systemctl restart apache2

配置 Apache 虚拟主机

sudo nano /etc/apache2/sites-available/example.com.conf

<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com
    <FilesMatch .php$>
SetHandler "proxy:unix:/run/php/php-fpm.sock|fcgi://localhost"
</FilesMatch>
    <Directory /var/www/example.com>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>

启用站点并重启 Apache

sudo a2ensite example.com.conf
sudo apache2ctl configtest
sudo systemctl restart apache2

生产环境中的 PHP-FPM 池调优 {#tuning}

默认的 PHP-FPM 池配置是保守的,适合开发。对于生产工作负载,你应该根据服务器的可用 RAM 和预期流量调优池设置。

定位池配置文件

sudo nano /etc/php/8.2/fpm/pool.d/www.conf

关键参数调优

pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 1000
request_terminate_timeout = 60
slowlog = /var/log/php-fpm/slow.log
request_slowlog_timeout = 5

计算 pm.max_children

动态环境的实用公式:

pm.max_children = (Total Available RAM - OS/Other Services) / Average PHP Process Size

要找到平均 PHP 进程大小:

ps aux | grep php-fpm | grep -v grep | awk '{sum+=$6} END {print sum/NR " KB"}'

在典型的 WordPress 网站上,每个 PHP-FPM 工作进程消耗大约 30–60 MB。在具有 2 GB RAM 的 VPS 上(为 OS 开销后留下约 1.5 GB),你可以安全地运行 25–50 个工作进程。

应用更改

sudo systemctl restart php-fpm

你应该选择哪种

15%

全场主机优惠15%

测试技能,享折扣

使用代码:

Skills
开始使用