有个常驻进程 监听rabbitmq队列,如果这个队列有信息进来就把这个信息保存到一个数据库表中,自打上线后发现个规律只能运行一小段儿时间正常,过一段时间后就无法保存数据库了,日志报异常
SQLSTATE[HY000]: General error: 2006 MySQL server has gone away
应该是数据库连接丢失了,理论上model应该有自动重连的机制,这个需要特殊配置吗?还是说有其他解决方案?
Model::create(['id'=>'123']); // 主要就这样保存的
SQLSTATE[HY000]: General error: 2006 MySQL server has gone away
"workerman/webman-framework": "~2.1",
"workerman/workerman": "~5.1",
SQLSTATE[HY000]: General error: 2006 MySQL server has gone away
这个报错的调用栈发下
不好意思,因为重启 日志被清空了,我这边再复现 给你发,先谢过
php-amqplib 是一个阻塞组件,阻塞过程中webman内核无法拿到进程控制权,无法发送心跳保持数据库连接。
哦哦 大概明白了,那如果是这种需求,需要使用 php-amqplib 这个类库连接rabbitmq,配合数据库的业务该如何做呢?
最简单的方法,数据库关闭连接的设置改长一点
这个脚本是常年运行的,即便是改长应该是 还有断开的时间 对吧?
它是连接空闲一定时间后断开的,保证这期间有处理业务就可以。
或者你装下swoole扩展,进程开启swoole协程试下。
也有开发者尝试用定时器去wait(), 参考https://www.workerman.net/q/8688
好的 谢谢 我看一下 非常感谢
回来报告一下消息:
按照walkor老大指引的开启了协程的方式,数据库开启了连接池,经过一晚的时间测试 还是没能解决问题:
配置如下:
监听的进程配置如下:
不用swoole了。
更新下
composer require webman/database:^2.1.3
,增加了重连。感谢 大佬~
问一下,这个新版是否兼容连接池的方式?因为我已经将rabbitmq 协程化加入了 连接池了,如果不用swoole的话得改回来~如果我更新到这个版本,是不是 不能兼容swoole的模式了?
兼容
好的 感谢
回来再报个信息,更新后今天大部分都正常,但是收到一个错误:
回来再报问题,经过这几天的测试发现上面提到的问题还是依然存在,大概现象就是,这个进程大概1天半的时间没有与数据库通信是静默状态没有数据推送过来,等到再次有数据推送过来的时候一定会报错:
"error":"PDO::prepare(): Send of 132 bytes failed with errno=110 Connection timed out
如果接下来继续有数据推送程序就正常处理,如果再次隔很久才有数据推送过来处理入库还是如上的报错。
Connection timed out 和 MySQL server has gone away 是不同的错误类型了。一个是发送数据超时,一个是连接断开。
你们用的什么数据库?云数据库?
不是云数据,服务器自己架设的mysql8.0,2点高可用
可能是你们系统有什么防火墙之类的把不活跃连接清理了,导致超时了。
刚看了下代码,PhpAmqpLib的wait()有超时参数,你们设置个超时,比如50秒。
超时后执行个SQL,这样和数据库定时通讯下,维持下连接。
好的,谢谢,我研究一下,就是 PhpAmqpLib的wait() 的时候有个捕获异常? 然后在执行sql?
求问,经过这几天的测试,还是这个问题,这种 timeout能否有什么方法手动去连接数据库呢?
PDO::prepare(): Send of 132 bytes failed with errno=110 Connection timed out
如果50秒和mysql通讯一次,还有 Connection timed out ,这个应该不是程序问题了。
50秒通讯一次该如何实现呢? 因为理论上mq的进程是阻塞试的,一单这个进程启动他就一直在 wait的状态了,这个状态下如何尝试50秒与数据库通讯一次?
另外我有个不明白的地方 理论上我启用的swoole模式下的连接池配置,理论上连接池会有心跳维持,当有数据库操作的时候不会出现连接timeout的状态因为连接池理论上是肯定有个min可用连接的,对吧?难道是连接池在这种自定义进程的模式下是不起作用的吗?
50秒通讯一次就是上面说的利用wait()的超时参数,超时后调用一次数据库。
连接从连接池里获取后没归还前不会调用心跳,连接没归还说明连接正在被使用,可能正在等待数据,发出心跳查询可能导致数据错乱,swoole和swow下会报错。
好的 明白了,谢谢