生产环境配置

将 Viswoole 应用部署到生产环境时,需要对 Swoole 服务参数、PHP 配置和框架配置进行全面优化。

Swoole 服务配置

完整生产环境 server.php

php
<?php
// config/server.php - 生产环境版本

declare (strict_types=1);

use Swoole\Constant;
use Swoole\Http\Server as httpServer;
use Viswoole\HttpServer\Exception\HttpExceptionHandle;
use Viswoole\HttpServer\HttpEventHandle;

return [
    'default_start_server' => env('DEFAULT_START_SERVER', 'http'),

    'servers' => [
        'http' => [
            'type' => httpServer::class,
            'exception_handle' => HttpExceptionHandle::class,

            'construct' => [
                // 监听地址:0.0.0.0 允许外部访问
                'host' => env('SERVER_HOST', '0.0.0.0'),
                // 监听端口
                'port' => (int)env('SERVER_PORT', 9501),
                // 运行模式:多进程模式
                'mode' => SWOOLE_PROCESS,
                // TCP 协议
                'sock_type' => SWOOLE_SOCK_TCP,
            ],

            'options' => [
                // ===== 核心选项 =====

                // 上传文件大小限制(KB),框架默认 5 * 1024(5MB),生产环境可适当调大
                Constant::OPTION_UPLOAD_MAX_FILESIZE => 10 * 1024,  // 10MB

                // 启用 HTTP2 支持
                Constant::OPTION_OPEN_HTTP2_PROTOCOL => true,

                // ===== 进程配置 =====

                // 守护进程运行(后台运行)
                Constant::OPTION_DAEMONIZE => (bool)env('SWOOLE_DAEMONIZE', true),

                // Task Worker 数量(CPU 核数或根据任务量调整)
                Constant::OPTION_TASK_WORKER_NUM => (int)env('TASK_WORKER_NUM', swoole_cpu_num()),

                // 启用 Task 协程支持
                Constant::OPTION_TASK_ENABLE_COROUTINE => true,

                // Task 最大请求数(防止内存泄漏)
                Constant::OPTION_TASK_MAX_REQUEST => (int)env('TASK_MAX_REQUEST', 10000),

                // ===== 性能调优 =====

                // Worker 进程数(建议 = CPU 核数 × 2~4)
                Constant::OPTION_WORKER_NUM => (int)env('WORKER_NUM', swoole_cpu_num() * 2),

                // 每个 Worker 最大处理请求数后重启(防止内存泄漏)
                Constant::OPTION_MAX_REQUEST => (int)env('MAX_REQUEST', 100000),

                // Reactor 线程数(通常等于 CPU 核数)
                Constant::OPTION_REACTOR_NUM => (int)env('REACTOR_NUM', swoole_cpu_num()),

                // ===== 内存与缓冲区 =====

                // Socket 缓冲区大小
                Constant::OPTION_SOCKET_BUFFER_SIZE => 2 * 1024 * 1024,  // 2MB

                // 输出缓冲区大小
                Constant::OPTION_BUFFER_OUTPUT_SIZE => 2 * 1024 * 1024,  // 2MB

                // 数据包最大长度
                Constant::OPTION_PACKAGE_MAX_LENGTH => 2 * 1024 * 1024,  // 2MB

                // ===== 协程配置 =====

                // 一键协程化 Hook 范围
                Constant::OPTION_HOOK_FLAGS => SWOOLE_HOOK_ALL,

                // 启用协程调度器
                Constant::OPTION_ENABLE_COROUTINE => true,

                // 单个协程最大栈空间(字节),8192 字节 = 8KB
                Constant::OPTION_STACK_SIZE => 8192,  // 8KB

                // 最大协程数量
                Constant::OPTION_MAX_CONCURRENCY => (int)env('MAX_COROUTINE', 100000),

                // ===== 日志配置 =====

                // 守护进程日志文件路径
                Constant::OPTION_LOG_FILE => env('LOG_FILE', BASE_PATH . '/runtime/sysLog.log'),

                // 日志级别(生产环境建议 WARNING 或更高)
                Constant::OPTION_LOG_LEVEL => (int)env('LOG_LEVEL', SWOOLE_LOG_WARNING),

                // ===== 连接配置 =====

                // 是否启用 TCP 快速握手
                Constant::OPTION_OPEN_TCP_NODELAY => true,

                // Keep-Alive 探测间隔(秒),0 表示不探测
                Constant::OPTION_KEEP_ALIVE_INTERVAL => 30,

                // 空闲超时时间(秒)
                Constant::OPTION_IDLE_TIMEOUT => 300,

                // ===== 安全配置 =====

                // 压缩传输(节省带宽但增加 CPU 消耗)
                Constant::OPTION_HTTP_COMPRESSION => true,

                // 压缩最小长度(字节)
                Constant::OPTION_HTTP_COMPRESSION_MIN_LENGTH => 2048,

                // 压缩级别(1-9)
                Constant::OPTION_HTTP_COMPRESSION_LEVEL => 6,
            ],

            // 事件回调
            'events' => [
                Constant::EVENT_REQUEST => [HttpEventHandle::class, 'onRequest'],
            ],
        ],
    ],

    // 全局默认选项
    'options' => [
        Constant::OPTION_HOOK_FLAGS => SWOOLE_HOOK_ALL,
        Constant::OPTION_ENABLE_COROUTINE => true,
        Constant::OPTION_DAEMONIZE => (bool)env('SWOOLE_DAEMONIZE', true),
        Constant::OPTION_LOG_FILE => env('LOG_FILE', BASE_PATH . '/runtime/sysLog.log'),
        Constant::OPTION_WORKER_NUM => (int)env('WORKER_NUM', swoole_cpu_num()),
        Constant::OPTION_TASK_WORKER_NUM => (int)env('TASK_WORKER_NUM', swoole_cpu_num()),
        Constant::OPTION_MAX_REQUEST => (int)env('MAX_REQUEST', 100000),
    ],

    // 全局事件
    'events' => [],
];

