跳转至

PHP Worker 执行器

本文引用的文件列表
- src/executor/php_cgi_executor.v - src/upstream/transport/fastcgi.v - src/executor/lifecycle.v - src/executor/registry.v - config/vhttpd.example.toml - examples/config/laravel.toml - examples/config/wordpress.toml - README.md - docs/EXECUTOR_MODES.md - articles/03-php-apps.md - examples/wordpress/README.md

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能与调优
  8. 故障排除指南
  9. 结论
  10. 附录:配置与环境变量

简介

本文件聚焦于 vhttpd 中的 PHP Worker 执行器,系统性阐述其工作原理、FastCGI 协议实现、进程间通信机制、Worker 池管理与生命周期管理,并给出配置项与环境变量的说明。同时提供 Laravel、WordPress 等框架的集成部署示例,以及错误处理、性能优化与故障排除方法。

vhttpd 将“请求逻辑”抽象为可插拔的执行器(executors),其中 PHP 执行器通过外部 php-worker 进程以 Unix Socket 进行通信;此外还提供 php-cgi 执行器,通过 FastCGI 协议直接调用系统 php-cgi 进程,适用于传统 CGI 场景(如 WordPress)。

项目结构

围绕 PHP Worker 执行器的关键代码与配置分布如下: - 执行器实现与生命周期 - src/executor/php_cgi_executor.v:php-cgi 执行器实现(HTTP 请求经 FastCGI 转发) - src/executor/lifecycle.v:PHP Worker 与 php-cgi 的生命周期准备与启动/停止 - src/executor/registry.v:PHP 运行时命令构建与环境注入 - 传输层 - src/upstream/transport/fastcgi.v:FastCGI 编解码与响应解析 - 配置与示例 - config/vhttpd.example.toml:通用示例配置 - examples/config/laravel.toml:Laravel 站点示例 - examples/config/wordpress.toml:WordPress 站点示例 - articles/03-php-apps.md:PHP 应用集成实战文档 - examples/wordpress/README.md:WordPress 运行说明

graph TB
Client["客户端"] --> Ingress["HTTP 入口"]
Ingress --> Exec["执行器选择<br/>php / php-cgi / vjsx"]
Exec --> |php| Pool["ManagedWorkerPool<br/>Unix Socket 池"]
Exec --> |php-cgi| FCGI["FastCGI 编解码"]
FCGI --> PhpCgi["php-cgi 进程"]
Pool --> PhpWorker["php-worker 进程"]
PhpWorker --> App["PHP 应用/框架"]
PhpCgi --> App

图表来源 - src/executor/php_cgi_executor.v:42-82 - src/upstream/transport/fastcgi.v:79-249 - src/executor/lifecycle.v:97-134

章节来源 - README.md:84-126 - docs/EXECUTOR_MODES.md:25-76

核心组件

  • PhpCgiExecutor:对外暴露 HTTP 调度接口,内部通过 FastCGI 编码请求并发送至 php-cgi 进程,再解码响应返回给上层。
  • FastCgiCodec:实现 FastCGI Record 的编码与解码,组装标准 CGI 环境变量,支持分帧发送参数与请求体,并解析 stdout/stderr 输出为 HTTP 响应。
  • PHP Worker 生命周期:负责准备 worker 命令与环境变量、启动 ManagedWorkerPool、事件上报与优雅停止。
  • Registry:根据配置生成 php-cgi 启动命令,注入扩展与参数,并将 VHTTPD_APP 注入到 worker 环境。

章节来源 - src/executor/php_cgi_executor.v:1-118 - src/upstream/transport/fastcgi.v:1-386 - src/executor/lifecycle.v:84-154 - src/executor/registry.v:354-386

架构总览

下图展示了从 HTTP 请求进入 vhttpd,到最终由 php-cgi 执行并返回响应的完整流程。

sequenceDiagram
participant C as "客户端"
participant H as "vhttpd 入口"
participant E as "PhpCgiExecutor"
participant T as "FastCgiCodec"
participant P as "php-cgi 进程"
C->>H : "HTTP 请求"
H->>E : "dispatch_http(req)"
E->>T : "encode_request(method,path,headers,env_overrides)"
T-->>E : "FastCGI 请求字节流"
E->>P : "写入 Unix Socket"
P-->>E : "stdout/stderr + end_request"
E->>T : "decode_response(conn)"
T-->>E : "WorkerResponse(status, headers, body)"
E-->>H : "HttpLogicDispatchOutcome(response)"
H-->>C : "HTTP 响应"

图表来源 - src/executor/php_cgi_executor.v:42-82 - src/upstream/transport/fastcgi.v:79-249 - src/upstream/transport/fastcgi.v:266-317

详细组件分析

