zhamao-robot / zhamao-framework

协程、高性能、灵活的聊天机器人 & Web 开发框架(炸毛框架)
https://framework.zhamao.xin
Apache License 2.0
158 stars 26 forks source link

onebot的ws链接在Worker启动前连接上 将无法触发@OnOpenEvent("qq")等注解事件 #278

Closed YiwanGi closed 1 year ago

YiwanGi commented 1 year ago

受影响版本

2.8.6

描述

rt 偶然发现机器人连接时可能会出现不触发连接注解事件 我在 Framework.php fun>>>registerServerEvents() 添加调试输出 image 可见 如在Worker启动前连接 \ZM\Event\EventManager::$events 数组为空 image 导致连接后事件分发未进行 image

复现步骤

频繁启停框架 多个onebot断连 偶尔(仅在Worker未启动前连接)出现

解决方案

事件未初始化完成前禁止ws接入

附加信息

No response

crazywhalecc commented 1 year ago

这算是一个 2.x 的根本性问题了。

首先,在 1.x 时期的单进程环境下,由于只有一个 Worker 进程,所以在连接保持方面,reload 重载 Worker 进程时也将连接断开。2.x 为了减少多进程重复连接次数,以及避免热更新时反复断开和连接,所以在这里对连接的维持做了分离。

2.x 中,连接是被保持在 Master 进程内的 Reactor 线程的,只有 Worker 进程就绪后,才可执行 WebSocketOpen 等事件(此类事件均在 Worker 进程内执行),所以当 Worker 进程没有准备好的时候,确实会无法触发相关事件。

解决方案在 3.0 有,但是 2.x 目前没有涉及。如果想保持在 Worker 进程未就绪前连接一定是断开的,可以在 WorkerStop 事件内遍历断开所有连接。

注意,由于 Swoole 的特性,在使用默认的包分配策略下,连接均被维持在一个进程空间,所以在循环断开所有连接时应仅让一个 Worker 进程发送断开。

crazywhalecc commented 1 year ago

另外,如果想保持连接,并在 WorkerStart 执行后继续执行 open 等事件,这个实现起来可能比较困难,需要用到协程。

crazywhalecc commented 1 year ago

此问题看起来不是一个 Bug,如果没有其他疑问,将在一天内关闭此 Issue。

YiwanGi commented 1 year ago

没有疑问 但框架停止再启动后如果会出现连接事件不触发的情况 还是感觉有点奇怪