swoole 异步mysql连接池对象在数据库重启后重连时被拒绝如何解决?

我用的框架:SwooleDistributed 3, swoole 4.1, PHP7.1
这个框架是有mysql异步连接池的,按他的源码,连接池对象在失去连接后会重连的,一般没问题。
重连代码如下:

    public function query($sql, $client = null, MySqlCoroutine $mysqlCoroutine)
    {
        $notPush = false;
        $delayRecv = $mysqlCoroutine->getDelayRecv();
        if ($client == null) {
            $client = $this->pool_chan->pop();
            $client->setDefer($delayRecv);
        } else {//这里代表是事务
            $notPush = true;
            //事务不允许setDefer
            $delayRecv = false;
            $client->setDefer($delayRecv);
        }
        if (!$client->connected) {
            $set = $this->config['mysql'][$this->active];
            //(重点在这里,注释掉的是我调试的)
            //echo "\n\n";
            //print_r($client);
            //$client->close();
            $result = $client->connect($set);
            //ar_dump($result);
            if (!$result) {
                $this->pushToPool($client);
                $errcode = $client->errno ?? '';
                $mysqlCoroutine->getResult(new SwooleException(sprintf("[%s]%s,%s", $errcode, $client->connect_error ??'' , $client->error ?? '')));
            }
        }
        $res = $client->query($sql, $mysqlCoroutine->getTimeout() / 1000);
        if ($res === false) {
            $this->pushToPool($client);
            if ($client->errno == 110) {
                $mysqlCoroutine->onTimeOut();
            } else {
                $mysqlCoroutine->getResult(new SwooleException("[sql]:$sql,[err]:$client->error"));
            }
        }
        $mysqlCoroutine->destroy();
        if ($delayRecv)//延迟收包
        {
            $data['delay_recv_fuc'] = function () use ($client) {
                $res = $client->recv();
                $data['result'] = $res;
                $data['affected_rows'] = $client->affected_rows;
                $data['insert_id'] = $client->insert_id;
                $data['client_id'] = $client->id;
                $this->pushToPool($client);
                return $data;
            };
            return new MysqlSyncHelp($sql, $data);
        }
        $data['result'] = $res;
        $data['affected_rows'] = $client->affected_rows;
        $data['insert_id'] = $client->insert_id;
        $data['client_id'] = $client->id;
        if (!$notPush) {
            $this->pushToPool($client);
        }
        return new MysqlSyncHelp($sql, $data);
    }

运维要半夜维护mysql,是需要停机的,过一小段间后再启动。于是我们业务代码,也就是连接池里的对象,在他停机期间连接了mysql,很明显会失败.

问题来了:我进程内的连接池里有10个swoole异步连接对象,这些连接对象在mysql 停机期间去连接过mysql的,在mysql启动后再次去连接时就报了如下的错:

Connection refused. 111
MySQL server has gone away. 2006

然而,在mysql 停机期间没有去连接过mysql的对象 在 mysql启动后再次去连接是成功的。

上面描述可能有点费解,我举个例子:
我连接池有10个连接对象,mysql停机期间有4个尝试连接了(肯定是失败的),mysql启动后,其它6个对象可以正常重连,这4个对象再也连不上了。

发现这个问题,我都是费了很大的精力,也不知为啥 。
请哪个大牛来给我解释一下?

阅读 1.3k
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