Circuit breaker design pattern: Difference between revisions

Content deleted Content added
added a PHP implementation
No edit summary
 
(45 intermediate revisions by 25 users not shown)
Line 1:
{{Short description|Software development pattern}}
{{Multiple issues|
The '''Circuit Breaker''' is a [[Design pattern (computer science)|design pattern]] commonly used in [[software development]] to improve system resilience and fault tolerance. Circuit breaker pattern can prevent [[cascading failure]]s particularly in [[Distributed computing|distributed systems]].<ref>{{Cite book |title=Machine Learning in Microservices Productionizing Microservices Architecture for Machine Learning Solutions |publisher=Packt Publishing |year=2023 |isbn=9781804612149}}</ref> In distributed systems, the Circuit Breaker pattern can be used to monitor service health and can detect failures dynamically. Unlike [[Timeout (computing)|timeout]]-based methods, which can lead to delayed error responses or the premature failure of healthy requests, the Circuit Breaker pattern can proactively identify unresponsive services and can prevent repeated attempts. This approach can enhance the user experience. <ref name=":1">{{Cite book |last=Richards |first=Mark |title=Microservices AntiPatterns and Pitfalls |publisher=O'Reilly}}</ref>
{{cleanup rewrite|date=September 2013}}
{{howto|date=September 2013}}
}}
'''Circuit breaker''' is a [[Design pattern (computer science)|design pattern]] used in modern [[software development]]. It 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.
 
The circuit breaker pattern can be used in conjunction with other patterns, such as retry, fallback, and timeout, to enhance fault tolerance in systems. <ref>{{Cite book |title=Kubernetes Native Microservices with Quarkus and MicroProfile |publisher=Manning |year=2022 |isbn=9781638357155}}</ref>
==Common Uses==
 
==Challenges==
Assume that an application connects to a [[database]] 100 times per second and the database fails. The application designer does not want to have the same error reoccur constantly. They also want to handle the error quickly and gracefully without waiting for [[TCP connection]] timeout.
 
According to Marc Brooker, circuit breakers can misinterpret a partial failure as total system failure and inadvertently bring down the entire system. In particular, sharded systems and cell-based architectures are vulnerable to this issue. A workaround is that the server indicates to the client which specific part is overloaded and the client uses a corresponding mini circuit breaker. However, this workaround can be complex and expensive.<ref>{{Cite book |title=Understanding Distributed Systems |isbn=9781838430214}}</ref><ref>{{Cite web |title=Will circuit breakers solve my problems? |url=https://brooker.co.za/blog/2022/02/16/circuit-breakers.html}}</ref>
Generally Circuit Breaker can be used to check the availability of an external service. An external service can be a database server or a web service used by the application.
 
== Different states of circuit breaker ==
[[Circuit breaker]] detects failures and prevents the application from trying to perform the action that is doomed to fail (until it's safe to retry).
 
* Closed
==Implementation==
* Open
* Half-open
 
=== Closed state ===
Implementations of the Circuit Breaker Design Pattern need to retain the state of the connection over a series of requests. It must offload the logic to detect failures from the actual requests. Therefore, the state machine within the circuit breaker needs to operate in some sense concurrently with the requests passing through it. One way this can be achieved is [[Asynchrony (computer programming)|asynchronously]].
[[File:Circuit Breaker -Closed state.png|thumb|Closed state]]
When everything is normal, the circuit breakers remain ''closed'', and all the requests pass through to the services. If the number of failures increases beyond the threshold, the circuit breaker trips and goes into an ''open'' state.
{{clear}}
 
=== Open state ===
In a multi-node (clustered) server, the state of the upstream service will need to be reflected across all the nodes in the cluster. Therefore, implementations may need to use a persistent storage layer, e.g. a network cache such as [[Memcached]] or [[Redis]], or local cache (disk or memory based) to record the availability of what is, to the application, an external service.
[[File:Circuit Breaker -Openstate.png|thumb|Open state]]
In this state circuit breaker returns an error immediately without even invoking the services. The Circuit breakers move into the ''half-open'' state after a timeout period elapses. Usually, it will have a monitoring system where the timeout will be specified.
{{clear}}
 
=== Half-open state ===
Circuit Breaker records the state of the external service on a given interval.
[[File:Circuit Breaker -Half Open state.png|thumb|Half-open state]]
In this state, the circuit breaker allows a limited number of requests from the service to pass through and invoke the operation. If the requests are successful, then the circuit breaker will go to the ''closed'' state. However, if the requests continue to fail, then it goes back to ''open'' state.
 
==References==
Before the external service is used from the application, the storage layer is queried to retrieve the current state.
{{reflist}}
 
==Performance Implication==
 
While it's safe to say that the benefits outweigh the consequences, implementing Circuit Breaker will negatively affect the performance.
 
By how much depends on the storage layer used and generally available resources. The largest factors in this regard are the type of cache, for example, disk-based vs. memory-based and local vs. network.
 
==Example Implementation==
 
===PHP===
 
The following is a sample implementation in PHP. The proof of concept stores the status of a MySQL server into a shared memory cache ([[Alternative PHP Cache|APC]]).
 
==== Check ====
 
The following script could be run on a set interval through [[crontab]].
 
<source lang="php">
$mysqli = new mysqli('localhost', 'user', 'pass');
 
if ($mysqli->connect_error) {
apc_store('dbStatus', 'down');
} else {
apc_store('dbStatus', 'up');
$mysqli->close();
}
</source>
 
====Usage in an application====
 
<source lang="php">
if (apc_fetch('dbStatus') === 'down') {
echo 'The database server is currently not available. Please try again in a minute.';
exit;
}
 
$mysqli = new mysqli('localhost', 'user', 'pass', 'database');
$result = $mysqli->query('SELECT * FROM table');
</source>
 
==External links==
Line 68 ⟶ 37:
*[https://www.nuget.org/packages/Polly/ Polly NuGet package]
*[https://github.com/alexandrnikitin/CircuitBreaker.Net Example of C# implementation from Alexandr Nikitin]
*[https://pypi.python.org/pypiproject/pybreaker/0.2.2 Implementation in Python]
*[httphttps://www.javaworldinfoworld.com/article/2824163/application-performance/stability-patterns-applied-in-a-restful-architecture.html Stability patterns applied in a RESTful architecture]
*[https://packagist.org/packages/eshta/resilient-task Implementation in PHP]
*[https://martinfowler.com/bliki/CircuitBreaker.html Martin Fowler Bliki]
*[http://www.javaworld.com/article/2824163/application-performance/stability-patterns-applied-in-a-restful-architecture.html Stability patterns applied in a RESTful architecture]
 
[[Category:Software design patterns]]