关于webman文档中推荐的redis问题

0

截图


按照官网配置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']);

已邀请:

walkor

赞同来自:

参考这个文档给redis加一个定时心跳试下。
https://www.workerman.net/doc/webman#/db/heartbeat

张先生

赞同来自:

这是我模拟网络差的情况。网络中断一次,那么如果webman 依赖redis的服务就不可用了,除非重启,我们开发的时候redis和webman用的一台机器,所以没有发现过此问题,但是我生产环境 redis 和webman 用的内网不同服务器,就会有此问题。

张先生

赞同来自:

我还联想到webman中使用的rabbitmq会不会出现此类问题。

张先生

赞同来自:

<?php

/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/

namespace support\bootstrap;

use support\exception\BusinessException;
use Webman\Bootstrap;
use Illuminate\Redis\RedisManager;

class Redis implements Bootstrap
{

/**
* @var RedisManager
*/
protected static $_manager = null;

/**
* @param \Workerman\Worker $worker
* @return void
*/
public static function start($worker)
{
if (!class_exists('\Illuminate\Redis\RedisManager')) return;
$config = config('redis');
static::$_manager = new RedisManager('', 'phpredis', $config);
self::connection()->setOption(\Redis::OPT_READ_TIMEOUT, -1); #这里设置为读取不超时
}

/**
* @param string $name
* @return \Illuminate\Redis\Connections\Connection
*/
public static function connection($name = 'default')
{
return static::$_manager->connection($name);
}

/**
* @param $name
* @param $arguments
* @return mixed
*/
public static function __callStatic($name, $arguments)
{
#这里修改为断线后重新创建对象
try {
return static::$_manager->connection('default')->{$name}(... $arguments);
} catch (\RedisException $ex) {
self::start(null);
log_write('redis 重新创建对象');
return static::$_manager->connection('default')->{$name}(... $arguments);
}
}
}

如果遇到网络闪断,或者redis挂掉后恢复了,webman操作redis 任然报错问题。
这是我的解决方案,大家以后遇到可以参考

要回复问题请先登录注册