无法实时从Redis读取数据

10

我有一个长时间运行的服务器应用程序,它存储这样的进程:

routes.php

Route::post('cloud/slice/{modelfileid}', 'CloudController@slice');
Route::get('cloud/slice/sliceProgress', 'CloudController@sliceProgress');

slice()函数的一部分:

while($s = fgets($pipes[2]))
{
    if(strpos($s, "Progress:") !== FALSE)
    {
        Log::info(100 * substr($s, -10, 4) . '%');
        $this->redis->SET('sliceProgress' . $uid, 100 * substr($s, -10, 4) . '%');

    }
}

我的客户端每0.5秒向 Redis 发出请求以获取进度,请求的代码如下:

public function sliceProgress()
{
    if (!isset($_SESSION["uid"]))
        return Redirect::to('cloud');
    $uid = $_SESSION["uid"];
    return Response::json(array('status' => 'success', 'data' => array('progress' => $this->redis->GET('sliceProgress' . $uid))));
}
and
$interval(function()
{
    $scope.refreshProgress();
}, 500);

但是客户端的进度请求会一直保持到100%结束,没有不到100%的进度。也就是说,当服务器分片应用程序完成时,我才获得进度响应。我认为,当Laravel处理分片时,它不会处理第二个请求。


编辑: 在redis->SET正常工作后,我使用以下代码在slice()中获取redis,这将实时输出sliceProgress。

Log::info($this->redis->GET('sliceProgress' . $uid));


完全不理解你的问题。请再试一次? - Someone Special
@SomeoneSpecial 现在检查一下。 - LF00
@KrisRoofe 你有什么问题吗? - Bara' ayyash
@Bara'ayyash,问题标题以及最后一条 - LF00
2个回答

2
我认为问题可能是会话锁。考虑您在多次GET调用之后发送了POST请求。现在,如果存在会话锁,则在第一个请求完成之前,PHP将不处理任何GET请求。
会话锁的工作原理是什么?PHP简单地锁定会话文件以进行读取,因此所有其他Apache进程都必须等待。Laravel也使用基于文件的会话管理。
现在删除会话锁并不是一个好主意,尽管您可以这样做。尝试从不同的主机或端口公开此Get服务。
我不确定Laravel如何处理会话锁,因此请交叉检查一下是否存在此问题。
删除会话锁: 第一种方法:在会话处理完毕后使用方法session_write_close。 第二:在使用session_start启动会话时,将read_and_close传递为true
不确定Laravel是否允许这样做。有其他实时进度同步的方法。

我在哪里可以找到会话锁的深入了解? - LF00

2

尝试在后台进程中运行此代码,例如异步队列或计划任务

while($s = fgets($pipes[2]))
{
if(strpos($s, "Progress:") !== FALSE)
{
    Log::info(100 * substr($s, -10, 4) . '%');
    $this->redis->SET('sliceProgress' . $uid, 100 * substr($s, -10, 4) . '%');

}
}

有关编程的内容,请将以下文字从英语翻译成中文。请仅返回翻译后的内容:某些解释可能更有帮助。非常感谢。 - LF00
尝试使用Laravel命令或异步队列来使用此包https://github.com/barryvdh/laravel-async-queue。 - Bara' ayyash
我认为你是正确的,你的建议是一个很好的实现。但我也想知道,为什么第二个请求会等待第一个请求完成。 - LF00
1
如果即使函数什么也不做,只是返回一个字符串,它也会等待,那么这意味着进程将被 sliceProgress 请求占用,并且在前一个请求解决之前无法提供任何服务。因此,如果您想要执行类似于 sliceProgress 的操作,应该在另一个进程中执行,这就是我建议使用命令和异步队列的原因。 - Bara' ayyash
1
通过使用 Laravel 作为长时间运行的应用程序,运行该应用程序的进程将具有相同的 ID。 - Bara' ayyash
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接