引言
写代码只占一半,把 PHP 应用稳、快、可回滚地跑在生产是另一半。本文主线是 Nginx + PHP-FPM 的经典架构(全球 PHP 网站的事实标准),再给 Docker 化与 CI/CD 流水线,最后落到灰度、回滚、监控与高频故障排查——让你部署不再靠「改了试试」。
前置:/php-performance-tuning/(FPM 调参)、/php-security-hardening/(加固)。Docker 深入见 [[docker]]。
目录
- 1. Nginx + PHP-FPM 架构
- 2. Nginx 配置实战:站点与静态资源
- 3. PHP-FPM 调优:进程池与参数
- 4. Docker 化:多阶段构建
- 5. 环境变量与配置管理
- 6. CI/CD 流水线
- 7. 上线策略:灰度与回滚
- 8. 监控与告警
- 9. 高频故障排查
- 10. 速查表
- 延伸阅读
1. Nginx + PHP-FPM 架构
为什么是这套:Nginx 处理静态与并发连接,PHP-FPM 独立进程池执行 PHP——两者解耦、各干所长。
用户 → [Nginx] ──静态资源──→ 直接返回
└──PHP 请求──→ [PHP-FPM] → PHP 代码
→ MySQL / Redis / ...
请求流转:Nginx 收到 /index.php → 按 location 匹配 → 用 fastcgi_pass 转发到 FPM 的 socket → FPM 在空闲 worker 上执行 → 返回。
| 组件 | 职责 | 特点 |
|---|---|---|
| Nginx | 静态、反向代理、限流、TLS | 高并发事件驱动 |
| PHP-FPM | 执行 PHP | 进程池 + 按请求创建 |
理解点:PHP 每请求一个 worker 执行——没有常驻状态,这是 FPM 模型(常驻见 /php-swoole-async/)。
2. Nginx 配置实战:站点与静态资源
最小站点配置:
server {
listen 80;
server_name example.com;
root /var/www/app/public;
index index.php;
# 静态资源:Nginx 直接服务,不经过 PHP
location ~* \.(js|css|png|jpg|woff2)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# PHP 请求转发到 FPM
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# 安全头
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
}
# 前端路由(SPA / Laravel fallback)
location / {
try_files $uri $uri/ /index.php?$query_string;
}
}
关键点:
| 配置 | 作用 |
|---|---|
try_files $uri =404 | 防 PHP 文件不存在 500 |
SCRIPT_FILENAME | 传 PHP 文件路径(防任意文件执行) |
| 静态资源直接返回 | 不给 FPM 加压 |
| 安全头 | XSS 基础防护 |
反模式:把所有请求都扔给 PHP(连 .js 也过 FPM)——静态资源必须 Nginx 直出。
3. PHP-FPM 调优:进程池与参数
www.conf 核心参数:
[www]
pm = dynamic # dynamic / static / ondemand
pm.max_children = 40 # 最大进程数(核心)
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 15
pm.max_requests = 500 # 进程处理 500 请求后重启(防内存泄漏累积)
进程数怎么定(经验公式):
每进程约 20–40MB 内存
max_children ≈ 可用内存 / 每进程内存
例:4GB 内存机器 → 4GB / 40MB ≈ 100,留余量取 60–80
运行模式对比:
| 模式 | 行为 | 适用 |
|---|---|---|
| dynamic | 按需增减 | 流量波动 |
| static | 固定常驻 | 流量稳定(最稳) |
| ondemand | 有请求才起 | 低流量/省内存 |
opcache 相关(配合 /php-performance-tuning/):
opcache.enable = 1
opcache.memory_consumption = 256
opcache.max_accelerated_files = 20000
4. Docker 化:多阶段构建
多阶段构建:构建阶段装 Composer 依赖,运行阶段只留运行时。
# 阶段 1:依赖构建
FROM composer:2 AS vendor
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --prefer-dist --no-progress
# 阶段 2:运行时
FROM php:8.3-fpm-alpine
RUN docker-php-ext-install pdo_mysql opcache
COPY --from=vendor /app/vendor /var/www/vendor
COPY . /var/www
WORKDIR /var/www
# FPM 默认启动
EXPOSE 9000
CMD ["php-fpm"]
docker-compose 编排:
services:
app:
build: .
environment:
APP_ENV: production
DB_HOST: mysql
depends_on: [mysql]
nginx:
image: nginx:1.27-alpine
ports: ["80:80"]
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on: [app]
mysql:
image: mysql:8.4
environment:
MYSQL_DATABASE: app
多阶段要点:锁版本(composer.lock)、非 root 运行、.dockerignore(排除 .git/node_modules)。
5. 环境变量与配置管理
配置不进镜像:镜像一套,环境变量区分环境。
// 读取环境变量(Laravel 已内置)
$dbHost = getenv('DB_HOST');
// 生产必须覆盖:APP_ENV、APP_DEBUG、DB_*、REDIS_*
环境管理规范:
| 配置 | 处理 |
|---|---|
| 密钥/密码 | 环境变量/密钥管理(K8s Secret) |
| 环境区分 | APP_ENV + 对应 env 文件 |
| 调试开关 | 生产强制 APP_DEBUG=false |
| 默认值 | 只在开发默认,生产显式注入 |
安全铁律:APP_DEBUG=true + 线上异常 = 源码/环境泄露——生产必须 false(见 /php-security-hardening/)。
6. CI/CD 流水线
GitHub Actions 完整流水线:
name: Deploy
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with: { php-version: '8.3', extensions: pdo_mysql, coverage: xdebug }
- run: composer install --no-interaction
- run: cp .env.ci .env
- run: php artisan key:generate
- run: php artisan test # 测试
- run: vendor/bin/phpstan analyse # 静态分析
- run: vendor/bin/ecs check # 代码规范
deploy:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: docker build -t ${{ vars.IMAGE }} .
- run: docker push ${{ vars.IMAGE }}
- run: ssh ${{ secrets.SSH }} 'docker pull && docker compose up -d'
CI 阶段:lint → 静态分析 → 单测 → 集成测试 → 构建 → 部署——测试挂了不部署。
7. 上线策略:灰度与回滚
灰度发布:新版本先给部分流量,验证后再全量。
# Nginx 按比例分流(示意:90% 老版,10% 新版)
# 或用负载均衡权重、开关/Feature Flag
# docker-compose 多版本并存(简化示意)
services:
app-v2:
image: app:v2
environment: { CANARY: "true" }
Feature Flag(更细粒度):
// 功能开关:按用户/百分比放量
if (feature_flag('new_checkout', $user)) {
$this->handleNewCheckout($order);
} else {
$this->handleOldCheckout($order);
}
回滚策略:
| 策略 | 做法 |
|---|---|
| 镜像回滚 | 保留上一 tag,docker compose 指回 |
| 数据库迁移 | 前滚兼容(迁移可回退),先迁移后代码 |
| 快速回滚 | 路由/开关层一键切旧 |
铁律:数据库迁移要「前向兼容」——先跑迁移再上代码,回滚不拖库。
8. 监控与告警
必监控指标(PHP 应用):
| 指标 | 告警阈值(参考) |
|---|---|
| FPM 活跃进程 | 接近 max_children |
| FPM 队列(backlog) | > 0 持续 |
| 请求 95 分位延迟 | 超 SLA |
| 5xx 比例 | > 1% |
| 内存使用 | > 80% |
| MySQL 慢查询 | 持续增多 |
| 磁盘/CPU | 常规 |
落地工具:
指标:Prometheus + php-fpm-exporter + node_exporter
日志:Laravel 结构化日志 → 采集 → 检索
追踪:traceId 贯穿(见 [[observability]])
告警:Alertmanager → 飞书/钉钉/邮件
健康检查:
// /health 端点:探活 + 依赖状态
Route::get('/health', function () {
try { DB::select('SELECT 1'); } catch (Throwable) {
return response()->json(['status' => 'degraded'], 503);
}
return response()->json(['status' => 'ok']);
});
9. 高频故障排查
故障 → 排查路径:
| 故障 | 先看什么 |
|---|---|
| 502 Bad Gateway | FPM 挂了/未启动、socket 路径不匹配 |
| 504 Gateway Timeout | FPM max_execution_time/Nginx proxy_read_timeout |
| 500 内部错误 | 应用日志(Laravel log / stderr) |
| 页面空白 | PHP 错误被屏蔽 → display_errors 临时开(生产关) |
| 静态 404 | Nginx root 路径/try_files |
| 慢请求 | FPM slow log + MySQL 慢查询 |
| 内存爆 | pm.max_requests 没设 → 泄漏累积 |
常用排查命令:
# FPM 状态
curl localhost/status # pm.status_path 暴露的指标
php-fpm -t # 语法检查
# Nginx
nginx -t
tail -f /var/log/nginx/error.log
# 进程与连接
ps aux | grep php-fpm
ss -lntp | grep 9000
记忆:502 是「FPM 连不上」,504 是「FPM 太慢」,500 看应用日志——先定层再深挖。
10. 速查表
| 需求 | 做法 |
|---|---|
| PHP 部署架构 | Nginx + PHP-FPM |
| 静态资源 | Nginx 直出 + 缓存头 |
| FPM 进程数 | 内存估算,dynamic 起步 |
| 容器化 | 多阶段 Docker + compose |
| 配置管理 | 环境变量注入 |
| 上线 | 灰度/Feature Flag + 可回滚 |
| 迁移 | 前向兼容,先迁移后代码 |
| 监控 | 5xx/延迟/FPM 队列 + 告警 |
| 排查 | 502→FPM、504→超时、500→日志 |
一句话记忆:Nginx 管静态与转发、FPM 管执行;Docker 多阶段、环境变量管配置;灰度放量、镜像回滚、迁移前向兼容;502 查 FPM、504 查超时、500 看日志。
延伸阅读
- /php-performance-tuning/ — FPM/OPcache 深度调优
- /php-security-hardening/ — 生产加固与环境配置
- /php-microservices-message-queue/ — 部署后服务间的通信
- [[docker]] — 容器化与编排深入
- [[devops]] — CI/CD 与监控运维
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。