按照官网配置redis,运行一段时间后出现链接断开问题,
Next RedisException: Connection closed in /abc/vendor/illuminate/redis/Connections/PhpRedisConnection.php:406
出现此问题,我测试会在两种情况下出现
<?php
#default_socket_timeout为默认值60
#第一种
$rds = new \Redis();
try {
$ret = $rds->connect("127.0.0.1", 6379);
if ($ret == false) {
echo "Connect return false";
exit;
}
//设置超时时间为 0.1ms
$rds->setOption(Redis::OPT_READ_TIMEOUT, 0.0001);
var_dump($rds->get("user_count"));
} catch (Exception $e) {
var_dump($e);
}
#第二种(运行以下代码,去手动杀掉redis链接)
$rds = new Redis();
try {
$ret = $rds->pconnect("127.0.0.1", 6379);
if ($ret == false) {
echo "Connect return false";
exit;
}
while (1) {
var_dump($rds->get("aa"));
}
} catch (Exception $e) {
var_dump($e);
}
第一种情况我们可以使用设置$rds->setOption(Redis::OPT_READ_TIMEOUT, -1); 不超时
或者修改default_socket_timeout为-1
但是第二种情况当网络出现闪断的时候就避免不了,最好加一个短线重连。
我看illuminate/redis 7.X 并没有短线重连功能,并且在配置文件里面 read_timeout 设置为 -1 会报错,因为它的 $client->setOption(Redis::OPT_READ_TIMEOUT, $config['read_timeout']);
参考:https://wenda.workerman.net/question/6311
参考这个文档给redis加一个定时心跳试下。
https://www.workerman.net/doc/webman#/db/heartbeat
redis正常的时候启动webman, 然后后把redis服务停掉,然后webman 再也连不上redis了,除非重启webman
加心跳也没用。
这样是不是可以说明手册上的 redis不用自动重连(redis底层已经实现自动重连)是错误的
redis扩展会自动重连。你的问题应该是连接被某个网络节点清理了,没有通知客户端(没有发fin包),客户端认为连接仍然存活,继续使用导致出错。比如用了阿里云的redis或者mysql服务,redis连接和mysql连接都会因为长时间不活跃被偷偷清理(不通知客户端那种),客户端不知道连接断开就不会重连,导致读写超时。解决办法就是定时加心跳,心跳间隔小于60秒。
redis扩展里面的重连是,连续重试10次,再链接不上就不会重连了。
这是我模拟网络差的情况。网络中断一次,那么如果webman 依赖redis的服务就不可用了,除非重启,我们开发的时候redis和webman用的一台机器,所以没有发现过此问题,但是我生产环境 redis 和webman 用的内网不同服务器,就会有此问题。
我还联想到webman中使用的rabbitmq会不会出现此类问题。
如果遇到网络闪断,或者redis挂掉后恢复了,webman操作redis 任然报错问题。
这是我的解决方案,大家以后遇到可以参考