参考资料

  1. 按 2 核 2G 的标准,把你的 config/octane.php 调整好
  2. php --ri swoole 的输出可以看到
  3. Fresns 社区中用于解决 502 Bad Gateway 错误
  4. 占用 8000 的正是你之前启动的 octane 进程
  5. 网站引擎 API 地址配置有问题
  6. Nginx 无法连接到 Octane 监听的端口
  7. Swoole 6.2.2 扩展正在为 PHP 8.3 编译的过程
  8. Fresns 的请求头采用 X-Fresns-* 命名格式,主要用于身份认证和客户端信息传递

按 2 核 2G 的标准,把你的 config/octane.php 调整好

下面按 2 核 2G 的标准,把你的 config/octane.php 调整好。核心思路是:Worker 数量减半、GC 阈值调低、单包/缓冲调小,避免 2G 内存被撑爆。

<?php

use Laravel\Octane\Contracts\OperationTerminated;
use Laravel\Octane\Events\RequestHandled;
use Laravel\Octane\Events\RequestReceived;
use Laravel\Octane\Events\RequestTerminated;
use Laravel\Octane\Events\TaskReceived;
use Laravel\Octane\Events\TaskTerminated;
use Laravel\Octane\Events\TickReceived;
use Laravel\Octane\Events\TickTerminated;
use Laravel\Octane\Events\WorkerErrorOccurred;
use Laravel\Octane\Events\WorkerStarting;
use Laravel\Octane\Events\WorkerStopping;
use Laravel\Octane\Listeners\CloseMonologHandlers;
use Laravel\Octane\Listeners\CollectGarbage;
use Laravel\Octane\Listeners\DisconnectFromDatabases;
use Laravel\Octane\Listeners\EnsureUploadedFilesAreValid;
use Laravel\Octane\Listeners\EnsureUploadedFilesCanBeMoved;
use Laravel\Octane\Listeners\FlushOnce;
use Laravel\Octane\Listeners\FlushTemporaryContainerInstances;
use Laravel\Octane\Listeners\FlushUploadedFiles;
use Laravel\Octane\Listeners\ReportException;
use Laravel\Octane\Listeners\StopWorkerIfNecessary;
use Laravel\Octane\Octane;

