Skip to content

11.4 后端部署 ​

概述

本节详细说明后端服务的部署配置,包括 Nginx、Apache、PHP 生产优化、定时任务配置,以及多数据库部署注意事项。

Nginx 配置 ​

nginx
# =============================================================================
# Nginx 站点配置 — ThinkPHP 6 后端 API
# =============================================================================
# 用途:生产环境 Nginx 反向代理,将 HTTP 请求转发给 PHP-FPM 处理
# 配置路径:/etc/nginx/sites-available/rxthinkcmf
# 启用方式:ln -s /etc/nginx/sites-available/rxthinkcmf /etc/nginx/sites-enabled/
# =============================================================================

server {
    # 监听 80 端口(HTTP),生产环境建议改为 443(HTTPS)
    listen 80;
    # 绑定域名(替换为实际域名)
    server_name api.example.com;

    # 网站根目录指向 ThinkPHP 入口目录
    # 注意:必须指向 public/ 子目录,而非项目根目录
    root /www/api/public;
    index index.php;

    # -----------------------------------------------------------------
    # URL 重写(ThinkPHP 必需)
    # -----------------------------------------------------------------
    # 将所有非真实文件请求转发到 index.php,由 ThinkPHP 路由解析
    # 例:GET /api/user/page → /index.php?s=/api/user/page
    location / {
        if (!-e $request_filename) {
            rewrite ^(.*)$ /index.php?s=$1 last;
        }
    }

    # -----------------------------------------------------------------
    # PHP-FPM 处理
    # -----------------------------------------------------------------
    # 所有 .php 请求通过 FastCGI 协议转发给 PHP-FPM 进程
    # 127.0.0.1:9000 是 PHP-FPM 默认监听地址
    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;    # PHP-FPM 监听地址
        fastcgi_index  index.php;          # 默认索引文件
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        fastcgi_params;     # 引入标准 FastCGI 参数

        # 超时设置(秒),防止长请求(如 Excel 导出)被 Nginx 提前断开
        fastcgi_read_timeout  300;         # PHP 脚本最长执行时间
        fastcgi_send_timeout  300;         # Nginx 向 PHP-FPM 发送请求的超时
    }

    # -----------------------------------------------------------------
    # 安全规则
    # -----------------------------------------------------------------
    # 禁止访问隐藏文件(如 .env、.git、.htaccess)
    location ~ /\. {
        deny all;
    }

    # 禁止上传目录执行 PHP(防止恶意文件上传后被当作脚本执行)
    location ~ /uploads/.*\.php$ {
        deny all;
    }

    # -----------------------------------------------------------------
    # 静态资源缓存
    # -----------------------------------------------------------------
    # 常见静态文件类型设置 30 天浏览器缓存,减少重复请求
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # -----------------------------------------------------------------
    # Gzip 压缩
    # -----------------------------------------------------------------
    # 对文本类响应启用压缩,减少传输体积(可节省 60%+ 带宽)
    gzip            on;
    gzip_types      text/plain text/css application/json application/javascript text/xml;
    gzip_min_length 1024;       # 小于 1KB 的响应不压缩(压缩收益低)
}

CDN / 负载均衡部署 ​

当项目部署在 CDN、云防护或负载均衡后面时,PHP 获取到的 REMOTE_ADDR 是代理服务器的 IP(通常为 127.0.0.1),而非真实客户端 IP。

框架内置 ProxyMiddleware 全局中间件,会自动从 X-Forwarded-For / X-Real-IP 请求头中提取真实客户端 IP。只需在 .env 的 [API] 段配置受信代理 IP:

ini
[API]
# 受信代理 IP(逗号分隔,支持 CIDR 网段)
# 腾讯云 CDN 常用 IP 段(完整列表请参考云服务商文档)
PROXY_IPS = 127.0.0.1,::1,101.226.0.0/15,112.65.0.0/16,140.207.0.0/16,180.101.0.0/16,182.254.0.0/16,223.166.0.0/16

