hyperf 的 hyperf/config-apollo 默认启用 long_polling 模式,但长轮询请求失败(如返回 504)会退回到被动轮询或暂停监听,导致配置更新延迟;需检查 pulltimeout、interval、apollo_server 地址、namespaces 一致性、strict_mode 及 runtime/config-apollo 缓存目录状态。

Long Polling 请求失败会直接导致配置更新延迟
Hyperf 的 hyperf/config-apollo 默认启用长轮询(LONG_POLLING)模式,但一旦长轮询请求失败(比如返回 504 Gateway Timeout),客户端会退回到被动轮询或暂停监听,造成配置变更无法及时触达。你看到的日志 Long polling failed, will retry in 1 seconds 就是典型信号。
- 检查
apollo.php中的pullTimeout和interval是否合理:默认pullTimeout=10秒,但 Apollo 服务端长轮询超时通常是 30 秒,若网络链路中有 Nginx/网关,其proxy_read_timeout必须 ≥30 秒,否则会主动切断连接并返回 504 -
interval是 fallback 轮询间隔(单位秒),不建议设为0或过小(如1),否则在长轮询中断期间会造成高频无效请求,加重服务端压力 - 确认
APOLLO_SERVER地址可直连 ConfigService,避免经由 Portal 或 AdminService 域名——后者不支持长轮询接口/notifications/v2
为什么 config() 读取不到最新值?不是 Apollo 没推,而是没触发监听
Hyperf 的 ConfigInterface 是单例且 runtime 可调用,但前提是你要确保配置已成功拉取并合并进内存。如果长轮询卡住,config('xxx') 返回的仍是上次成功加载的快照,不是“失效”,而是“未刷新”。
- 不要依赖
@Value注入字段做动态配置——它只在 Bean 初始化时读一次,后续 Apollo 变更完全不影响该变量值 - 验证当前生效的配置版本:在代码中加一行
var_dump(config()->get('apollo.last_sync_time'));(如果存在该 key)或手动调用config()->get('database.default.host')看是否与 Apollo 控制台一致 - 检查
listeners.php是否注册了Hyperf\ConfigApollo\Listener\FetchConfigOnBootListener和OnPipeMessageListener,缺一不可;后者负责跨 Worker 进程同步变更事件
strict_mode=false 会掩盖 namespace 加载失败问题
当 Apollo 中某个 namespace(如 redis)不存在或权限不足时,strict_mode=false 会让驱动静默跳过,不报错也不拉取,但日志里也不会提示。结果就是你改了 redis.default.host,却始终读不到新值。
- 上线前把
strict_mode临时设为true,启动时立即暴露缺失的 namespace,避免线上“看似正常实则漏配” - 检查
namespaces数组是否与 Apollo 控制台实际发布的 namespace 完全一致(注意大小写、空格、后缀如.properties) - Apollo 的 namespace 名称若含特殊字符(如
+、.),需 URL 编码处理;例如日志中出现RD-SHIFT.nacos+application,说明客户端尝试合并两个 namespace,但服务端可能只认其中一个
本地缓存文件损坏会导致长轮询永久失效
Hyperf 的 ApolloDriver 会在 runtime/config-apollo/ 下生成缓存文件(如 application.properties.json)。如果该目录被清空、权限错误或文件内容损坏,驱动可能无法恢复状态,反复 fallback 到低效轮询。
- 定期检查
runtime/config-apollo/目录是否存在、可写,且文件 mtime 与 Apollo 发布时间接近 - 遇到长期不更新时,可手动删除该目录下所有文件,重启服务强制重拉——不是清 Redis 或 Swoole Table,而是清这个本地磁盘缓存
- 生产环境建议将
runtime/config-apollo/挂载为独立卷,避免容器重建后丢失缓存上下文
pullTimeout 没被中间件截断、namespaces 没拼错、缓存目录没锁死。











