编程 RoadRunner v3:http.middleware 改成从左到右执行,Kafka 重试也不再回写原 topic

2026-11-04 21:06:53

RoadRunner v3 升级笔记:中间件顺序反转、Goridge v4 与 Kafka 重试的静默变化

项目地址:

信源:v3.0.0(2026-10-08)与 v3.0.1(2026-10-21)release notes、roadrunner-php/cli v3.0.0、roadrunner-php/worker v3.8.0。

版本与插件体系

v3.0.0 切到 v6 的 Go 插件体系,Go 模块路径改为 github.com/roadrunner-server/roadrunner/v3。插件 API 的 protobuf schema、生成的 Go 消息、Go 插件契约拆到三个仓库:api、api-go/v6、api-plugins/v6。自定义插件要用 log/slog、pool/v2、goridge/v4。

v3.0.1 用 Go 1.27.3 修 crypto/x509 的 CVE-2026-111943:证书校验时会拒绝已知的不可信中间证书。如果链路里有自签或私有 CA 的中间证书,升级后可能直接握手失败。

http.middleware 的执行方向反了

请求现在按从左到右进入 http.middleware。旧行为是从右到左。如果从 v5 迁过来,要把原来的列表反转才能保持之前的顺序。

这条不会报错,中间件也都在执行,只是顺序变了。认证、限流、静态文件、代理头解析这类依赖先后关系的中间件要逐个核对。

http:
  address: 0.0.0.0:8080
  # 从左到右执行:proxy_ip_parser → rate_limiter → static
  middleware: [proxy_ip_parser, rate_limiter, static]
  # proxy_ip_parser 通过它选择转发头及其优先级
  trusted_headers: ["X-Forwarded-For", "X-Forwarded-Proto"]

proxy_ip_parser 依赖 http.trusted_headers 选择转发头及其优先级;PROXY protocol v1/v2 在 HTTP/HTTPS 监听器上可用,但要求显式配置可信代理地址。

Goridge v4 移除 MessagePack

Goridge v4 去掉 MessagePack,保留 JSON、protobuf、Gob 和 raw 负载。RPC 传输本身不变,影响面在 PHP 侧或自定义插件里显式依赖 MessagePack 编解码的代码。升级时全局搜一遍 msgpack 相关引用。

明文 HTTP/2 只支持 prior knowledge

H2C 改用 prior knowledge,不再支持 HTTP/1.1 的 Upgrade: h2c。客户端还走 Upgrade 握手时会退回 HTTP/1.1 或直接连不上。反向代理侧的 upstream 要按 prior knowledge 配置。

Kafka 重试进进程内优先级队列

被 requeue 或被 nack 要求重投的任务回到 RoadRunner 的优先级队列,驱动不再向源 topic 生产副本。由此产生几个后果:

  • 其他消费组收不到这次重试,重试只是本进程内的一次调度。
  • 驱动遵守请求的延迟,但重试在内存里等。
  • 一旦该分区更靠后的 offset 被提交,重启/崩溃后这条重试就丢了。

新增的 consume_partitions 可以直接消费指定分区与起始 offset。消费者遇到不可重试的 Kafka 错误(例如 broker 拒绝访问 topic、消费者被移出组)时,jobs 插件会重启 pipeline;配置的 pipeline 重启失败会让 RoadRunner 报错退出。

也就是说,不能把 topic 当成重试的持久化层。

envfile 与 max_workers 的语义变化

envfile 不用实验模式就能加载根目录的 envfile;一旦配置了文件,启动时该文件必须存在。以前缺文件可能静默跳过,现在会挡住启动。

自动扩缩容里,dynamic_allocator.max_workers 统计的是“在基础池大小之上新增的 worker 数”,不是 worker 总数。按旧语义写的数值会多起或少起 worker。自动扩容后会重试获取 worker,空闲 worker 的移除逻辑也改了。

server.on_init.env 里的值会覆盖继承来的值:

server:
  on_init:
    env:
      APP_ENV: production
      APP_DEBUG: "false"

其他行为变化

  • 默认插件容器新增 NSQ、HTTP 限流、Zstd 压缩、protobuf registry;TCP 插件需要自定义构建。
  • static 中间件:可配 URL 前缀、元数据缓存 TTL、缺失文件缓存 TTL、缓存容量;rr reset static 清缓存;弱 ETag 改用文件大小与修改时间生成。
  • rate_limiter:可按全局 / IP / header 键限流,被拒请求返回 429 并带 Retry-After。
  • grpc 插件:支持 reflection 发现服务、通过内置 Protoreg 取 PHP 服务描述符;失败的一元调用日志里带 google.rpc.Status 详情。
  • amqp 驱动:支持命名连接,静态 pipeline 需要 config.connection 和嵌套的 exchange/queue 设置,AMQP 的 config.version 移除;exchange/queue 声明可独立配置,便于使用无建队权限的账号。
  • jobs 插件:支持命名 worker 池,用 pool 头选择目标池;通过 RPC 提交时保留有效的 producer trace context;新增 rr_jobs_jobs_requeue 计数区分成功/失败/重入队。
  • nats 驱动:pipeline 停止时默认保留 stream 内容,除非开启删除;新增 ack_wait 控制 JetStream 重投时机。
  • sqs 驱动:FIFO 重试用新的 broker 去重 ID,避免重试被当作已删除原消息的重复项丢弃。
  • beanstalk 驱动:任务 header 会随存储和重试保留,包括 trace context 和命名池路由;已存在的旧消息无法补回未存过的 header。

PHP 侧的变化

roadrunner-php/cli 3.0.0 生成 RoadRunner 3 能接受的配置。tcp、websockets、broadcast、reload 插件移除,RoadRunner 3 不再提供。大量 Command/Configuration/Downloader 命名空间移入 Internal 且不再公开。

get-binary 与 download-protoc-binary 要求 RR_GITHUB_API_URL 为 https://api.github.com 或以 /api/v3 结尾;GHE 的 token 从 DLOAD_TOKEN_ 读取(如 DLOAD_TOKEN_GHE_EXAMPLE_COM)。依赖要求 symfony/console 与 symfony/http-client 6.4+。

roadrunner/worker v3.8.0 改名为 roadrunner/worker,要求 PHP 8.2。

复制全文 生成海报 RoadRunner PHP Go 队列

推荐文章

程序员茄子在线接单