Apache 迁移 Nginx 实操:从伪静态到 PHP-FPM 的配置对照

从 Apache 迁移到 Nginx:性能提升与配置迁移指南 封面配图

网站流量涨上来之后,很多站长会遇到同一个场景:服务器内存占用一路走高,页面响应越来越慢,重启 Apache 能缓一阵,但过几天又回来了。这时候你会开始研究如何在不推倒重来的前提下解决这个问题,而把 Web 服务从 Apache 迁移到 Nginx,正是被验证最多的方案之一。这篇指南会带你完整走一遍迁移流程:先讲清楚 Apache 为什么在高并发下吃力,再给出虚拟主机、伪静态规则、PHP 处理方式这三个核心配置的对照迁移方法,最后是灰度切换、验证和回滚方案。即使没有专职运维,也可以按照文中步骤逐项核对,控制迁移风险。

一、Apache 为什么在高并发下吃力

先理解问题的根源,迁移时才知道哪些配置是关键。Apache 常见的 Prefork 和 Worker 模式本质上都是”连接驱动进程或线程”:每来一个连接,就分配一个进程或线程去处理,连接不断开,这个进程就一直占着几 MB 到几十 MB 内存。日常几十个并发没问题,但一旦并发涨到几百上千(比如被采集、搞促销),内存和进程切换开销会迅速把服务器压垮。

Nginx 用的是完全不同的模型:每个 Worker 进程基于事件驱动(epoll),单进程就能同时维持数以万计的连接,静态文件请求直接由 Worker 高速吐出,不需要为每个连接单开进程。实际案例里,同样的 2 核 4G 服务器,迁移后内存占用从 90% 以上降到 30% 左右是常见结果,动态请求响应也会更稳定。关于服务器性能的更多优化思路,可以配合本篇方案阅读。

不过要客观看待:Apache 的 .htaccess 目录级配置和庞大的模块生态是 Nginx 没有的优势,如果网站重度依赖 .htaccess 做跳转和伪静态,迁移时就必须把这些规则手工转换成 Nginx 配置,这也是下文重点要解决的环节。

二、迁移前先盘点现有配置

动手改配置之前,先花十分钟把 Apache 的”家底”摸清楚,避免迁移到一半才发现缺东西。在服务器上依次执行下面的命令并记录结果:

# 查看 Apache 版本和已加载模块(确认是否有 mod_rewrite、mod_security 等)
apache2ctl -M 2>/dev/null || httpd -M

# 找到所有虚拟主机配置文件的位置
apachectl -S 2>/dev/null || httpd -S

# 检查 PHP 运行方式(是 mod_php 还是 php-fpm)
ps aux | grep -E "php-fpm|php[0-9.-]*-fpm" | grep -v grep

# 列出网站目录里所有的 .htaccess 文件(这些是转换重点)
find /var/www -name ".htaccess" -type f 2>/dev/null

盘点结果决定三件事:伪静态数量决定转换工作量;PHP 运行方式决定迁移后用 mod_php 还是 PHP-FPM;有无 mod_security 等安全模块决定要不要找替代方案。记下这些,后面每一节都能对应上。

三、虚拟主机配置:一一对应转换

Apache 的 VirtualHost 和 Nginx 的 server 块是同一个概念的两套写法,对照着转换即可。以一个运行 WordPress 的站点为例,先看 Apache 的原始配置:

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/example
    ErrorLog ${APACHE_LOG_DIR}/example-error.log
    CustomLog ${APACHE_LOG_DIR}/example-access.log combined
</VirtualHost>

转换成 Nginx 后是这样:

server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/example;
    index index.php index.html;

    access_log /var/log/nginx/example-access.log;
    error_log  /var/log/nginx/example-error.log;
}

对应关系可以记成三组:ServerName/ServerAlias 对应 server_name;DocumentRoot 对应 root;日志指令对应 access_log / error_log。两个差异点要留意:Nginx 的 root 写的是文件系统实际路径;Nginx 没有目录级 .htaccess,所有规则必须集中写在 server 块里,这也是迁移工作量的主要来源。

四、伪静态规则:.htaccess 转 Nginx rewrite

伪静态是整个迁移里最容易出错的一步。Apache 的 mod_rewrite 规则写在 .htaccess 里,语法和 Nginx 的 rewrite 不兼容,不能直接复制。以 WordPress 默认的 .htaccess 为例,它的核心只有一句话:请求的文件或目录不存在时,把所有请求交给 index.php 处理。

对应的 Nginx 写法非常简洁:

location / {
    try_files $uri $uri/ /index.php?$args;
}

这一行替代了整段 WordPress 的 rewrite 规则,也是官方推荐写法。其他自定义跳转规则的对照关系是:RewriteRule ... [R=301] 对应 rewrite ... permanent;RewriteCond 条件通常改写成 location 匹配,官方建议少用 if。

转换完先做语法检查再谈生效:

nginx -t          # 检查配置语法
nginx -s reload   # 语法通过后再热加载

