Laravel应用程序中的断路器模式详解

2023-06-01 00:00:00 应用程序 断路器 详解

让我们从框架问题开始。许多应用程序向外部请求获取或发送数据。众所周知,分布式计算的谬误

网络不可靠,这是我们在应用程序中无法控制的事情之一。重复发生的失败网络请求可能会导致您的应用程序无响应。

例如,您在构建应用程序,并且正在使用外部搜索服务。就像我们之前提到的,网络不是我们的朋友,有一天,服务开始出现严重的延迟或完全停止响应。

正如您容易理解的那样,这些对于我们的应用程序来说是个坏消息。在这种情况下允许应用程序发出请求将导致其性能下降或完全停止工作。


抢救断路器模式

断路器是现代软件开发中使用的一种设计模式。它用于检测故障并封装了防止故障在维护期间不断发生的逻辑,临时外部系统故障或意外的系统故障。 -维基百科

断路器是一种防止针对无响应服务执行请求的模式。

如果您需要有关该主题的更多信息,我可以强烈推荐Martin Fowler的这篇文章。

Laravel 7附带了构建断路器所需的所有要素:

HTTP客户端

RateLimiter(一个很好的解释https://medium.com/@DarkGhostHunter/laravel-there-is-a-rate-limiter-and-you-didnt-know-eb443b1bedc)

我将尝试使代码尽可能简单,并更多地关注模式本身,以更好地解释概念。


在断路器模式之前,我们的应用程序如下所示:

$response = Http::get('https://fake-search-service.com/api/v1/search?q=Laravel'); 
return view('articles.index', ['articles' => $response->body()];

HTTP客户端将等待几秒钟,然后再引发异常,因此,最好始终对请求定义超时。

Laravel的客户端带有一个方便的方法来定义我们的请求超时。

$response = Http::timeout(2)->get('https://fake-search-service.com/api/v1/search?q=Laravel'); 
return view('articles.index', ['articles' => $response->body()];

好的,但是我们仍然没有阻止我们的服务向无响应的API发出请求。

$limiter = app(RateLimiter::class);$actionKey = 'search_service';$threshold = 10;try {
   if ($limiter->tooManyAttempts($actionKey, $threshold)) {
       // Exceeded the maximum number of failed attempts.
       return $this->failOrFallback();
   }
   $response = Http::timeout(2)->get('https://fake-search-service.com/api/v1/search?q=Laravel');

   return view('articles.index', ['articles' => $response->body()]);} catch (\Exception $exception) {
   $limiter->hit($actionKey, Carbon::now()->addMinutes(15));

   return $this->failOrFallback();}

使用Laravel的RateLimiter,我们可以计算对搜索API 

$ limiter-> hit($ actionKey,Carbon :: now()-> addMinutes(15))执行失败的尝试。

通过计算这些尝试,我们可以防止我们的应用程序在一定时间内向此API发出任何其他请求。

在每次请求之前,我们都会检查失败尝试次数是否超过

$ limiter-> tooManyAttempts($ actionKey,$ threshold),如果失败尝试次数超过了我们的阈值,我们将阻止我们的服务在15分钟内请求搜索API。

使用failOrFallback方法,我们可以提供回退实现,例如在数据库中搜索而不是外部服务,或者向用户返回适当的错误消息。

无响应的服务等待大量请求的响应将减慢我们的应用程序的速度。使用断路器模式,我们可以防止整个应用程序崩溃。搜索页面处于关闭状态,但不影响其他页面的性能。

如果我们使用微服务架构来构建应用程序,那么我们也可以将这种模式用于我们的服务。

而且,最好使用共享存储(例如Redis),以便所有服务都可以采用一种通用的方式来了解另一个服务是否关闭而无需请求N次。使用此模式将帮助不响应的服务更快恢复,而不是在顶部增加更多负载。

就像我说的那样,这是断路器模式的简单实现。您可以以更复杂的方式实现它,并更适当地处理许多事情。

如果您以不同的方式在Laravel中实现了该模式,那么我很想阅读它,因此随时留下您的反馈。


转:https://dev.to/tkorakas/circuit-breaker-pattern-in-laravel-applications-5ap2

相关文章