Predis 给出“从服务器读取行时出错”

Posted

技术标签:

【中文标题】Predis 给出“从服务器读取行时出错”【英文标题】:Predis is giving 'Error while reading line from server' 【发布时间】:2012-07-31 08:09:16 【问题描述】:

我正在使用predis,它已订阅频道并正在收听。它会引发以下错误(如下)并在 60 秒后完全消失。这肯定不是我的网络服务器错误或超时。

here 正在讨论类似的问题。无法获得太多。

我尝试将 predis conf 文件中的 connection_timeout 设置为 0,但没有多大帮助。

另外,如果我继续使用(向它发送数据并处理)worker,它不会给出任何错误。所以它很可能在某个地方超时,而且连接也是如此。

这是我的代码 sn-p,它可能会产生错误,因为如果将数据提供给 worker,它会运行此代码并继续前进,之后不会产生错误。

$pubsub = $redis->pubSub();
$pubsub->subscribe($channel1);

foreach ($pubsub as $message)  //doing stuff here and unsubscribing from channel

追踪

php Fatal error:  Uncaught exception 'Predis\Network\ConnectionException' with message 'Error while reading line from the server' in Predis/Network/ConnectionBase.php:159 Stack trace:
#0 library/vendor/predis/lib/Predis/Network/StreamConnection.php(195): Predis\Network\ConnectionBase->onConnectionError('Error while rea...')
#1 library/vendor/predis/lib/Predis/PubSub/PubSubContext.php(259): Predis\Network\StreamConnection->read()
#2 library/vendor/predis/lib/Predis/PubSub/PubSubContext.php(206): Predis\PubSub\PubSubContext->getValue()
#3 pdf/file.php(16): Predis\PubSub\PubSubContext->current()
#4 main   thrown in Predis/Network/ConnectionBase.php on line 159

也检查了 redis.conf 超时,它也被禁用了。

【问题讨论】:

你可以使用 redis-cli 连接到 redis 吗? 是的,如果数据被处理,worker 也可以正常工作,如果它被放置 60 秒,它就会死亡并给出错误 【参考方案1】:

只需将read_write_timeout 连接参数设置为 0 或 -1 即可解决此问题。例如

$redis = new Predis\Client('tcp://10.0.0.1:6379'."?read_write_timeout=0");

设置连接参数是documented in the README。 Redis 的作者在an issue on GitHub 中指出了read_write_timeout 参数与此错误的相关性,他在其中指出:

如果您在类似守护进程的脚本中使用 Predis,如果您想完全禁用超时,则应将 read_write_timeout 设置为 -1(此值适用于旧版本和新版本的 Predis)。另外,请记住,您必须通过在 redis.conf 中设置 timeout = 0 来禁用 Redis 的默认超时,否则 Redis 将在 300 秒不活动后断开空闲客户端的连接。

【讨论】:

如果你使用 Laravel,在 Redis 数据库的 config/database.php 中添加 'read_write_timeout' => -1 对于heroku redis服务器,你必须使用CLI:heroku redis:timeout [redis-app-name] --seconds 0 --app [parent-app-name] 除了设置'read_write_timeout' => -1,运行php artisan config:clear。由于某种原因,laravel 正在缓存配置,并且此更改没有生效。 @Sangar82 在 config/database.php 中是什么键? @pilat 在您定义的每个 redis 服务器上。我在 ['redis']['default'] 和另一台服务器中有这个。['redis']['another_server']【参考方案2】:

我有类似的问题,更好的解决方案不是将超时设置为 0,而是使用指数退避并设置上限和下限。 将配置参数connection_timeout更改为0也可以解决问题。

【讨论】:

【参考方案3】:

我得到了问题的解决方案。因此,应用程序服务器可以连接到另一台机器上的特定应用程序的端口是有限制的。这些端口已经耗尽。 我们提高了限制,问题得到了解决。

我们是怎么知道这个问题的? 在 php 中,我们在创建套接字时收到“无法分配请求的地址”错误(错误代码 99)。

【讨论】:

【参考方案4】:

/etc/redis/redis.conf 处,设置

timeout = 0 

【讨论】:

【参考方案5】:

我正在使用 Heroku,并通过从 Redis Heroku 切换到 Redis Enterprise 插件解决了这个问题,然后:

use Predis\Client as PredisClient;

解决与 GuzzleHttp\Client 的冲突。你可以离开

作为 PredisClient

如果你不使用 GuzzleHttp 则行。

然后连接:

$redisClient = new PredisClient(array(
     'host' => parse_url(env('REDIS_URL'), PHP_URL_HOST),
     'port' => parse_url(env('REDIS_URL'), PHP_URL_PORT),
     'password' => parse_url(env('REDIS_URL'), PHP_URL_PASS)
)

);

(您可以在 Heroku 配置变量中找到自动预填充的“REDIS_URL”)。

【讨论】:

以上是关于Predis 给出“从服务器读取行时出错”的主要内容,如果未能解决你的问题,请参考以下文章

Laravel Horizo​​n - Redis - HAProxy - 从服务器读取行时出错

laravel5.4安装predis

predis连接redis sentinel的问题处理

使用 Predis 使用 Laravel-5.4.32 配置 AWS Elasticache redis Cluster-3.2.4

predis连接redis sentinel和redis cluster

安装redis 客户端predis