frankenphp本身不参与mercure消息推送链路,仅负责将publish请求转发给独立mercure服务,端到端延迟(30–120ms)主要由mercure服务分发、客户端eventsource重连、网络拓扑及jwt验签等环节决定。

FrankenPHP 本身不直接决定 Mercure 消息延迟,延迟主要由底层 HTTP/2 推送机制、事件循环调度、网络栈和 mercure.rocks 或自建 mercure 服务的实现决定。实测端到端延迟(从 publish 调用到浏览器 EventSource 收到)通常在 30–120ms 区间,但需具体看部署结构。
为什么不能只看 FrankenPHP?
FrankenPHP 是 PHP 运行时 + SAPI 层,它把 Mercure 的 Publish 请求转发给独立的 mercure 二进制(或 Docker 容器),真正的消息广播由 mercure 服务完成。FrankenPHP 只影响「发布请求的处理耗时」,不参与推送链路。
- 如果你用
curl -X POST直连mercure的/.well-known/mercure,延迟几乎不变 - 如果通过 FrankenPHP 的
mercure.Publish()(如用symfony/mercure-bundle),会多一次 PHP → HTTP 的往返,增加约 5–20ms(取决于本地网络栈) - HTTP/2 Server Push 在 FrankenPHP 中默认启用,但 Mercure 实际走的是
text/event-stream,不依赖 Push,所以这个特性对延迟无实质帮助
真实延迟瓶颈在哪?
实测中,以下环节贡献主要延迟:
-
mercure服务的事件分发:使用libevent,单核吞吐高,但若订阅者 > 500 且跨节点,延迟可能跳至 200ms+ - 客户端
EventSource的重连策略:默认 3s 重试,首次连接建立常有 100–300ms TCP/TLS 握手开销 - FrankenPHP 所在机器与
mercure服务是否同机:跨容器或跨主机时,Docker 网络或 Kubernetes Service 增加 1–10ms 不稳定抖动 - JWT 签名验证开销:若用
HS256且密钥短,可忽略;但ES256验签在低配 VPS 上可达 8–15ms
怎么快速验证你环境的真实延迟?
别信文档,用这个最小闭环测:
curl -s -H "Authorization: Bearer $(jwt encode --secret 'foo' --iss 'example' --exp '+1h' '{\"mercure\":{\"subscribe\":[\"https://example.com/news\"]}}')" \
http://localhost:8080/.well-known/mercure | head -c 100
然后在另一个终端跑:
time curl -N -H "Accept: text/event-stream" \
-H "Authorization: Bearer $(jwt encode --secret 'foo' --iss 'example' --exp '+1h' '{\"mercure\":{\"subscribe\":[\"https://example.com/news\"]}}')" \
"http://localhost:8080/.well-known/mercure"
再立刻执行:
curl -X POST -H "Authorization: Bearer $(jwt encode --secret 'foo' --iss 'example' --exp '+1h' '{\"mercure\":{\"publish\":[\"https://example.com/news\"]}}')" \
-F "data={\"msg\":\"test\"}" \
http://localhost:8080/.well-known/mercure
观察第二条 curl -N 输出时间戳与第三条 POST 发出时刻的差值 —— 这就是你当前环境的典型端到端延迟。
容易被忽略的配置点
很多人卡在看似“没延迟”其实根本没收到消息,本质是配置错位:
-
mercure.publish_url和mercure.subscribe_url必须严格一致(包括协议、host、port),FrankenPHP 的$_SERVER['HTTP_HOST']可能带端口,而 mercure 默认监听:8080,但返回的Location头却写成http://localhost/news -
mercure的-allowed-origins若设为*,某些版本会拒绝带凭证的请求,导致 SSE 连接静默失败 - FrankenPHP 的
fastcgi_finish_request()不影响 Mercure,因为它是异步 HTTP 调用,不是 PHP 后台任务
延迟数字本身不重要,关键是你能否在 100ms 内确认消息已送达目标客户端 —— 这需要在客户端加 eventsource.onmessage 时间戳打点,而不是只信服务端日志。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











