Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/244.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 使用redis实现消息队列时出错,使用BLPOP时出错_Php_Redis_Message Queue_Phpredis - Fatal编程技术网

Php 使用redis实现消息队列时出错,使用BLPOP时出错

Php 使用redis实现消息队列时出错,使用BLPOP时出错,php,redis,message-queue,phpredis,Php,Redis,Message Queue,Phpredis,我正在尝试使用Redis构建消息队列。 每当客户机发送新数据时,都会将其添加到列表中 这是它的代码 $client->lPush("my_queue", $data); 现在有一个单独的脚本slave.php,它弹出新到达的数据并对其进行处理。 slave.php的代码 while (true) { list($queue, $message) = $client->brPop(["my_queue"], 0); /* Logic to process t

我正在尝试使用Redis构建消息队列。 每当客户机发送新数据时,都会将其添加到列表中

这是它的代码

$client->lPush("my_queue", $data);
现在有一个单独的脚本slave.php,它弹出新到达的数据并对其进行处理。 slave.php的代码

while (true) {
   list($queue, $message)  = $client->brPop(["my_queue"], 0);

    /*
    Logic to process the data
    */
}
我已经修改了apache启动脚本,以便slave.php可以使用apache启动和停止。它工作得很好。但等待几分钟后,brPop停止侦听,并显示如下错误消息:

Uncaught exception 'Predis\Connection\ConnectionException' with message 'Error while reading line from the server [tcp://127.0.0.1:6379]' in /var/www/api/lib/predis-0.8/lib/Predis/Connection/AbstractConnection.php:139
Stack trace:
#0 /var/www/api/lib/predis-0.8/lib/Predis/Connection/StreamConnection.php(205): Predis\Connection\AbstractConnection->onConnectionError('Error while rea...')
#1 /var/www/api/lib/predis-0.8/lib/Predis/Connection/AbstractConnection.php(128): Predis\Connection\StreamConnection->read()
#2 /var/www/api/lib/predis-0.8/lib/Predis/Connection/AbstractConnection.php(120): Predis\Connection\AbstractConnection->readResponse(Object(Predis\Command\ListPopLastBlocking))
#3 /var/www/api/lib/predis-0.8/lib/Predis/Client.php(227): Predis\Connection\AbstractConnection->executeCommand(Object(Predis\Command\ListPopLastBlocking))
#4 /var/www/api/lib/slave.php(7): Predis\Client->__call('brPop', Array)
#5 /var/www/api/lib/slave.php(7): Predis\Client->brPop(Array, 0)
#6 {main}
 thrown in /var/www/api/lib/predis-0.8/lib/Predis/Connection/AbstractConnection.php on line 139
function process_data()
{
    try {
        $client = new \Predis\Client();

        require_once("logger.php");

        while (true) {
            list($queue, $message) = $client->brPop(["bookmark_queue"], 0);
            // logic
        }
    } catch (Exception $ex) {
        $error = $ex->getMessage();
        log_error($error, "slave.php");
        process_data(); // call the function recursively if connection fails
    }
}
process_data(); // call the function
根据文档,如果列表为空,则BLPOP/BRPOP会阻止连接,直到另一个客户端对其中一个键执行LPUSH或RPUSH操作。 但我的情况并非如此。 在我的例子中,一旦brpop阻塞了连接,即使新数据到达列表中,它也不会再次侦听


我应该做些什么改变才能让这项工作正常进行?

这项工作现在对我有效,但我不确定这是否是正确的方法。现在,我捕获错误并在连接失败的情况下递归调用该函数。我的新slave.php如下所示:

Uncaught exception 'Predis\Connection\ConnectionException' with message 'Error while reading line from the server [tcp://127.0.0.1:6379]' in /var/www/api/lib/predis-0.8/lib/Predis/Connection/AbstractConnection.php:139
Stack trace:
#0 /var/www/api/lib/predis-0.8/lib/Predis/Connection/StreamConnection.php(205): Predis\Connection\AbstractConnection->onConnectionError('Error while rea...')
#1 /var/www/api/lib/predis-0.8/lib/Predis/Connection/AbstractConnection.php(128): Predis\Connection\StreamConnection->read()
#2 /var/www/api/lib/predis-0.8/lib/Predis/Connection/AbstractConnection.php(120): Predis\Connection\AbstractConnection->readResponse(Object(Predis\Command\ListPopLastBlocking))
#3 /var/www/api/lib/predis-0.8/lib/Predis/Client.php(227): Predis\Connection\AbstractConnection->executeCommand(Object(Predis\Command\ListPopLastBlocking))
#4 /var/www/api/lib/slave.php(7): Predis\Client->__call('brPop', Array)
#5 /var/www/api/lib/slave.php(7): Predis\Client->brPop(Array, 0)
#6 {main}
 thrown in /var/www/api/lib/predis-0.8/lib/Predis/Connection/AbstractConnection.php on line 139
function process_data()
{
    try {
        $client = new \Predis\Client();

        require_once("logger.php");

        while (true) {
            list($queue, $message) = $client->brPop(["bookmark_queue"], 0);
            // logic
        }
    } catch (Exception $ex) {
        $error = $ex->getMessage();
        log_error($error, "slave.php");
        process_data(); // call the function recursively if connection fails
    }
}
process_data(); // call the function

在连接字符串中添加
?read\u write\u timeout=-1

问题不在于您的Redis配置,而是您必须更改
php.ini
设置和设置

default_socket_timeout = 90 //Or whatever you would like to set

是PHP在达到最大套接字超时时断开套接字连接。

我建议确保两个脚本都连接到同一数据库上的同一个Redis实例。它应该会起作用。此外,设置无限超时也是一种不好的做法。最好等待10秒钟,然后处理/忽略代码中的空结果。是的。两个脚本都连接到同一数据库上的同一个redis实例。正如我所提到的,它在几分钟内运行良好。但在等待几分钟后,它会阻塞连接,不再侦听。关于等待10秒,我们可以这样做,但我认为BLPOP有一些特性,通过这些特性,每当列表中出现新数据时,从脚本就会发现。另外,发出不必要的空请求也会增加服务器负载。如果每10秒检查一次,则每200亿或300亿个周期会添加一些额外的指令。这并不重要,但会使您的服务更可靠。迪迪埃是对的;这是在Redis中阻止POP的标准做法。请确保您的生产者(LPUSH)和消费者(BRPOP)使用单独的连接。另外,在
while
循环中,捕获任何异常,必要时重新连接(Predis是否自动执行此操作),然后继续循环。这已经超过一年了。您是否找到了避免异常的方法(比如为
$client
设置超时时间等)?@ManuManjunath请检查下面的答案,以了解原因。如果这是简单的答案,则不应删除。我会等待OP批准或否决答案,但看起来仍然很糟糕。我们本可以对此作进一步的解释