重要

  • 未配置 PROXY_IPS 时,默认信任 127.0.0.1 和 ::1
  • 不要在 Nginx 的 fastcgi_param 中手动覆盖 REMOTE_ADDR、HTTP_X_REAL_IP、HTTP_X_FORWARDED_FOR,否则会丢失 CDN 传递的真实 IP
  • 配置后需清除运行时缓存:rm -rf runtime/*

Apache 配置 ​

项目 public/.htaccess 已配置好 URL 重写,确保启用 mod_rewrite:

bash
# 启用 Apache 重写模块(ThinkPHP 路由依赖此模块)
sudo a2enmod rewrite

# 编辑站点配置文件
sudo nano /etc/apache2/sites-available/000-default.conf
apache
# =============================================================================
# Apache 虚拟主机配置 — ThinkPHP 6 后端 API
# =============================================================================
# 配置路径:/etc/apache2/sites-available/000-default.conf
# 生效命令:sudo systemctl restart apache2
# =============================================================================

<VirtualHost *:80>
    # 绑定域名(替换为实际域名)
    ServerName api.example.com
    # 网站根目录指向 ThinkPHP 入口目录(必须是 public/)
    DocumentRoot /www/api/public

    # 允许 .htaccess 覆盖配置(ThinkPHP URL 重写依赖此设置)
    <Directory /www/api/public>
        AllowOverride All           # 允许 .htaccess 覆盖所有配置
        Require all granted         # 允许所有 IP 访问
    </Directory>

    # 安全:禁止上传目录执行 PHP
    <Directory /www/api/public/uploads>
        <FilesMatch "\.php$">
            Require all denied      # 拒绝所有 .php 文件的访问
        </FilesMatch>
    </Directory>
</VirtualHost>

PHP 生产环境优化 ​

php.ini 推荐配置 ​

ini
; =============================================================================
; php.ini 生产环境推荐配置
; =============================================================================
; 配置路径:/etc/php/8.2/fpm/php.ini(Nginx + PHP-FPM 场景)
; 生效命令:sudo systemctl restart php8.2-fpm
; =============================================================================

; -----------------------------------------------------------------------------
; 错误处理(生产环境必须关闭错误显示)
; -----------------------------------------------------------------------------
display_errors = Off                                ; 不向浏览器显示错误(防止 SQL/路径泄露)
error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED ; 记录除通知和弃用外的所有错误

; -----------------------------------------------------------------------------
; OPcache 加速(生产环境必须启用)
; -----------------------------------------------------------------------------
opcache.enable = 1                      ; 启用 OPcache 字节码缓存
opcache.memory_consumption = 256        ; OPcache 共享内存大小(MB),按项目规模调整
opcache.interned_strings_buffer = 16    ; 驻留字符串内存(MB)
opcache.max_accelerated_files = 10000   ; 最大缓存文件数(需大于项目 PHP 文件总数)
opcache.validate_timestamps = 0         ; 不检查文件修改时间(性能最优,更新代码后需重启 PHP-FPM)
opcache.save_comments = 1               ; 保留注释(ThinkPHP 注解依赖此配置)

OPcache 注意事项

opcache.validate_timestamps = 0 表示不检查文件修改时间,性能最优但更新代码后需要手动清除缓存:php opcache:clear 或重启 PHP-FPM。开发环境建议设为 1。

ini
; -----------------------------------------------------------------------------
; 内存与超时
; -----------------------------------------------------------------------------
memory_limit = 256M         ; 单脚本最大内存(Excel 导出建议 256M+)
max_execution_time = 60     ; 单脚本最大执行时间(秒)
max_input_time = 60         ; 解析请求数据的最大时间(秒)

; -----------------------------------------------------------------------------
; 文件上传
; -----------------------------------------------------------------------------
upload_max_filesize = 50M   ; 单文件最大上传大小
post_max_size = 50M         ; POST 请求最大大小(必须 >= upload_max_filesize)
max_file_uploads = 20       ; 单次请求最大上传文件数

; -----------------------------------------------------------------------------
; 时区与会话
; -----------------------------------------------------------------------------
date.timezone = Asia/Shanghai       ; 时区(与 .env 中 APP.DEFAULT_TIMEZONE 一致)
session.gc_maxlifetime = 7200       ; 会话过期时间(秒),默认 2 小时

PHP-FPM 配置 ​

ini
; =============================================================================
; PHP-FPM 进程池配置
; =============================================================================
; 配置路径:/etc/php/8.2/fpm/pool.d/www.conf
; 生效命令:sudo systemctl restart php8.2-fpm
; =============================================================================

[www]
; 运行用户(Nginx 也需使用同一用户,否则权限冲突)
user  = www-data
group = www-data

; -----------------------------------------------------------------------------
; 进程管理方式
; -----------------------------------------------------------------------------
; dynamic = 动态管理(推荐生产环境),根据负载自动调整进程数
; static  = 固定进程数(高并发场景)
pm = dynamic
pm.max_children     = 50    ; 最大子进程数(根据服务器内存调整,每个约 30-50MB)
pm.start_servers    = 5     ; 启动时的进程数
pm.min_spare_servers = 5    ; 最小空闲进程数(低于此值会自动创建)
pm.max_spare_servers = 35   ; 最大空闲进程数(高于此值会自动销毁)
pm.max_requests     = 500   ; 单进程最大请求数(达到后重启,防内存泄漏)

; -----------------------------------------------------------------------------
; 慢请求日志(排查性能问题)
; -----------------------------------------------------------------------------
slowlog = /var/log/php-fpm-slow.log     ; 慢请求日志路径
request_slowlog_timeout = 5s            ; 超过 5 秒的请求记录为慢请求

定时任务配置 ​

Linux Crontab ​

bash
# 编辑当前用户的 crontab 定时任务
crontab -e

# 添加定时任务:每分钟执行一次任务调度器
# 格式:分 时 日 月 周 命令
# * * * * * = 每分钟
# cd /www/api  → 切换到项目目录(ThinkPHP 需要工作目录定位配置文件)
# /usr/bin/php → PHP 绝对路径(crontab 环境变量不完整,必须用绝对路径)
# think job:run → 执行 ThinkPHP 命令行任务调度
# >> /dev/null 2>&1 → 丢弃输出(有日志系统记录,不需要控制台输出)
* * * * * cd /www/api && /usr/bin/php think job:run >> /dev/null 2>&1

# 验证 crontab 是否配置成功
crontab -l

Windows 计划任务 ​

powershell
# =============================================================================
# Windows 计划任务 — 每分钟执行一次任务调度器
# =============================================================================
# /create   → 创建新任务
# /tn       → 任务名称(在任务计划程序中显示的名称)
# /tr       → 要执行的命令
#   cmd /c  → 执行后关闭 cmd 窗口
#   cd /d   → 切换驱动器和目录(/d 支持跨盘符)
# /sc minute → 调度频率为"分钟"
# /mo 1      → 每 1 分钟执行一次
# /f         → 强制覆盖同名任务
# =============================================================================
schtasks /create /tn "RXThinkCMF_Job" /tr "cmd /c cd /d D:\xampp\htdocs\v3\thinkphp6 && C:\xampp\php\php.exe think job:run" /sc minute /mo 1 /f

# 或通过图形界面:Win+R → 输入 taskschd.msc → 回车

Daemon 守护进程(Supervisor) ​

ini
; =============================================================================
; Supervisor 进程守护配置
; =============================================================================
; 配置路径:/etc/supervisor/conf.d/rxthinkcmf-job.conf
; 生效命令:sudo supervisorctl reread && sudo supervisorctl update
; 优势:进程崩溃自动重启,比 crontab 更适合常驻进程
; =============================================================================

[program:rxthinkcmf-job]
command     = php /www/api/think job:daemon     ; 守护进程模式运行任务调度
directory   = /www/api                          ; 工作目录
autostart   = true                              ; Supervisor 启动时自动启动此进程
autorestart = true                              ; 进程退出后自动重启
user        = www-data                          ; 运行用户
stdout_logfile = /var/log/rxthinkcmf-job.log    ; 标准输出日志路径
bash
# 重新读取 Supervisor 配置文件(发现新增的 conf 文件)
sudo supervisorctl reread

# 更新进程状态(应用新配置)
sudo supervisorctl update

# 启动 rxthinkcmf-job 进程
sudo supervisorctl start rxthinkcmf-job

# 查看进程状态
sudo supervisorctl status rxthinkcmf-job

多数据库部署注意事项 ​

MySQL ​

bash
# 确保 MySQL 服务已启动
sudo systemctl start mysql

# 创建生产数据库
# CHARACTER SET utf8mb4 → 支持 emoji 等四字节字符
# COLLATE utf8mb4_general_ci → 不区分大小写的排序规则
mysql -u root -proot -e "CREATE DATABASE `rxthinkcmf.thinkphp6.elevue` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;"

# 导入初始化数据(项目自带的 SQL 文件)
mysql -u root -proot rxthinkcmf.thinkphp6.elevue < document/mysql/rxthinkcmf.thinkphp6.elevue.sql

PostgreSQL ​

bash
# 确保 PostgreSQL 服务已启动
sudo systemctl start postgresql

# 安装 PHP 的 PostgreSQL 扩展(如果尚未安装)
sudo apt install php8.2-pgsql

# 重启 PHP-FPM 使扩展生效
sudo systemctl restart php8.2-fpm

# 创建数据库(-u postgres 以 postgres 用户执行)
sudo -u postgres createdb rxthinkcmf.thinkphp6.elevue

SQLite ​

bash
# 创建数据库文件存放目录
mkdir -p /www/api/runtime

# 创建空的 SQLite 数据库文件(touch 创建空文件即可)
touch /www/api/runtime/database.sqlite

# 设置文件权限(664 = owner/group 可读写,others 只读)
chmod 664 /www/api/runtime/database.sqlite
ini
; .env 配置(切换到 SQLite 数据库)
[DATABASE]
TYPE = sqlite                                           ; 数据库类型改为 sqlite
DATABASE = /www/api/runtime/database.sqlite             ; SQLite 文件路径

数据库连接池 ​

高并发场景建议配置持久连接:

ini
; php.ini — 使用 Unix Socket 连接 MySQL(比 TCP 更快)
; 前提:PHP-FPM 和 MySQL 在同一台服务器上
pdo_mysql.default_socket = /var/run/mysqld/mysqld.sock

目录权限 ​

bash
# -----------------------------------------------------------------------------
# 项目目录(owner 可读写执行,group/others 可读和执行)
# -----------------------------------------------------------------------------
chmod -R 755 /www/api/                  # 目录 755,文件 644
chown -R www-data:www-data /www/api/    # 设置 owner 为 Web 服务器用户

# -----------------------------------------------------------------------------
# 运行时目录(必须可写 — ThinkPHP 缓存、日志、编译模板)
# -----------------------------------------------------------------------------
chmod -R 777 /www/api/runtime/          # 777 确保 PHP-FPM 进程可写入
chown -R www-data:www-data /www/api/runtime/

# -----------------------------------------------------------------------------
# 上传目录(必须可写 — 用户上传文件存储位置)
# -----------------------------------------------------------------------------
mkdir -p /opt/data/uploads              # 创建上传目录(如不存在)
chmod -R 755 /opt/data/uploads          # 目录可写
chown -R www-data:www-data /opt/data/uploads    # 设置 owner

SSL 证书(HTTPS) ​

nginx
# =============================================================================
# HTTPS 配置(生产环境必须启用)
# =============================================================================

# HTTPS 站点配置
server {
    listen 443 ssl;                         # 监听 443 端口,启用 SSL
    server_name api.example.com;

    # SSL 证书文件路径(替换为实际证书路径)
    ssl_certificate     /etc/ssl/certs/api.example.com.pem;     # 证书文件(含证书链)
    ssl_certificate_key /etc/ssl/private/api.example.com.key;   # 私钥文件

    # ... 其他配置(location、fastcgi 等)同上方 Nginx 配置 ...
}

# HTTP 自动跳转 HTTPS(301 永久重定向)
server {
    listen 80;                              # 监听 80 端口(HTTP)
    server_name api.example.com;
    return 301 https://$server_name$request_uri;    # 301 跳转到 HTTPS
}

小蚂蚁云团队 · 提供技术支持