断路器 微服务
NOTE: This article is for people that have basic understanding about Microservices Architecture (MSA) and want to deep dive into it. If you are newbie in MSA world, I would like to recommend 2 websites — where you can find everything related to MSA from beginner to advanced level:
注意:本文适用于对微服务体系结构(MSA)有基本了解并希望深入研究它的人们。 如果您是MSA领域的新手,我想推荐2个网站-从初级到高级,您都可以找到与MSA相关的所有信息:
https://martinfowler.com/microservices/
什么是断路器? (What is Circuit Breaker?)
A circuit breaker is an automatically operated electrical switch designed to protect an electrical circuit from damage caused by excess current from an overload or short circuit. Its basic function is to interrupt current flow after a fault is detected. Unlike a fuse, which operates once and then must be replaced, a circuit breaker can be reset (either manually or automatically) to resume normal operation. — Wikipedia.
背景 技术断路器 是自动操作的 电 切换 设计用来保护一个 电路 从过载或过剩引起的电流损坏 短路 。 它的基本功能是在检测到故障后中断电流。 与 只能操作一次然后必须更换 的 保险丝 不同 ,可以将断路器复位(手动或自动)以恢复正常操作。 — 维基百科 。
But, wait….!
可是等等…。!
This is a Software Programming topic, and why I’m bring something related to Electrical Technology into this topic?
这是一个软件编程主题,为什么我将与电气技术相关的东西带入该主题?
Because the way we apply Circuit Breaker Pattern in Software Programming is very similar. And I just want to bring something that you are familiar with in order to make the topic easier to understand.
因为我们在软件编程中应用断路器模式的方式非常相似。 我只想带一些您熟悉的东西,以使该主题更易于理解。
Back to the definition of Circuit Breaker in Software Programming…
返回软件编程中断路器的定义…
Circuit Breaker pattern is used to detect failures and encapsulates the logic of preventing a failure from constantly recurring, during maintenance, temporary external system failure or unexpected system difficulties. — Wikipedia
断路器模式用于检测故障,并封装了防止故障在维护期间不断重复发生,维护,临时外部系统故障或意外系统故障的逻辑。 — 维基百科
Bear in mind that, It’s not available to prevent the broken service, but not to make it worse than it was. While other design patterns are born for making our solution easy to maintain, maximize reusability, better performance… then Circuit Breaker is the one for “when sh*t happens”.
请记住,它不能用于防止服务中断,但不能使其比以前更糟。 虽然其他设计模式应运而生,以使我们的解决方案易于维护,最大化可重用性,更好的性能……然后断路器是“ 当发生问题时 ”的一种。

为什么选择断路器? (Why Circuit Breaker?)
Back to several years ago — the time I started digging and applying Microservices architecture (MSA), MSA was something very new with not only me but also other developers. Nowadays, you can easily find technical articles, sample projects and case studies about MSA as it’s becoming very popular. There is a fact which can’t be denied that MSA brings so many advantages and benefits, it also makes our solution brittle because a request from user will need to call multiple micro-services. It replaces the in-memory calls of a Monolithic architecture with remote calls across the network, which works well when all services are up and running. But when one or more services are unavailable, slow network connection or timeout… it results in a cascading failure across the application.
追溯到几年前,当我开始挖掘和应用微服务体系结构(MSA)时,不仅对我本人而且对其他开发人员来说,MSA都是一种非常新的东西。 如今,随着MSA变得非常流行,您可以轻松找到有关MSA的技术文章,示例项目和案例研究。 不可否认的是,MSA具有如此多的优点和好处,这也使我们的解决方案变得脆弱,因为用户的请求将需要调用多个微服务。 它通过网络上的远程调用代替了Monolithic体系结构的内存中调用,当所有服务都启动并运行时,它可以很好地工作。 但是,当一项或多项服务不可用时,网络连接缓慢或超时……会导致整个应用程序级联失败。
And, Circuit Breaker is here to help us can build a fault-tolerant and resilient system that can survive gracefully when key services are either unavailable or have high latency. Circuit Breaker pattern enables an application to detect whether the fault has been resolved. If the problem appears to have been fixed, the application can try to invoke the operation.
而且,断路器在这里可以帮助我们构建容错和弹性的系统,当关键服务不可用或延迟较长时,该系统可以正常运行。 断路器模式使应用程序能够检测到故障是否已解决。 如果问题似乎已解决,则应用程序可以尝试调用该操作。
断路器状态 (Circuit Breaker States)

