我正在使用Guzzle 6处理Laravel应用程序。许多功能依赖于API,我已经为其创建了一个包装器。
我的包装器是一个单独的类,它在__construct()
中创建了Guzzle客户端,并且有各种公共函数可以返回Guzzle请求的响应。
我使用的API每10秒限制40个请求。我正在缓存这些东西,所以达到这个限制是非常罕见的,但是我想知道我的应用程序如果真的死了就不会死!
关于我的应用的一些注意事项:
所以,我的问题是,我应该如何确保我没有达到这个限制?我的一些想法如下:
HandlerStack
表示Guzzle。不确定这是否可行,但我之前已使用HandlerStack
缓存响应。我试图不挑起过于自以为是的反应,但我确信这可能比上面的更好和/或更简单,或者如果它们是好主意,任何指针或建议会很棒。
提前致谢。
答案 0 :(得分:2)
没有足够的信息可以深入挖掘这一点,但为了让您入门,优秀的API通常会在您超出其限制限制时返回429响应代码。
你可以使用guzzle中的$res->getStatusCode()
检查这一点,如果他们提出的请求太快,就会向用户发送消息。
您能否提供有关您的应用正在做什么的更多信息?你在foreach循环中提出请求吗?视图是否依赖于此API的数据?
答案 1 :(得分:1)
使用Jobs来包装API调用,并将其推送到单独的队列:
ApiJob::dispatch()->onQueue('api');
使用mxl/laravel-queue-rate-limit程序包(我是作者)来限制api
队列的速率。将此添加到config/queue.php
:
'rateLimit' => [
'api' => [
'allows' => 40,
'every' => 10
]
]
运行队列工作器:
$ php artisan queue:work --queue api
另请参阅this answer。
答案 2 :(得分:0)
我个人认为Guzzle不应该处理这种情况,但如果你想让Guzzle处理它,我会写一个中间件来检查响应,如果它返回一个速率限制错误(例如状态代码429)。然后,您可以发出自定义错误或等到速率限制结束,然后重试。然而,这可能会在较长的响应时间内结束(因为您等待速率限制)。
我不认为Laravel队列会更好,因为这会使响应异步可用,并且无论您在何处存储结果,都必须轮询数据库或缓存。 (当然,如果您不希望结果立即可用,它可以工作)
如果此第三方服务直接连接到面向用户的界面,我可能会应用相同的速率限制(在您的应用程序代码中)并向用户返回错误消息,而不是等待并自动解决问题。
答案 3 :(得分:0)
我也在研究相同的问题,我更喜欢基于回调的体系结构,其中Client
类控制请求流。目前我在做睡眠和检查算法。我为我工作,因为我有3秒的冷静时间。
我使用Cache
来保存已解雇的请求数。
while(($count = Cache::get($this->getCacheKey(),0)) >= 40){ // Max request
sleep(1);
}
Cache::set($this->getCacheKey(), ++$count);
// fire request
function getCacheKey(){
return floor(time()/10); // Cool down time
}
排队似乎是一个更好的选择,我最终会转向它。在排队之前,您需要记住几件事。
Client
类的所有控制。您不必担心代码中的限制。 __sleep
和__wakeup
。