关键参数详解

进程模型参数

参数开发环境推荐生产环境推荐说明
worker_numswoole_cpu_num()swoole_cpu_num() * 2~4Worker 进程数
task_worker_numswoole_cpu_num()swoole_cpu_num()Task Worker 数
reactor_num默认值swoole_cpu_num()Reactor 线程数
daemonizefalsefalse(使用 systemd/supervisor 管理时)守护进程模式
max_request10000010000~100000Worker 最大请求数

Worker 数量计算公式:

text
Worker 数量 = CPU 核心数 × 每核心承载系数

- CPU 密集型: × 1~2
- IO 密集型(推荐): × 2~4
- 混合型: × 2~3

示例(8 核服务器):

php
// IO 密集型应用(Web API)
'worker_num' => 24,  // 8核 × 3

// CPU 密集型应用(数据处理)
'worker_num' => 8,   // 8核 × 1

内存管理参数

参数推荐值说明
max_coroutine100000最大并发协程数
stack_size8192 (8KB)协程栈大小
socket_buffer_size2MSocket 缓冲区
buffer_output_size2M输出缓冲区
package_max_length2M最大数据包

注意: max_coroutine × stack_size 会占用虚拟内存,需确保服务器内存充足。100000 个协程 × 8KB ≈ 800MB 虚拟内存(实际物理内存按需分配)。

日志参数

参数开发环境生产环境说明
log_filesysLog.log/var/log/app/swoole.log日志文件路径
log_levelSWOOLE_LOG_INFOSWOOLE_LOG_WARNING日志级别

日志文件位置建议:

bash
# Linux 标准日志目录
/var/log/app/
├── swoole.log          # Swoole 系统日志
├── app/
   ├── error.log       # 应用错误日志
   └── access.log      # 访问日志

.env 生产环境配置

ini
; ============================================
; 生产环境 .env 配置模板
; ============================================

; --- 应用基础(对应 app.php,env() 内部会将键名转为大写)---
APP_NAME=MyProductionApp
APP_ENV=production
APP_DEBUG=false                          # 必须 false!
APP_URL=https://api.example.com
DEFAULT_TIMEZONE=Asia/Shanghai           # 对应 app.php 的 env('default_timezone', ...)

; --- Swoole 服务 ---
SERVER_HOST=0.0.0.0
SERVER_PORT=9501
SWOOLE_DAEMONIZE=true                    # 使用 systemd 管理时必须设为 false,见下文说明
WORKER_NUM=16
TASK_WORKER_NUM=8
MAX_REQUEST=50000
MAX_COROUTINE=100000
LOG_LEVEL=2                              # SWOOLE_LOG_WARNING
LOG_FILE=/var/log/app/swoole.log

; --- 数据库(对应 database.php,环境变量名为 DATABASE_*)---
DATABASE_DEFAULT=default
DATABASE_HOST=127.0.0.1
DATABASE_PORT=3306
DATABASE_NAME=production_db
DATABASE_USER=app_user
DATABASE_PASSWORD=<strong_password_here>

; --- Redis ---
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=<redis_password>
REDIS_DB=0

; --- 缓存(对应 cache.php 的 env('cache.store', ...))---
CACHE_STORE=redis                        # 需在 cache.php 中配置 redis store

; --- 安全 ---
APP_KEY=<generate_with_php_viswoole_key_generate>
CORS_ORIGIN=https://www.example.com

注意:config/log.php 中的 defaulttrace_sourceconsole 均为硬编码值,不通过环境变量配置,因此 .env 中无需设置 LOG_* 变量。如需按环境差异化配置日志,请自行修改 log.php 引入 env() 调用。

PHP 配置优化

php.ini 关键参数

ini
; ============================================
; 生产环境 php.ini 推荐配置
; ============================================

; --- 性能相关 ---
realpath_cache_size = 4096k
realpath_cache_ttl = 600
opcache.enable = 1
opcache.memory_consumption = 256
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 20000
opcache.revalidate_freq = 60
opcache.validate_timestamps = 0          # 生产环境设为 0(不自动检测文件变更,提升性能),开发环境设为 1
opcache.save_comments = 1
opcache.fast_shutdown = 1
opcache.enable_cli = 1                  # CLI 模式也启用(Swoole 需要)