Although the name “Circuit Breaker” is mimicked from Electrical Technology, in software programming, Circuit Breaker can do much more than turning on/off the electricity (tripping).
尽管名称“ Circuit Breaker”是用电气技术来模仿的,但在软件编程中,Circuit Breaker的作用远不止于打开/关闭电源(跳闸)。
- Both of them can detect when there is a problem and automatically turn on. But while Circuit Breaker in software programming can turn off automatically, then Circuit Breaker in Electrical Technology couldn’t. 它们都可以检测出何时有问题并自动打开。 但是,尽管软件编程中的断路器可以自动关闭,但电气技术中的断路器却不能自动关闭。
- Besides having fully opened and fully closed state, Circuit Breaker in software programming can have an intermediate state, called “Half-open” where an application can operate at degraded functionalities. 除了具有完全打开和完全关闭状态之外,软件编程中的断路器还可以处于中间状态,称为“半打开”,在该状态下,应用程序可以在降级的功能下运行。
Here are the full explanation of 3 distinct states in the Circuit Breaker pattern:
这是断路器模式中3种不同状态的完整说明:
Open
打开

The open state rejects all requests for a fixed amount of time without attempting to send them and returns an error.
打开状态会在固定时间内拒绝所有请求,而不会尝试发送它们,并返回错误。
2. Half-open
2.半开

After a timeout period, the circuit switches to a half-open state to test if the underlying problem still exists. If a single call fails in this half-open state, the breaker is once again tripped. If it succeeds, the circuit breaker resets back to the closed state.
超时后,电路切换到半开状态以测试是否仍然存在根本问题。 如果在此半开状态下单个呼叫失败,则断路器将再次跳闸。 如果成功,则断路器将重置为闭合状态。
3. Closed
3.封闭

The closed state is the default “everything is working as expected” state. Requests pass freely through. When certain failures happen, they cause a circuit break and “Closed” moves to “Open”.
关闭状态是默认的“一切正常”。 请求自由通过。 当发生某些故障时,它们会导致电路中断,并且“ Closed(关闭) ”移至“ Open(断开)”。
These states are dependent on pre-set criteria, known as thresholds, that might include qualities like: server timeout, increase in errors or failures, failing status codes, and unexpected response types. Many circuit breaker libraries, like Polly for .NET, allow you to define a mix of threshold metrics as part of the configuration.
这些状态取决于预设的标准(称为阈值),这些标准可能包括以下质量:服务器超时,错误或故障增加,状态代码失败以及意外的响应类型。 许多断路器库(例如.NET的Polly)都允许您定义阈值指标的混合,作为配置的一部分。
Here is the relationship between the above states
这是上述状态之间的关系

Initially, we are in the “Closed” state and the remote call to Web API happens.
最初,我们处于“ 已关闭”状态,并且发生了对Web API的远程调用。
- Every time the call succeeds, we reset the state to as it was in the beginning. 每次调用成功,我们都将状态重置为开始时的状态。
If the number of failures cross a certain threshold, we move to the “Open” state, which acts just like an open circuit and prevents remote service calls from being made, thus saving resources.
如果故障次数超过某个阈值,我们将进入“ 打开 ”状态,其作用就像是断路,并阻止进行远程服务呼叫,从而节省了资源。
Once we exceed the retry timeout period, we move to the “Half-open” state and make another call to the remote service again to check if the service is working so that we can serve fresh content. A failure sets it back to “Open” state and another attempt is made after the retry timeout period, while a success sets it to “Closed” state so that everything starts working normally again.
一旦超过重试超时期限,我们将进入“ 半开”状态,并再次调用远程服务,以检查该服务是否正常运行,以便我们可以提供新鲜的内容。 如果失败,则将其设置为“ 打开”状态,并在重试超时时间后进行另一次尝试;如果成功 ,则将其设置为“ C 丢失”状态,从而使一切重新开始正常工作。
使用Polly施加断路器 (Using Polly to apply Circuit Breaker)
I guess, at this moment you guys already understand the concept of Circuit Breaker. If not please scroll up and read again because it’s time to practice!
我猜,现在你们已经了解了断路器的概念。 如果没有,请向上滚动并重新阅读,因为该练习了!

As I mentioned above, there is a library in .NET named Polly that allows us can implement Circuit Breaker very easy. Although you can choose to build a Circuit Breaker from scratch by yourself but please ensure that don’t try to “reinvent the wheel”.
如上所述,.NET中有一个名为Polly的库,使我们可以非常轻松地实现Circuit Breaker。 尽管您可以选择自己从头开始构建断路器,但请确保不要尝试“ 重新发明轮子 ”。
Now, I will show you step by step to apply the Circuit Breaker design pattern to your Web API by using Polly.
现在,我将逐步向您展示使用Polly将Circuit Breaker设计模式应用于Web API。
Firstly, we need to create a Web API project by Visual Studio (or Visual Code — it’s up to you). The solution structure will look like this:
首先,我们需要通过Visual Studio(或Visual Code,由您决定)创建一个Web API项目。 解决方案结构如下所示:

