生产环境必须关闭 server:watch,因其会导致类重载混乱、注解缓存错乱、协程污染及进程行为不一致;ScanDir 配置运行时修改无效;watcher 在容器中不可靠且性能劣化,官方明确限定仅用于开发。

Hyperf 生产环境热更新根本就该关掉,server:watch 是开发专用机制,强行在生产跑只会触发不可控的类重载、注解缓存错乱和协程状态污染。
为什么生产环境不能开 server:watch
Hyperf 的 server:watch 依赖 hyperf/watcher 组件轮询文件变更并触发 reload,它会在运行时:
- 杀死当前 worker 进程并 fork 新进程,破坏长连接、定时任务、全局静态变量等生命周期
- 不清理 runtime/container/proxy 下已生成的代理类,导致新旧类定义混用(比如 #[Inject] 注入失败)
- 跳过 Di\ClassLoader::init() 的完整初始化流程,使部分注解(如枚举值上的 #[OA\Property])完全不被重新扫描
- 在 Swoole 多进程模型下,watcher 只作用于主进程,子 worker 仍运行旧代码,造成行为不一致
ScanDir 配置改了也没用,除非你停掉服务再重启
很多人以为改 config/autoload/scan.php 中的 paths 或 ignore_dirs 能让热更新“感知”新目录——但这是误解。该配置只在应用启动时被 ClassLoader 读取一次,用于构建初始扫描范围。运行中修改它:
- 对 server:watch 无影响(watcher 自己维护监听路径列表)
- 对生产环境的常驻进程更无意义(没 reload 就不会重新 scan)
- 若真要加扫描路径,必须:清空 runtime/container 和 runtime/cache,然后执行 php bin/hyperf.php start
Watcher 组件在生产部署中实际不可用
即使你手动安装 hyperf/watcher 并尝试在生产启用,也会立刻暴露硬伤:
- 它依赖 inotify 或 fsnotify,而多数容器环境(如 Docker with overlay2)不支持可靠文件监听
- 每次变更触发全量类重载,CPU 和内存抖动剧烈,QPS 直接下跌 30%+
- 日志里频繁出现 Class "X" not found 或 Cannot declare class X, because the name is already used,本质是 opcache + 类加载器未同步清理
- 官方文档明确标注:server:watch 仅限开发环境,生产应使用滚动发布或 Box 打包二进制后替换进程
真正需要“动态生效”的场景(如配置热加载),应该走 config-center(Nacos/ACM)或监听 Redis Pub/Sub 事件,而不是碰热更新这个开关。枚举注解失效这类问题,根源从来不是 Watcher 配置,而是你试图在不该 reload 的地方 reload。


