验证伪静态是否工作的最快办法:浏览器直接打开一篇文章的内页 URL,能正常显示就说明规则生效;如果首页正常、内页 404,九成是 try_files 里的 index.php 回退没写对。

五、PHP 处理:从 mod_php 切换到 PHP-FPM

Apache 常见跑法是 mod_php,PHP 解释器直接内嵌在 Apache 进程里;Nginx 不能这样,它必须通过 FastCGI 协议把 PHP 请求交给独立的 PHP-FPM 进程池处理。这一步没接好,迁移后的站点会直接把 PHP 文件当成下载弹出来,属于典型事故。

先安装并启动 PHP-FPM(以 Debian/Ubuntu 为例):

apt install php8.2-fpm
systemctl enable --now php8.2-fpm

然后在 Nginx 的 server 块里加上 FastCGI 转发段:

location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}

location ~ /\.ht {
    deny all;
}

最后的 location 是安全底线:拒绝访问 .htaccess 等隐藏文件,避免规则文件被外人下载。PHP-FPM 进程数按内存调整,2 核 4G 的机器 pm.max_children 设 20-30 比较稳妥,设太大会重现内存打满的老问题。

六、灰度切换与验证:不要一口气停掉 Apache

配置全部转换完,也不建议直接停掉 Apache 切流量。更稳的做法是让两个服务短期并存,用端口分流先验证:让 Nginx 先监听 8080,Apache 继续占 80,然后做三轮检查:

  1. 用 curl -I http://服务器IP:8080/ 确认响应头里已经是 Nginx,且返回 200 而不是 502;
  2. 逐页点检核心路径:首页、文章内页、搜索页、登录后台、图片等静态资源,任何一页 404 或 500 都要回到配置里排查;
  3. 观察半小时的 error_log,重点看有没有 connect() failed 或 PHP-FPM 超时记录,没有再正式切 80 端口。

正式切换选凌晨低峰期执行:先 systemctl stop apache2 释放 80 端口,再把 Nginx 的 listen 改回 80 并 reload,通常不超过一分钟。保留 Apache 配置原样不动,24 小时内出现定位不了的问题可以按原路径回滚。

切换完成后用数据确认收益。同一台 2 核 4G 服务器上的典型对比:并发 500 连接时,Apache 内存占用 90% 以上、平均响应超过 2 秒;Nginx 内存占用 30% 左右、平均响应 200-500ms。用 ab -n 1000 -c 100 https://你的域名/ 在切换前后各测一次,用真实数据代替案例数字,结论才有说服力。

到这里,迁移主线就完整了。如果你的站点目前还跑在配置较低的环境里,也可以考虑把业务搬到 VPS(虚拟专用服务器)环境,结合 Hostease 的 VPS主机 方案一并规划升级,迁移和扩容一次做完,避免短期内二次停机。

Apache 与 Nginx 的并发处理差异对比配图

七、迁移后最容易踩的三个坑

即使流程都走对了,下面三个问题仍然是返工最多的地方,切完流量后第一周要重点盯。

坑一:内页 404 但首页正常。 几乎都是 try_files 配置里漏了 /index.php?$args 回退,或者 server 块里没有那个 location ~ \.php$ 段。按第四、五节的配置逐行核对即可,改完记得 nginx -t 通过后再 reload。

坑二:上传的图片超过限制直接报错。 Nginx 默认 client_max_body_size 只有 1MB,比多数 Apache 环境小得多。在 server 块加一行 client_max_body_size 64m;,同时核对 PHP-FPM 的 upload_max_filesize 保持一致,两边不匹配时以较小的那个生效。

坑三:静态资源缓存行为变了。 Apache 之前可能通过 mod_expires 设置了图片长缓存,迁移后如果不补上,用户浏览器会频繁回源重新拉图,反而觉得”迁移后变慢了”。补一段简单的缓存规则:

location ~* \.(jpg|jpeg|png|webp|gif|css|js)$ {
    expires 30d;
    add_header Cache-Control "public";
}

这三个坑覆盖了迁移后报修的大多数情况。日常巡检配合 systemctl status php8.2-fpm 和 tail -f /var/log/nginx/error.log,基本可以在用户反馈前发现问题。

八、总结与下一步行动

整个迁移的脉络可以收成一句话:先盘点 .htaccess、虚拟主机和 PHP 运行方式这三类配置,再按 server 块、try_files 伪静态、PHP-FPM 三步完成转换,最后用 8080 端口灰度验证、保留 Apache 回滚路径,切换本身只需要一分钟。性能收益则用你自己跑的 ab 压测数据说话,不依赖任何案例数字。

如果你正准备动手,建议先在测试环境走一遍第三到五节的转换命令,再按第六节灰度验证,确认无误后挑低峰期切换。没有专职运维的团队,把迁移交给托管环境更省心——Hostease 的 虚拟主机 和 WordPress主机 方案自带调优过的环境和中文技术支持,配置问题可以直接提交工单。迁移完成后,建议把第六节的验证清单存进运维手册,每次改配置后照着跑一遍,能避免绝大多数上线事故。

Apache 迁移 Nginx 四个阶段流程示意图

发表评论