Try to run the default project and make a call using Postman, to ensure that it works.
尝试运行默认项目并使用Postman进行呼叫,以确保它可以正常工作。

Note: Don’t focus to much about the default controller, our goal is Circuit Breaker :)
注意 :不要过多地关注默认控制器,我们的目标是断路器:)
After that, we will make the Web API fails randomly (try to reproduce how s*** happens).
之后,我们将使Web API随机失败(尝试重现s ***的发生方式)。


Next step, we should create a new Console Application — this is our testing client. From this project, we will use HttpClient to make a call to the above WebAPI as below:
下一步,我们应该创建一个新的控制台应用程序-这是我们的测试客户端。 在该项目中,我们将使用HttpClient来调用上述WebAPI,如下所示:

And run it!
并运行它!

Next step, install Polly package from NuGet for Client Application
下一步,从NuGet安装用于客户端应用程序的Polly软件包

Next, we need to declare using Circuit Breaker Policy in the constructor
接下来,我们需要在构造函数中声明使用断路器策略

We can set up the Circuit Breaker Policy based on HttpResponseMessage like I’m suggesting or ExceptionType by using .Handle<Exception>, obviously this would depend on the requirement. The parameters we provide in CircuitBreakerAsync method will decide the behaviour of our Circuit Breaker.
我们可以使用.Handle <Exception>像我建议的那样基于HttpResponseMessage或ExceptionType来设置断路器策略,显然这取决于要求。 我们在CircuitBreakerAsync方法中提供的参数将决定断路器的行为。
The first parameter is “handledEventsAllowedBeforeBreaking” that I’m using value is “1” is the number of exceptions or handled results that are allowed before opening the Circuit Breaker.
第一个参数是“ handleEventsAllowedBeforeBreaking ”,我正在使用的值为“ 1”是打开断路器之前允许的异常或已处理结果的数量。
The second parameter is “durationOfBreak” means the duration the circuit will stay open before resetting. It’s TimeSpan format.
第二个参数是“ durationOfBreak ”,表示电路在复位之前将保持断开状态。 它是TimeSpan格式。
OnBreak, OnReset and OnHalfOpen are three actions for 3 states of Circuit Breaker.
OnBreak , OnReset和OnHalfOpen是断路器3种状态的三个动作。

In summary, the circuit will break if handledEventsAllowedBeforeBreaking exceptions or results that are handled by this policy are encountered consecutively. The circuit will stay broken for the durationOfBreak. Any attempt to execute this policy while the circuit is broken, will immediately throw a Polly.CircuitBreaker.BrokenCircuitException containing the exception or result that broke the circuit. If the first action after the break duration period results in a handled exception or result, the circuit will break again for another durationOfBreak; if no exception or handled result is encountered, the circuit will reset — it’s the half-open state.
总之,如果连续遇到此策略处理的handledEventsAllowedBeforeBreaking异常或结果,电路将中断。 电路将在BreakingOfBreak 期间保持断开状态。 在电路断开时执行此策略的任何尝试都将立即引发Polly.CircuitBreaker.BrokenCircuitException,其中包含断开电路的异常或结果。 如果在中断持续时间之后的第一个动作导致处理异常或结果,则电路将再次中断另一个durationOfBreak ; 如果没有遇到异常或处理结果,则电路将重置-这是半开状态。
The last step, we need to amend the code logic that calling to Web API a little bit to set it as a parameter of “ExecuteAsync” method of the Circuit Breaker Policy as well as to add the “Try-Catch” block in order to handle when Circuit Breaker is Open.
最后一步,我们需要修改代码逻辑,即稍微调用Web API,将其设置为Circuit Breaker Policy的“ ExecuteAsync”方法的参数,并添加“ Try-Catch”块,以便当断路器打开的句柄。

Let’s check it out!
让我们来看看!

Try again after 10 seconds and it returns “Half-Open” state and then returns “Open” state, intermediately. Because we only set the threshold is “1”.
10秒钟后重试,它会返回“ Half-Open ”状态,然后中间返回“ Open ”状态。 因为我们只将阈值设置为“ 1 ”。

Finally, It returned to “Closed” state
最终,它返回到“ Closed ”状态

You can find the full solution that I published on Github here:
您可以在这里找到我在Github上发布的完整解决方案:
Note: It’s also very easy to use Polly in API Gateway that uses Ocelot:
注意 :在使用Ocelot的API网关中使用Polly也非常容易:
结论 (Conclusions)
We’ve covered the concept of Circuit Breaker Design Pattern and implemented it together by using Polly. I hope you can find some useful information from this article. Feel free to drop me a message if you want to discuss further.
我们已经介绍了断路器设计模式的概念,并通过使用Polly一起实现了它。 希望您可以从本文中找到一些有用的信息。 如果您想进一步讨论,请随时给我留言。
断路器 微服务