PhpCgiExecutor 组件

  • 职责
  • 选择目标 socket(按 kind=php-cgi)
  • 设置读取超时
  • 获取该 kind 的环境覆盖(例如 VPHP_WP_ROOT、VHTTPD_INDEX 等)
  • 调用 FastCgiCodec 编码请求并写入连接
  • 解码响应并释放 socket
  • 限制
  • 不支持 WebSocket、Stream、MCP 等高级能力(返回错误)
classDiagram
class PhpCgiExecutor {
+model() LogicExecutorModel
+kind() string
+provider() string
+admin_details() LogicExecutorAdminDetails
+warmup(app) void
+close() void
+dispatch_http(app, req) HttpLogicDispatchOutcome
+open_websocket_session(...)
+dispatch_stream(...)
+dispatch_mcp(...)
+dispatch_websocket_upstream(...)
+dispatch_websocket_event(...)
}
class FastCgiCodec {
+encode_request(...) []u8
+decode_response(conn) !WorkerResponse
}
PhpCgiExecutor --> FastCgiCodec : "使用"

图表来源 - src/executor/php_cgi_executor.v:1-118 - src/upstream/transport/fastcgi.v:76-317

章节来源 - src/executor/php_cgi_executor.v:42-96

FastCgiCodec 组件

  • 编码阶段
  • 构造 FCGI_BEGIN_REQUEST(responder 角色)
  • 组装标准 CGI 环境变量(REQUEST_METHOD、SCRIPT_FILENAME、DOCUMENT_ROOT、QUERY_STRING、HTTP_* 等)
  • 特殊处理 WordPress 场景:VPHP_WP_ROOT 存在时计算 SCRIPT_FILENAME 与 DOCUMENT_URI
  • 合并 env_overrides(过滤 HTTP_ 前缀与保留字段)
  • 分帧发送 FCGI_PARAMS(最大 65535 字节)
  • 分帧发送 FCGI_STDIN(请求体)
  • 解码阶段
  • 循环读取记录头、内容、padding
  • 聚合 stdout/stderr
  • 遇到 FCGI_END_REQUEST 结束
  • 解析 stdout 为 HTTP 状态码、头部与 Body(兼容 \r\n\r\n 或 \n\n)
flowchart TD
Start(["开始"]) --> Begin["构造 BEGIN_REQUEST"]
Begin --> Params["组装 CGI 环境变量<br/>合并 env_overrides"]
Params --> SendParams["分帧发送 PARAMS"]
SendParams --> Stdin{"有请求体?"}
Stdin --> |是| SendStdin["分帧发送 STDIN"]
Stdin --> |否| EndParams["发送空 PARAMS 帧"]
SendStdin --> EndParams
EndParams --> Loop["循环读取记录"]
Loop --> Type{"类型"}
Type --> |STDOUT| AppendStdout["追加到 stdout_buf"]
Type --> |STDERR| AppendStderr["追加到 stderr_buf"]
Type --> |END_REQUEST| ExitLoop["退出循环"]
Type --> |其他| Loop
AppendStdout --> Loop
AppendStderr --> Loop
ExitLoop --> Parse["解析 stdout 为 HTTP 响应"]
Parse --> Return(["返回 WorkerResponse"])

图表来源 - src/upstream/transport/fastcgi.v:79-249 - src/upstream/transport/fastcgi.v:266-317 - src/upstream/transport/fastcgi.v:320-376

章节来源 - src/upstream/transport/fastcgi.v:79-249 - src/upstream/transport/fastcgi.v:266-317 - src/upstream/transport/fastcgi.v:320-376

Worker 池与生命周期

  • 生命周期准备
  • 基于内置 spec 解析 PHP 运行时配置
  • 注入 worker 环境变量(包含 VHTTPD_APP)
  • 若未显式指定 worker_cmd,则自动生成(php-worker 或 php-cgi)
  • 启动与停止
  • 根据 autostart 决定是否启动 ManagedWorkerPool
  • 启动后上报 worker.started 或 worker.restart_scheduled 事件
  • 停止时统一关闭所有受管 worker
sequenceDiagram
participant L as "Lifecycle"
participant R as "Registry"
participant P as "ManagedWorkerPool"
L->>R : "resolve_php_runtime_config(args,cfg)"
R-->>L : "PhpConfig"
L->>L : "build_env(注入 VHTTPD_APP)"
alt worker_cmd 为空
L->>R : "php_cgi_runtime_build_command(php_cfg)"
R-->>L : "生成的命令字符串"
end
L->>P : "start(cmd, env, sockets, workdir)"
P-->>L : "返回受管 worker 列表"
L-->>L : "上报 worker.started/restart_scheduled"
Note over L,P : "stop 时统一关闭"

图表来源 - src/executor/lifecycle.v:84-154 - src/executor/registry.v:354-386

章节来源 - src/executor/lifecycle.v:84-154 - src/executor/registry.v:354-386

