3

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

当手动请求创建所述发票时,它永远不会上传失败。至于 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',
    ]
]

对此事的任何想法表示赞赏。

4

2 回答 2

3

差不多 2.5 个月后,我再次尝试找到解决问题的方法。我认为这一次当我重读@Tommmm 更新时它真的很成功。

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

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


--Daemon (正如@the-shift-exchange 在 StackOverflow 的这篇文章中很好地解释了它)

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

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


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

我很确定情况就是这样,现在有两种可能开始。一段时间后(对于 Rackspace,<24 小时)重新启动您的工作人员,或者您不将工作人员与--daemon.


编辑:

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

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

于 2016-08-08T17:40:48.667 回答
2

我一直有一个类似的问题。这个问题的文档和错误率似乎相当低。在这里阅读(https://github.com/rackspace/php-opencloud/issues/427)看起来过期的令牌是根本原因。

上面链接的建议是通过重新验证客户端

$client->authenticate();

但是,客户端隐藏在少数命令之下。您应该能够通过以下方式访问底层客户端

Storage::disk('my-disk')->getDriver()->getAdapter()->getContainer()->getClient()->authenticate();

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

有一个

hasExpired()

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


5/25 更新:在又花了几个小时试图在这里找到解决方案之后,我认输了,只是创建了一个 cron 作业,以每 12 小时重新启动相关工作人员。假设令牌在 24 小时内有效(根据HTTP 401 Fog::Storage::Rackspace::ServiceError),因此 12 小时窗口应该安全地防止错误发生。虽然超级 hacky,但它确实使该网站的那部分保持正常运行。

于 2016-05-23T20:35:31.380 回答