return [

    // 默认服务器 swoole
    'server' => env('OCTANE_SERVER', 'swoole'),

    // 生产站点是 https://www.madama.cn,必须开启
    'https' => env('OCTANE_HTTPS', true),

    'listeners' => [
        WorkerStarting::class => [
            EnsureUploadedFilesAreValid::class,
            EnsureUploadedFilesCanBeMoved::class,
        ],

        RequestReceived::class => [
            ...Octane::prepareApplicationForNextOperation(),
            ...Octane::prepareApplicationForNextRequest(),
        ],

        RequestHandled::class => [
            //
        ],

        RequestTerminated::class => [
            FlushUploadedFiles::class,   // ✅ 及时释放上传临时文件,防止内存堆积
        ],

        TaskReceived::class => [
            ...Octane::prepareApplicationForNextOperation(),
        ],

        TaskTerminated::class => [
            //
        ],

        TickReceived::class => [
            ...Octane::prepareApplicationForNextOperation(),
        ],

        TickTerminated::class => [
            //
        ],

        OperationTerminated::class => [
            FlushOnce::class,
            FlushTemporaryContainerInstances::class,
            DisconnectFromDatabases::class,   // ✅ 避免长连接导致 MySQL 连接数爆满
            CollectGarbage::class,            // ✅ 主动触发 GC
        ],

        WorkerErrorOccurred::class => [
            ReportException::class,
            StopWorkerIfNecessary::class,
        ],

        WorkerStopping::class => [
            CloseMonologHandlers::class,
        ],
    ],

    'warm' => [
        ...Octane::defaultServicesToWarm(),
    ],

    'flush' => [
        //
    ],

    // Swoole Table 示例,若没用到可以删掉
    'tables' => [
        // 'example:1000' => [
        //     'name' => 'string:1000',
        //     'votes' => 'int',
        // ],
    ],

    // Octane Cache(Swoole Table),2G 内存下保守设置
    'cache' => [
        'rows' => 100,
        'bytes' => 1000,
    ],

    'watch' => [
        'app',
        'bootstrap',
        'config/**/*.php',
        'database/**/*.php',
        'public/**/*.php',
        'resources/**/*.php',
        'routes',
        'composer.lock',
        '.env',
    ],

    // GC 阈值:2G 内存场景设 20M,比 4G 时更激进
    'garbage' => 20,

    // 最大执行时间:60 秒(Fresns 处理图片/大请求可能较慢)
    'max_execution_time' => 60,

    'state_file' => env('OCTANE_STATE_FILE', storage_path('logs/octane-server-state.json')),

    /*
    |--------------------------------------------------------------------------
    | Swoole Options  ← 按 2核2G 标准调整
    |--------------------------------------------------------------------------
    */
    'swoole' => [
        'options' => [
            'worker_num'          => 2,                        // 2核 × 1,2G 内存下不要开 4 个
            'task_worker_num'     => 1,                        // 处理队列任务
            'max_request'         => 500,                      // 每 500 请求重启 Worker 防泄漏(比 1000 更勤)
            'package_max_length'  => 10 * 1024 * 1024,         // 10M 单包上限,2G 内存别开 20M
            'buffer_output_size'  => 2 * 1024 * 1024,          // 2M 输出缓冲
            'socket_buffer_size'  => 8 * 1024 * 1024,          // 8M socket 缓冲
            'enable_coroutine'    => true,                     // 开启协程
            'hook_flags'          => SWOOLE_HOOK_ALL,          // hook 所有阻塞 IO
            'reload_async'        => true,                     // 异步重启
            'max_wait_time'       => 60,                       // Worker 退出等待时间
            'http_compression'    => true,                     // 开启 gzip 压缩
            'log_level'           => SWOOLE_LOG_WARNING,       // 生产只记 warning 以上
        ],
    ],

    'roadrunner' => [
        'command' => env('OCTANE_ROADRUNNER_COMMAND', 'vendor/bin/roadrunner-worker'),
        'http_middleware' => env('OCTANE_ROADRUNNER_HTTP_MIDDLEWARE', 'static'),
    ],

];

关键改动说明(2核2G 对比原来的 4G 配置)

配置项原值(4G)新值(2核2G)原因
worker_num422 核开 4 个 Worker 会频繁上下文切换,且每个 Worker 常驻内存,2G 扛不住
task_worker_num11保持不变,队列任务不多
max_request1000500更早重启 Worker,防止内存泄漏累积
package_max_length20M10M2G 内存下单包 20M 风险太高
buffer_output_size4M2M输出缓冲减半
socket_buffer_size16M8Msocket 缓冲减半
cache.rows200100Swoole Table 行数减半
cache.bytes20001000单行字节数减半
garbage3020GC 阈值更低,更早回收内存

额外建议(2核2G 必做)

  1. 加 Swap:2G 物理内存跑 Octane + MySQL + Redis 很容易 OOM,建议至少加 2G Swap:

    fallocate -l 2G /swapfile && chmod 600 /swapfile && mkswap /swapfile && swapon /swapfile
    echo '/swapfile none swap sw 0 0' >> /etc/fstab
  2. MySQL / Redis 与本机分离:如果 MySQL、Redis 和 Octane 挤在同一台 2G 机器上,强烈建议把数据库迁到外部,否则 2G 根本不够。

  3. 启动命令建议:

    php artisan octane:start --server=swoole --workers=2 --task-workers=1 --max-requests=500

    注意:config/octane.php 里的 swoole.options 优先级高于命令行参数,两者保持一致即可。

  4. 监控内存:上线后用 htop 观察,如果单个 Worker 常驻内存超过 150M,需要继续下调 max_request 或排查内存泄漏。

作者:王壹杰
时间:2026-10-02 11:27:17
来源:https://fresns.ciilii.com/