Laravel Flysystem 和 Rackspace CRON 上传失败并显示 401,而按需上传正常

Laravel Flysystem & Rackspace CRON uploads fail with 401 while on-demand uploads work

我们的系统每小时生成各种发票并将其上传到云端。也可以通过单击我们前端的按钮按需创建发票。

当手动请求创建上述发票时,它永远不会上传失败。 至于 cron 在一段时间后生成的发票,所有上传都失败了:

Client error response
[status code] 401
[reason phrase] Unauthorized
[url] https://storage101.dfw1.clouddrive.com/v1/MossoCloudFS_930575/ <...> .pdf" @ Guzzle\Http\Exception\BadResponseException->factory 

这应该意味着令牌已过期,它可能已经过期。 Rackspace 令牌持续 24 小时,但 Laravel 的存储应自动刷新令牌。


现在在这里了解一些有趣的事实:

1) 每次使用 Capistrano 部署我们的代码时,令牌似乎都会刷新,并且 cron 上传会再次工作一段时间。这里需要注意的重要一点是,每次部署都会创建一个类似于此的新文件夹 /releases/201605190925 提取代码,从头开始安装依赖项,如果一切顺利,则将此文件夹与 Apache 显示的文件夹进行符号链接。

2) Laravel 作业在与 www-data

不同的进程中处理

3) 部署后上传工作是否超过 24 小时很难追踪。我怀疑有时它的作用不止于此。但很难追踪,因为并非每个小时都有需要生成的发票。部署的开发人员比我等更多

4) 当 cron 失败并且我收到失败通知时,我可以立即去成功生成发票。在那之后,cron 仍然失败。所以这两个实例似乎在某处存储了不同的令牌。

5) php artisan cache:clear 缓存清理似乎没有任何影响

6) 可能已经尝试重启 Apache 服务但没有结果

因为它已经持续了一段时间,所以我已经测试了各种东西,甚至有一次联系了 Rackspace,但他们从他们那里找不到任何奇怪的东西......提醒我只是为了捕捉 401 错误,更新令牌并重试。但是 Laravel 和 Flysystem 应该自己在某个地方处理它

因为 Flysystem、Laravel 和 Rackspace 似乎都没有其他人遇到类似问题,所以我怀疑这是 cron 进程的某种独特问题。我只是希望很快我们就可以准备好系统的重构版本,问题就会消失。至于现在还在开发中,可能还需要一个月。


不要认为它与代码有关,但无论如何这是上传行:

Storage::put($folder . '/' . $filename, file_get_contents($filePath));

这是我们的配置:

'default' => 'rackspace',

'disks' => [
    'rackspace' => [
        'driver'    => 'rackspace',
        'username'  => ' ... ',
        'key'       => ' ... ',
        'container' => ' ... ',
        'endpoint'  => 'https://identity.api.rackspacecloud.com/v2.0/',
        'region'    => 'DFW',
    ]
]

如有任何想法,我们将不胜感激。

我也遇到过类似的问题。这个问题的文档和错误率似乎相当低。阅读此处 (https://github.com/rackspace/php-opencloud/issues/427),令牌过期似乎是根本原因。

上面 link 的建议是通过

重新验证客户端
$client->authenticate();

但是,客户端被埋没在少数命令之下。您应该能够通过

访问底层客户端
Storage::disk('my-disk')->getDriver()->getAdapter()->getContainer()->getClient()->authenticate();

不幸的是,我在尝试时遇到了 35 curl 错误 (SSL_CONNECT_ERROR)。

有一个

hasExpired()

方法也可用。如果您遇到相同的错误,您应该能够将此检查与某种机制结合起来以重新启动 cron 作业或 worker。虽然这肯定远非理想的解决方案,但它应该能让你起床 运行。你会认为这种行为会被自动捕获和处理。


5/25 更新:又花了几个小时试图在这里找到解决方案后,我认输了,只是创建了一个 cron 作业来每隔一段时间重新启动相关的工作人员12小时。据说令牌的有效期为 24 小时(根据 ),因此 12 小时 window 应该可以安全地防止错误发生。虽然超级 hacky,但它确实保持了该网站的一部分并且 运行.

在这里,我在将近 2.5 个月后再次尝试找到问题的解决方案。当我重读@Tommmm 更新时,我认为这次真的很成功。

所以你重新启动了工作队列,我开始思考我 运行我 supervisor/workers 的方式。

php artisan queue:work database --daemon --sleep=10 tries=3


--Daemon(因为它在 Whosebug post by @the-shift-exchange 中得到了很好的解释)

在 Laravel >=4.2 中添加了 --daemon 命令。它的工作方式是直接保持 运行ning 队列,而不是在处理完每个队列后重新启动整个框架。这是一个可选命令,可显着减少队列的内存和 cpu 要求。

--daemon 命令的重要一点是,当您升级应用程序时,您需要专门使用 queue:restart 重新启动您的队列,否则您可能会遇到各种奇怪的错误,因为您queue 内存中仍会有旧代码。


由于应用程序再也没有启动,我觉得令牌也永远不会更新。至于应用程序的其余部分仍然更新令牌并使用新令牌。这就解释了为什么所有的点击操作都有效,只有后台任务失败了。至于为什么部署临时解决了我们的问题是我们在每次部署后都有 queue:restart

我很确定情况确实如此,现在有两种可能性可以开始。要么你在一段时间后重新启动你的工人(Rackspace <24h)或者你不 运行 工人和 --daemon.


编辑:

已确认将以下内容添加到 Kernel.php 会在每 6 小时后重新启动守护进程。

$schedule->command('queue:restart')->cron('0 */6 * * *')