2: 工作池
守护进程为每个应用程序保持一组常驻的 PHP worker。每个 worker 启动一次应用程序,然后处理多个请求,从而消除了单次路径所需的每次调用启动开销。这与 FrankenPHP 的 HTTP worker 模式是相同的理念,但适用于非 HTTP 工作。
2.1: 工作者协议
一个 worker 运行 php <app.php> phlo_serve,启动应用程序,然后逐个请求地从标准输入读取以换行符分隔的 JSON:
in {"id", "target", "args"?, "stream"?}
out {"t":"ready"} // once, after boot
{"id", "t":"line", "data"} // 0..N, only when streaming
{"id", "t":"done", "result"} | {"id", "t":"error", "message"} // exactly one, terminal
并发等于池大小:一个 worker 一次处理一个调用,守护进程将其余调用排队,直到有 worker 释放出来。
2.2: 每次调用重置
在调用之间,worker 会重置状态(phlo('tech/reset')、会话关闭、GC),就像 FrankenPHP worker 循环一样,因此一个调用不会泄漏到下一个调用中。编写安全的 worker 目标:在 static 中不存储请求或用户状态,并提交或回滚数据库工作。您明确标记的长连接 objPers 会保留;其他所有内容都会被清除。
2.3: 动态大小,回收
池的大小自动调整:当一个调用到达且没有空闲的工作者时,它会生成一个工作者,最多达到核心数量减一的全局上限,并在工作者闲置时回收一个工作者。没有任何配置。
应用程序是运行 one-shot(每个调用一个新的进程,保持热重载工作)还是在 resident pool(温暖的工作者,无需每个调用启动)是在 config/daemon.js 中按主机配置的(或在 CLI 调度中按调用配置):一个 build: true 的开发应用是 one-shot,发布应用是池化的。两个保护措施保持 resident pool 的健康:每个调用的超时(一个卡住的工作者会被杀死并重新生成)和回收(在一定数量的调用后替换工作者,以消除任何缓慢的泄漏)。在部署后,重启工作者以便它们重新加载新构建。
2.4: 健康
GET /health 在守护进程上报告了实时工作者总数与上限的对比,每个池按应用路径键入,按主机连接的套接字数量,以及配置的主机:
{
"status": "ok",
"workers": 5,
"cap": 7,
"pools": { "/srv/app/release/www/app.php": { "workers": 4, "busy": 1, "queued": 0 } },
"sockets": { "app.example.com": { "tokens": 12, "sockets": 18 } },
"registered": ["app.example.com", "dev.example.com"]
}
busy 是当前正在处理调用的 workers,queued 是等待空闲 worker 的调用;workers/cap 是当前活跃的总数与上限的对比。如果 busy 达到上限而 queued 还在增加,这意味着节点已达到容量:需要添加节点或增加更多核心。