Gatewayworker奇异的RedisException-Redis连接异常问题

bv

Gatewayworker使用的是gateway-worker-for-win,版本:3.0.12
 
我遇到的奇异问题是,Gatewayworker没什么问题,在业务连接redis的时候,会造成第一次连接失败,第二次及以后连接都正常的问题产生。
 
情况说明:
 
我的redis初始化代码在onWorkerStart中:    

public static function onWorkerStart($businessWorker)
    {
        echo "Gatewayworker Start\n";
        ini_set('default_socket_timeout', -1); //redis不超时
        global $redis;
        $redis = new \Redis();
        $redis->connect('127.0.0.1', 6379);

redis业务代码在onmessage中,由客户端向gatewayworker发送message,触发服务端对redis进行操作。
 
问题是,当redis启动后,或者重启后,gatewayworker的events中的onmessage对redis进行的第一次操作,就会出现RedisException的问题,但是,不做任何处理,客户端继续发送message给gatewayworker,后面onmessage对redis的操作就一切正常了。
 
也就是说,只有在redis开启,或者重启后,gatewayworker第一次与redis进行操作是失败的,后续都是正常。
 
第一次操作失败的信息:
图片
 
说远程主机强迫关闭了一个现有连接,(有时候也会显示 Redis server went away),但实际上连接没有被关闭,那么可以肯定是是gatewayworker此时是无法与redis进行连接的。
 
排除法:
(1)redis连接错误或初始化错误,这个是不可能的,如果连接错误,会造成每次onmessage对redis操作都错误,但是现在是第一次错误,后面都正常。
(2)events业务代码错误,这个也是不可能的,因为除了第一次无法与redis连接外,后面都可以正常连接操作redis。
 
看到别人说在windows和mac os下会产生这种问题,在CentOS中正常,
 
是不是这是windows版gatewayworker的通病bug????
 
但也可能是window版本的Redis-x64-3.2.100的问题??

 
不知道如何解决,实在不行,只能等上线的时候,在centos里再观察看看了。
 
----2018年11月24日17:57:51 更新---------
 
刚刚又测试了一下,重启redis,然后
检查 redis 是否正常运行$ > redis-cli
$ > set test test
$ > get test测试发现,redis运行正常,redis没有问题,然后继续让客户端发送消息触发onmessage,然后依然是上面显示的连接错误。同样第二次再触发,就正常了。
所以redis错误的问题也可以排除,看来应该就是gatewayworker windows版的问题了吧。

5684 4 0
4个回答

walkor

之前并没有用户反馈过这个问题。不用gatewayWorker写个test.php,运行 php test.php 试下看下是否有问题

  • bv 2018-11-26

    嗯嗯,测试了,用test.php写了与onmessage里相同的redis使用代码,运行后是正常的。redis是没有问题的,应该还是gatewayworker的原因。

walkor

也就是说只有redis重启后才会有这个问题是吧?应该是redis被重启了,之前的redis连接无效了,再次使用这个redis连接的时候报了这个错误。
 
test.php 里可以这样测试

<?php
$redis = new \Redis();
 $redis->connect('127.0.0.1', 6379);
echo "睡眠20秒,这时候去重启redis\n";
sleep(20);
echo "睡眠完毕,尝试操作redis";
$redis->get('xxx');

 
运行脚本后去重启redis,然后脚本20秒后读写redis看下是否有问题
 

  • bv 2018-11-26

    谢谢大神指出问题原因,错误已解决,关于这个问题,我的看法写在下面的回复里了。

bv

感谢@https://wenda.workerman.net/people/walkor  在楼上指出的问题原因。
 
在@https://wenda.workerman.net/people/walkor 给出的 test.php 中,确实会出现read error on connection的错误,原因就是@walkor  所指出的redis 在重启以后,之前的redis连接失效。
 
但是在gatewayworker里,与test.php的代码机制不同。
 
在test.php 里,代码机制是先与redis连接成功,然后重启redis,然后才是redis连接失败。
 
而在gatewayworker的代码里,不仅仅是重启redis会有问题,在redis从未重启过的情况下,客户端通过events.php 中的onmessage 初次连接redis,就会产生连接失败的问题,而在test.php中,初次连接redis是不会产生连接失败的问题,只有重启redis才会连接失败。
 
所以,我觉得gatewayworker windows版在redis连接的处理上,还是有问题。

 
关于这个初次连接redis失败的问题,我用try { } catch (Exception $e) {}做了强制重连:
 
强制重连以后,客户端初次触发redis连接时,依然会产生“远程连接被关闭”的notice,但是后面在catch{}里做了二次重连,所以代码功能可以正常使用了,不会有连接失败造成redis数据缺损的问题了。
 
问题总结:
 
在gatewayworker windows版里,客户端初次触发onmessage的redis连接,会造成连接失败的情况,需要使用try { } catch (Exception $e) {}做强制重连,
 
感觉这还是gatewayworker windows版的一个bug,因为redis的初次连接失败,是在不涉及redis重启的情况下产生的。
 
以上是我个人的观点,再次感谢@walkor的帮助。

  • 暂无评论
walkor

你看下是不是redis服务端设置的timeout太短了,连接空闲时间到达了timeout设置的时间被redis服务端给关闭了。
 

  • bv 2018-11-26

    谢谢,timeout用的是默认值0,而且在onWorkerStart(){}里还加了ini_set('default_socket_timeout', -1); ,感觉不是timeout的问题,因为test.php是正常连接。

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