每个 Worker 进程必须在 onWorkerStart 中 require_once autoload.php,因进程内存独立,主进程加载的 autoloader 不继承;PSR-4 映射无性能问题,Composer 已去重;切勿在 onRequest 中重复引入,开发需关 OPcache 并平滑重启 Worker。

Worker 进程里 require_once autoload.php 是必须的
每个 Worker 进程启动时,PHP 内存空间是独立的,vendor/autoload.php 不会跨进程共享。如果你只在主进程(比如 server.php 首行)引入一次,那后续 fork 出来的 Worker 进程里 AppHttpServer 这类自定义类就找不到——因为它们的 autoloader 没被加载。
正确做法是在 onWorkerStart 回调里显式引入:
require_once __DIR__ . '/vendor/autoload.php';
这不是“多此一举”,而是 Swoole 多进程模型下的必然要求。不这么做,Class not found 错误会在第一个请求就抛出。
PSR-4 映射在每个 Worker 中重复解析但无性能问题
PSR-4 的路径映射逻辑(如 "App\": "app/")本身不耗资源,它只是字符串替换 + 文件存在性判断。即使每个 Worker 都执行一遍 require_once vendor/autoload.php,也不会导致类文件重复加载或路径解析变慢。
真正影响性能的是类文件本身的 include_once 行为——而 Composer 的 autoloader 已内置去重机制,同一类在同一个进程内只会被 include 一次。
注意点:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 不要在
onReceive或onRequest里重复require_once autoload.php,那是浪费 CPU - 如果用了
--classmap-authoritative,所有类必须提前扫进autoload_classmap.php,否则 Worker 启动时直接报错,不会 fallback 到 PSR-4 -
autoload-dev中的路径(如tests/)若被意外载入,可能让 Worker 加载一堆测试类,徒增内存占用
OPcache 和类缓存会让修改代码“不生效”
Worker 进程常驻内存,一旦某个类被加载,PHP 就把它锁在 OPcache 和类表里。你改了 app/Http/Controller.php,不重启 Worker,它永远用旧版本。
开发阶段最稳妥的组合是:
- 设置
opcache.enable=0(CLI 和 FPM 的 php.ini 都要关) - 每次改完代码后执行
composer dump-autoload - 用
kill -USR1 $PID平滑重启 Worker,或直接kill $PID全局重启
别指望 opcache_invalidate() 能刷新已加载类——它只对未 include 的文件有效;Swoole 场景下,类几乎总是在 Worker 启动时就全量加载完了。
多个 Worker 加载同一份 classmap 可能触发竞态?
不会。classmap 是纯数据数组(return ['App\Foo' => '/path/Foo.php'];),读取过程无状态、无副作用。即使 100 个 Worker 同时执行 vendor/autoload.php,各自拿到的都是完整、一致的映射表。
真正的并发风险点不在 autoload 本身,而在你放在 onWorkerStart 里的初始化逻辑,比如:
- 用
fopen(..., 'a')往同一个日志文件写内容 → 需加锁或改用 SwooleLog - 往全局变量
$GLOBALS['db']赋值一个连接 → 没问题,因为每个 Worker 的$GLOBALS是隔离的 - 调用
new Redis()并connect()→ 没问题,连接属于当前进程,但要注意连接池更优
autoload 是安全的,但紧随其后的业务初始化不是——别把“自动加载”和“业务初始化”混为一谈。

