; --- 内存限制 ---
memory_limit = 512M                     # 根据实际需求调整

; --- 执行时间 ---
max_execution_time = 30                 # Swoole 中主要受 request_slowlog_timeout 控制
max_input_time = 60

; --- 文件上传 ---
upload_max_filesize = 20M
post_max_size = 20M
max_file_uploads = 20

; --- 错误报告(生产环境关闭)---
display_errors = Off
display_startup_errors = Off
error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT
log_errors = On
error_log = /var/log/app/php_errors.log

; --- Session ---
session.save_handler = redis            # 使用 Redis 存储 session
session.save_path = "tcp://127.0.0.1:6379"
session.gc_maxlifetime = 7200
session.cookie_httponly = Yes
session.cookie_secure = Yes             # HTTPS 时开启
session.use_strict_mode = Yes
session.sid_length = 48

; --- 其他 ---
expose_php = Off                        # 隐藏 PHP 版本信息
date.timezone = Asia/Shanghai

Nginx 反向代理配置

基础配置

nginx
upstream viswoole_backend {
    least_conn;                          # 最少连接负载均衡
    server 127.0.0.1:9501 weight=5;
    server 127.0.0.1:9502 weight=5;
    # 可添加更多实例...
    keepalive 64;                        # 保持长连接
}

server {
    listen 80;
    server_name api.example.com;

    # 强制 HTTPS(可选)
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name api.example.com;

    # SSL 证书配置
    ssl_certificate     /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;

    # 访问日志
    access_log /var/log/nginx/api.access.log;
    error_log  /var/log/nginx/api.error.log;

    # 客户端请求体大小限制
    client_max_body_size 20m;

    # 代理超时设置
    proxy_connect_timeout 10s;
    proxy_send_timeout    60s;
    proxy_read_timeout    120s;

    location / {
        proxy_pass http://viswoole_backend;

        # 传递真实 IP
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # WebSocket 支持(如需要)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # Swoole 友好设置
        proxy_buffering off;               # 禁用 nginx 缓冲(让 Swoole 自己控制)
        proxy_cache off;
    }

    # 静态资源直接由 Nginx 处理(可选)
    location ~* .(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
        try_files $uri =404;
    }
}

进程管理

systemd 服务单元

创建 /etc/systemd/system/viswoole.service

重要:使用 systemd 管理进程时,.env 中的 SWOOLE_DAEMONIZE 必须设为 false。systemd 要求服务进程在前台运行,若启用守护进程模式(true),主进程会立即退出导致 systemd 认为服务已停止并不断重启。

ini
[Unit]
Description=Viswoole HTTP Server
After=network.target mysql.service redis.service
Requires=mysql.service redis.service

[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/var/www/app

# 启动命令(前台运行,由 systemd 管理 daemonize)
# 确保 .env 中 SWOOLE_DAEMONIZE=false
ExecStart=/usr/local/bin/php viswoole server:start --host=0.0.0.0 --port=9501
ExecReload=/usr/local/bin/php viswoole server:reload
ExecStop=/usr/local/bin/php viswoole server:close

# 自动重启策略
Restart=on-failure
RestartSec=5
StartLimitIntervalSec=60
StartLimitBurst=3

# 资源限制
LimitNOFILE=65535
LimitNPROC=65535

# 日志
StandardOutput=journal
StandardError=journal
SyslogIdentifier=viswoole

[Install]
WantedBy=multi-user.target

使用方法:

bash
# 启动服务
sudo systemctl start viswoole

# 设置开机自启
sudo systemctl enable viswoole

# 查看状态
sudo systemctl status viswoole

# 重载服务
sudo systemctl reload viswoole

# 重启服务
sudo systemctl restart viswoole

# 查看日志
sudo journalctl -u viswoole -f

Supervisor 配置(备选方案)

ini
[program:viswoole]
command=/usr/local/bin/php %(here)s/viswoole server:start
directory=/var/www/app
autostart=true
autorestart=true
startretries=3
user=www-data
redirect_stderr=true
stdout_logfile=/var/log/app/supervisor-viswoole.log
environment=APP_ENV="production"

安全加固清单

1. 网络层

  • 使用 HTTPS(SSL/TLS 终结在 Nginx)
  • 配置防火墙规则,仅开放必要端口
  • 禁止直接访问 Swoole 端口(9501 等),通过 Nginx 代理
  • 配置速率限制

2. 应用层

  • APP_DEBUG=false
  • 设置强密码的 APP_KEY
  • 配置 CORS 白名单
  • 移除或保护调试端点
  • 定期更新依赖包

3. 文件系统

  • .env 文件权限设为 600
  • runtime/ 目录权限设为 755
  • 禁止执行 vendor/config/ 下的 PHP 文件
  • 敏感文件不在 Web 根目录

4. 进程安全

  • 以非 root 用户运行(如 www-data)
  • 限制文件描述符数量
  • 配置 cgroup 资源限制