Closed macle-abc closed 3 years ago
我不觉得这是 graia 的问题......hmmmmmmmmmmm
我不觉得这是 graia 的问题......hmmmmmmmmmmm ...我个人猜测是aiohttp心跳包没有成功所导致的,因为https://github.com/GraiaProject/Application/blob/a03a34dced116370831b1a4596f2cc2918dbae07/src/graia/application/init.py#L1363 实际上依赖了aiohttp,https://github.com/aio-libs/aiohttp/blob/master/aiohttp/client_ws.py#L239 不过仅仅是推测
目前想到的解决方法是用户自己设计一个超时时间,不依赖于aiohttp,定时重启进程。虽然我也不知道会发生什么...是否有更好的解决方案呢
我不觉得这是 graia 的问题......hmmmmmmmmmmm emmmmmmmm,确实,ws连接断开原来有人提出了这个问题,不过建议,可以采纳node.js的做法改为Python版本
我发现大部分依赖 mirai-api-http 的 WebSocket 接口的项目都存在这个问题。 大概因为,多数用作测试的机器人账号总能在五分钟内收到一条消息,这导致很难有人发现五分钟后连接会丢失。 即使发生,表面上看来也是令人头疼的毫无规律的 BUG。 目前的一个有效实践是,每分钟向服务端发送一个 ping 包。
ws.on('open', () => {
// 每 60s 发个心跳
const interval = setInterval(() => {
ws.ping((err) => {
if (err) {
throw error;
}
});
}, 60000);
ws.on('close', (code, reason) => {
// 关闭心跳
clearInterval(interval);
close(code, reason);
});
});
我发现大部分依赖 mirai-api-http 的 WebSocket 接口的项目都存在这个问题。 大概因为,多数用作测试的机器人账号总能在五分钟内收到一条消息,这导致很难有人发现五分钟后连接会丢失。 即使发生,表面上看来也是令人头疼的毫无规律的 BUG。 目前的一个有效实践是,每分钟向服务端发送一个 ping 包。
ws.on('open', () => { // 每 60s 发个心跳 const interval = setInterval(() => { ws.ping((err) => { if (err) { throw error; } }); }, 60000); ws.on('close', (code, reason) => { // 关闭心跳 clearInterval(interval); close(code, reason); }); });
graia 的 0.16.1 将尝试解决这个问题
在本地的测试中已经通过每 30s 一次的 ping 解决问题.
遇到的问题: 当距离发送最后一条群消息后,大概超过5分钟后发送一条群消息,Python程序会出现没有响应的情况,但是miria-api-http还是能成功获取到消息的
复现步骤: 该 BUG 会在进行以下操作后出现:
发生错误的代码
https://graia-document.vercel.app/docs/guides/features/kanata/kanata-readme 上述测试代码
控制台日志输出截图:
运行环境:
mirai-core
版本: "net.mamoe:mirai-console" version 2.0.0mirai-api-http
版本: "net.mamoe:mirai-api-http" version 1.9.6graia-application-mirai
版本: 0.15.0额外信息:
确切地说,问题应该叫做python程序阻塞在接收服务器推送的地方,
https://github.com/GraiaProject/Application/blob/a03a34dced116370831b1a4596f2cc2918dbae07/src/graia/application/__init__.py#L1363
async def websocket_daemon(self): while True: self.logger.info("websocket daemon: websocket connection starting...") try: await self.ws_all_poster() except aiohttp.client_exceptions.ClientConnectorError: self.logger.info( "websocket daemon: it seems that remote down, waiting for 10 seconds..." ) await asyncio.sleep(10) self.logger.info("websocket daemon: detected closed, restarting...")
async def ws_all_poster(self): async with self.session.ws_connect( str( URL(self.url_gen("all")).with_query( {"sessionKey": self.connect_info.sessionKey} ) ) ) as connection: self.logger.info("websocket: connected") while True: try: ws_message = await connection.receive() # 经过debug发现问题应该发生在这里
我尝试过使用timeout来设置超时,但是这样当服务器没有收到qq消息时,会导致python程序认为服务器没有推送消息而触发TimeoutError从而使得机器人重复回复消息