依赖关系分析

  • PhpCgiExecutor 依赖 transport.FastCgiCodec 完成请求/响应编解码
  • Lifecycle 依赖 registry 提供的命令构建与环境注入
  • 配置加载与路径/环境变量展开在配置模块中完成,影响 worker.cmd、worker.env、php.* 等字段
graph LR
A["PhpCgiExecutor"] --> B["FastCgiCodec"]
C["Lifecycle"] --> D["Registry"]
E["配置加载"] --> C
E --> A

图表来源 - src/executor/php_cgi_executor.v:42-82 - src/executor/lifecycle.v:84-154 - src/executor/registry.v:354-386

章节来源 - src/executor/php_cgi_executor.v:1-118 - src/executor/lifecycle.v:1-179 - src/executor/registry.v:354-386

性能与调优

  • Worker 池大小
  • 建议依据 CPU 核心数与 I/O 特性调整 pool_size
  • 超时控制
  • read_timeout_ms 控制 worker 读取超时,普通请求与长流式请求应分别设置
  • 队列容量与等待超时
  • queue_capacity、queue_timeout_ms 用于削峰填谷,避免瞬时峰值导致拒绝
  • 定期重启
  • max_requests 配合 restart_backoff_ms/max 防止内存泄漏累积
  • FastCGI 参数分帧
  • 大请求头/参数会被分帧发送,避免单帧过大导致的阻塞

章节来源 - config/vhttpd.example.toml:19-26 - docs/EXECUTOR_MODES.md:48-76 - src/upstream/transport/fastcgi.v:194-216

故障排除指南

  • 常见症状
  • Worker 池为空:启动后无可用 socket,会持续重试
  • 解码失败:FastCGI 响应格式异常或连接中断
  • 环境变量缺失:如 VPHP_WP_ROOT 未设置导致 WordPress 路径解析失败
  • 排查步骤
  • 查看 admin/workers 与 events.ndjson 中的 worker.error 事件
  • 检查 php-cgi 是否可执行、扩展是否正确加载
  • 校验 VHTTPD_APP、VPHP_WP_ROOT、VHTTPD_INDEX 等关键环境变量
  • 恢复操作
  • 重启单个或全部 worker
  • 调整 read_timeout_ms、pool_size、max_requests 等参数

章节来源 - src/executor/lifecycle.v:104-130 - src/executor/php_cgi_executor.v:69-76 - src/upstream/transport/fastcgi.v:311-317

结论

vhttpd 的 PHP Worker 执行器提供了两种模式: - php-worker:通过 Unix Socket 与外部 php-worker 进程通信,适合 PSR-7 应用与自定义入口 - php-cgi:通过 FastCGI 协议直接驱动系统 php-cgi,适合传统 CGI 应用(如 WordPress)

两者共享统一的执行器抽象与生命周期管理,便于运维观测与扩展。结合合理的超时、队列与池化配置,可在保证稳定性的前提下获得良好的吞吐与延迟表现。

附录:配置与环境变量

通用示例配置

  • 参考:config/vhttpd.example.toml
  • 关键字段
  • [server]:监听地址与端口
  • [files]:pid_file、event_log
  • [runtime]:timezone
  • [worker]:autostart、pool_size、socket/socket_prefix、read_timeout_ms、max_requests、restart_backoff_*
  • [executor]:kind = "php" 或 "php-cgi"
  • [php]:bin、worker_entry、app_entry、extensions、args
  • [worker.env]:向 worker 进程注入的环境变量

章节来源 - config/vhttpd.example.toml:1-67

Laravel 集成

章节来源 - examples/config/laravel.toml:1-23 - articles/03-php-apps.md:51-160

WordPress 集成

  • 配置文件:examples/config/wordpress.toml
  • 关键点
  • 使用 vphp-worker 作为 worker 入口
  • 设置 VHTTPD_APP 指向应用引导脚本
  • 设置 VPHP_WP_ROOT 指向 WordPress 根目录,以便正确解析 SCRIPT_FILENAME 与 DOCUMENT_URI
  • 运行说明:参见 examples/wordpress/README.md

章节来源 - examples/config/wordpress.toml:1-23 - examples/wordpress/README.md:1-46

环境变量与覆盖

  • 常用环境变量
  • VHTTPD_APP:PHP 应用入口(由 registry 自动注入)
  • VPHP_WP_ROOT:WordPress 根目录(用于 FastCGI 参数计算)
  • VHTTPD_INDEX:首页文件名(默认 index.php)
  • VHTTPD_TRACE_ID、VHTTPD_REQUEST_ID:追踪与请求标识
  • 行为说明
  • FastCGI 编码器会将 HTTP 头转换为 HTTP_* 环境变量
  • CONTENT_TYPE、CONTENT_LENGTH 不带 HTTP_ 前缀
  • env_overrides 会合并进 CGI 环境变量,但会过滤 HTTP_ 前缀与保留字段

章节来源 - src/executor/registry.v:354-360 - src/upstream/transport/fastcgi.v:101-180