GatewayWorker没有按照预期断开连接导致客户端重连问题

binzhizhu

pingNotResponseLimit = 1
pingInterval = 60

60s内如果客户端没有发送任何数据,服务端则断开客户端连接

客户端已经做了重连策略,而且是每30s会发送一次心跳包到服务端,我看了一下Gateway的重连策略代码,大致的意思如下:

GatewayWorker进程启动的时候呢,如果有要求重连则设置一个定时器定期去检测客户端连接的心跳,如果在心跳检测时间内客户端有互动,则pingNotResponseCount=-1,否则pingNotResponseCount++,如果上次发送的心跳还没有回复次数大于限定值就断开

但是这样配置服务端还是会定时断开连接,不太明白,也就是说客户端一定要自己做重连策略了是吗?仅仅是定期发心跳包也是会断开连接?

3278 3 0
3个回答

walkor 打赏

断开连接不一定是心跳导致的。可能业务哪里断开了连接,这个需要你们自己具体分析。

如果想要测试框架的心跳设置,可以下载workerman-chat试下,避免因为业务代码问题导致误判。

另外更改完配置要restart才能生效,reload不生效。

  • binzhizhu 2021-03-17

    作者大大你好,刚刚我本地断点调试打印了一下,有一处实现不是很明白:

    我现在客户端的重连策略是这样的:

    var heartCheck = {
        timeout: 30 * 1000,
        timer: null,
        serverTimer: null,
        reset: function () {
            this.timer && clearTimeout(this.timer);
            this.serverTimer && clearTimeout(this.serverTimer);
        },
        start: function (ws) {
            console.info('heartCheck start',new Date());
            var that = this;
            this.reset();
            this.timer = setTimeout(function () {
                // console.log('发送心跳,后端收到后,返回一个心跳消息')
                // onmessage拿到返回的心跳就说明连接正常
                ws.send(JSON.stringify({heart: 1}))
                that.serverTimer = setTimeout(function () {
                    // 如果超过一定时间还没响应(响应后触发重置),说明后端断开了
                    ws.close()
                }, that.timeout)
            }, that.timeout)
        }
    };

    websocket连接成功、或者接受到服务端消息都会调用heartCheck.start重置一下,也就相当于如果在指定的心跳时间内如果服务端没有发送ACK心跳包给客户端,客户端也会自己断开。

        if ($ping_data) {
                    if ($connection->pingNotResponseCount === 0 ||
                        ($this->pingNotResponseLimit > 0 && $connection->pingNotResponseCount % 2 === 1)
                    ) {
                        continue;
                    }
                    $connection->send($ping_data, $raw);
                }

    这个GatewayWorker代码,pingNotResponseCount其实按照我的配置,如果是正常的情况应该一直都是0,因为接受到消息会重置-1,不会断开的话就会+1,然后如果我配置了ping_data,上面那个if就会直接跳过了,因为此刻pingNotResponseCount=0,所以服务端那时候没有发送ping_data给客户端,我这边客户端直接断了。

    其实不应该会发送ping_data的吗 ,现在是pingNotResponseCount=0,直接跳过了

binzhizhu

截图

其实期望服务端也要回应客户端ping_data,但是并没有,主要就是pingNotResponseCount 问题

  • 暂无评论
binzhizhu

http://doc2.workerman.net/heartbeat.html

我看了下心跳机制,是如果要求客户端必须发送心跳包,服务端就不会发送ping_data吗?因为pingNotResponseLimit >=1的时候 服务端没有下发ping_data。那这样的话,相当于服务端跟客户端自己协调一种方案了,如果说因为pingNotResponseLimit=1,只要确保客户端会定时发心跳包即可咯

  • walkor 2021-03-17

    一般不需要2端都发心跳,一端发就行。建议客户端发

  • binzhizhu 2021-03-17

    @1: 好的

年代过于久远,无法发表回答
×
🔝