Devre Kesici düzeniCircuit Breaker pattern

Uzak hizmete veya kaynağa bağlanırken, düzeltmek için gereken sürenin değişiklik gösterebileceği hataları işleyin.Handle faults that might take a variable amount of time to recover from, when connecting to a remote service or resource. Bu sayede uygulamanın kararlılığını ve dayanıklılığını artırabilirsiniz.This can improve the stability and resiliency of an application.

Bağlam ve sorunContext and problem

Dağıtılmış bir ortamda uzak kaynak ve hizmetlere yapılan çağrılar yavaş ağ bağlantıları, zaman aşımları ve kaynakların aşırı yüklenmesi veya geçici olarak devre dışı bırakılması gibi geçici hatalardan dolayı başarısız olabilir.In a distributed environment, calls to remote resources and services can fail due to transient faults, such as slow network connections, timeouts, or the resources being overcommitted or temporarily unavailable. Kısa bir süre sonra kendilerini genellikle bu hataları düzeltin ve sağlam bir bulut uygulaması [yeniden deneme düzeni] gibi bir strateji kullanarak işlemek için hazırlıklı olmalıdır [yeniden deneme düzeni].These faults typically correct themselves after a short period of time, and a robust cloud application should be prepared to handle them by using a strategy such as the [Retry pattern][retry-pattern].

Ancak bazı durumlarda hatalar beklenmedik olaylardan kaynaklanır ve bu hataları düzeltmek çok daha fazla zaman alabilir.However, there can also be situations where faults are due to unanticipated events, and that might take much longer to fix. Bu hataların önem derecesi kısmi bağlantı kaybıyla bir hizmetin tamamen çökmesi arasında değişebilir.These faults can range in severity from a partial loss of connectivity to the complete failure of a service. Böyle durumlarda uygulamanın, başarılı olma ihtimali düşük bir işlemi sürekli yeniden denemesi anlamsız olabilir; bunun yerine uygulama işlemin başarısız olduğunu çabuk kabul etmeli ve bu hatayı gerektiği gibi işlemelidir.In these situations it might be pointless for an application to continually retry an operation that is unlikely to succeed, and instead the application should quickly accept that the operation has failed and handle this failure accordingly.

Buna ek olarak, hizmet çok meşgulse sistemin bir bölümündeki hata zincirleme hatalara neden olabilir.Additionally, if a service is very busy, failure in one part of the system might lead to cascading failures. Örneğin, hizmet çağrısı yapan bir işlem zaman aşımı uygulayacak şekilde yapılandırılmış olabilir ve hizmetin bu süre içinde yanıt verememesi durumunda bir hata iletisiyle yanıtlayabilir.For example, an operation that invokes a service could be configured to implement a timeout, and reply with a failure message if the service fails to respond within this period. Öte yandan, bu strateji aynı işleme yönelik birçok eş zamanlı isteğin zaman aşımı süresi dolana kadar engellenmesine neden olabilir.However, this strategy could cause many concurrent requests to the same operation to be blocked until the timeout period expires. Bu engellenen isteklerde bellek, iş parçacıkları, veritabanı bağlantıları ve benzeri önemli sistem kaynakları bulunabilir.These blocked requests might hold critical system resources such as memory, threads, database connections, and so on. Sonuç olarak bu kaynaklar tükenebilir ve sistemin aynı kaynakları kullanması gereken, bununla ilişkisiz diğer bölümlerinde hataya neden olabilir.Consequently, these resources could become exhausted, causing failure of other possibly unrelated parts of the system that need to use the same resources. Böyle durumlarda, işlemin hemen başarısız olması ve hizmeti ancak başarılı olma olasılığı olduğunda çağırma girişiminde bulunması tercih edilebilir.In these situations, it would be preferable for the operation to fail immediately, and only attempt to invoke the service if it's likely to succeed. Daha kısa bir zaman aşımı süresi ayarlamanın bu sorunu çözmeye yardımcı olabileceğini unutmayın; ama zaman aşımı, hizmete yönelik istek sonunda başarılı olabilecek olsa bile işlemin çoğunlukla başarısız olması sonucunu doğuracak kadar da kısa olmamalıdır.Note that setting a shorter timeout might help to resolve this problem, but the timeout shouldn't be so short that the operation fails most of the time, even if the request to the service would eventually succeed.

ÇözümSolution

Michael Nygard tarafından Release It! kitabında tanıtılan Devre Kesici düzeni, uygulamanın başarısız olma olasılığı yüksek bir işlemi tekrar tekrar yürütmeye çalışmasını önleyebilir.The Circuit Breaker pattern, popularized by Michael Nygard in his book, Release It!, can prevent an application from repeatedly trying to execute an operation that's likely to fail. Hatanın düzeltilmesi beklenmeden devam etmesine izin verilir veya hatanın uzun süreceği saptanırken CPU döngüleri harcanır.Allowing it to continue without waiting for the fault to be fixed or wasting CPU cycles while it determines that the fault is long lasting. Devre Kesici düzeni uygulamanın hatanın düzeltilip düzeltilmediğini saptamasını da sağlar.The Circuit Breaker pattern also enables an application to detect whether the fault has been resolved. Sorun düzeltilmiş gibi görünüyorsa, uygulama işlemi çağırmayı deneyebilir.If the problem appears to have been fixed, the application can try to invoke the operation.

Devre Kesici düzeninin amacı Yeniden Deneme düzeninden farklıdır.The purpose of the Circuit Breaker pattern is different than the Retry pattern. Yeniden Deneme düzeni uygulamanın başarılı olacağı beklentisiyle işlemi yeniden denemesini sağlar.The Retry pattern enables an application to retry an operation in the expectation that it'll succeed. Devre Kesici düzeni, uygulamanın büyük olasılıkla başarısız olacak olan bir işlemi gerçekleştirmesini engeller.The Circuit Breaker pattern prevents an application from performing an operation that is likely to fail. Uygulama bu iki düzeni birleştirip bir devre kesici üzerinden işlemi çağırmak için Yeniden Deneme düzenini kullanabilir.An application can combine these two patterns by using the Retry pattern to invoke an operation through a circuit breaker. Öte yandan, yeniden deneme mantığının devre kesici tarafından döndürülen özel durumlara duyarlı olması ve devre kesici hatanın geçici olmadığını gösteriyorsa yeniden denemeyi bırakması gerekir.However, the retry logic should be sensitive to any exceptions returned by the circuit breaker and abandon retry attempts if the circuit breaker indicates that a fault is not transient.

Devre kesici, başarısız olabilecek işlemler için ara sunucu gibi çalışır.A circuit breaker acts as a proxy for operations that might fail. Ara sunucu son zamanlarda oluşmuş olan başarısızlıkların sayısını izlemeli ve bu bilgileri kullanarak işlemin devam etmesine izin mi vereceğine yoksa hemen bir özel durum mu döndüreceğine karar vermelidir.The proxy should monitor the number of recent failures that have occurred, and use this information to decide whether to allow the operation to proceed, or simply return an exception immediately.

Ara sunucu, elektrik devre kesicisinin işlevlerini taklit eden aşağıdaki durum değerleriyle bir durum makinesi olarak çalıştırılabilir:The proxy can be implemented as a state machine with the following states that mimic the functionality of an electrical circuit breaker:

  • Kapalı: Uygulamadan gelen istek işleme yönlendirilir.Closed: The request from the application is routed to the operation. Ara sunucu son başarısızlıkların sayısını tutar ve işleme yönelik çağrı başarısız olursa ara sunucuda bu sayı bir artırılır.The proxy maintains a count of the number of recent failures, and if the call to the operation is unsuccessful the proxy increments this count. Son başarısızlıkların sayısı belirli bir süre içinde belirtilen eşiği aşarsa, ara sunucu Açık duruma getirilir.If the number of recent failures exceeds a specified threshold within a given time period, the proxy is placed into the Open state. Bu noktada ara sunucu zaman aşımı zamanlayıcısını başlatır ve bu süre dolduğunda ara sunucu Yarı Açık duruma getirilir.At this point the proxy starts a timeout timer, and when this timer expires the proxy is placed into the Half-Open state.

    Zaman aşımı zamanlayıcısının amacı, uygulamanın işlemi yeniden denemesine izin vermeden önce sisteme başarısızlığa neden olan sorunu düzeltmesi için zaman tanımaktır.The purpose of the timeout timer is to give the system time to fix the problem that caused the failure before allowing the application to try to perform the operation again.

  • Açık: Uygulamadan gelen istek hemen başarısız olur ve uygulamaya bir özel durum döndürülür.Open: The request from the application fails immediately and an exception is returned to the application.

  • Yarı açık: Uygulama isteklerinden sınırlı sayıda geçmesine ve işlemi çağırmasına izin verilir.Half-Open: A limited number of requests from the application are allowed to pass through and invoke the operation. Bu istekler başarılı olursa, daha önce başarısızlığa neden olan hatanın düzeltildiği varsayılır ve devre kesici Kapalı duruma geçer (başarısızlık sayacı sıfırlanır).If these requests are successful, it's assumed that the fault that was previously causing the failure has been fixed and the circuit breaker switches to the Closed state (the failure counter is reset). Herhangi bir istek başarısız olursa devre kesici hatanın hala devam ettiğini varsayar, dolayısıyla Açık duruma geri döner ve zaman aşımı zamanlayıcısını yeniden başlatarak sisteme hatadan kurtulması için biraz daha zaman tanır.If any request fails, the circuit breaker assumes that the fault is still present so it reverts back to the Open state and restarts the timeout timer to give the system a further period of time to recover from the failure.

    Yarı Açık durum, kurtarılmakta olan bir hizmete aniden yoğun bir istek akışı olmasını önlemeye yarar.The Half-Open state is useful to prevent a recovering service from suddenly being flooded with requests. Hizmet kurtarılırken, kurtarma işlemi tamamlanana kadar sınırlı miktarda isteği destekleyebilir, ama kurtarma işlemi devam ederken yoğun bir iş akışı hizmetin zaman aşımına uğramasına veya yeniden başarısız olmasına neden olabilir.As a service recovers, it might be able to support a limited volume of requests until the recovery is complete, but while recovery is in progress a flood of work can cause the service to time out or fail again.

Devre Kesici durumları

Şekilde, Kapalı durumu tarafından kullanılan başarısızlık sayacı zamana dayalıdır.In the figure, the failure counter used by the Closed state is time based. Düzenli aralıklarla otomatik olarak sıfırlanır.It's automatically reset at periodic intervals. Bu, arada sırada başarısızlıklarla karşılaştığında devre kesicinin Açık duruma geçmesini önlemeye yardımcı olur.This helps to prevent the circuit breaker from entering the Open state if it experiences occasional failures. Devre kesiciyi Açık duruma geçiren başarısızlık eşiğine ulaşılması için, belirtilen süre içinde belirtilen sayıda başarısızlık olması gerekir.The failure threshold that trips the circuit breaker into the Open state is only reached when a specified number of failures have occurred during a specified interval. Yarı Açık durumu tarafından kullanılan sayaç, işlemi çağırmaya yönelik başarılı girişimlerin sayısını kaydeder.The counter used by the Half-Open state records the number of successful attempts to invoke the operation. Arka arkaya belirtilen sayıda işlem çağrısı başarılı olduktan sonra devre kesici Kapalı duruma geri döner.The circuit breaker reverts to the Closed state after a specified number of consecutive operation invocations have been successful. Çağrılardan herhangi biri başarısız olursa, devre kesici hemen Açık duruma geçer ve bir sonraki Yarı Açık duruma geçişinde başarı sayacı sıfırlanır.If any invocation fails, the circuit breaker enters the Open state immediately and the success counter will be reset the next time it enters the Half-Open state.

Sistemin kurtarılması harici olarak işlenir; büyük olasılıkla başarısız bileşen geri yüklenir veya yeniden başlatılır ya da ağ bağlantısı onarılır.How the system recovers is handled externally, possibly by restoring or restarting a failed component or repairing a network connection.

Devre Kesici düzeni sistem bir hatadan kurtarılırken tutarlılık sağlar ve performans üzerindeki etkiyi en aza indirir.The Circuit Breaker pattern provides stability while the system recovers from a failure and minimizes the impact on performance. Başarısız olma olasılığı yüksek bir işleme yönelik isteği, işlemin zaman aşımına uğramasını veya asla geri dönmemesini beklemek yerine hızla reddederek sistemin yanıt süresini korumaya yardımcı olabilir.It can help to maintain the response time of the system by quickly rejecting a request for an operation that's likely to fail, rather than waiting for the operation to time out, or never return. Devre kesici durumu her değiştiğinde bir olay oluşturuyorsa, bu bilgiler sistemin devre kesici tarafından korunan parçasının durumunu izlemek veya devre kesici Açık duruma geçtiğinde yöneticiyi uyarmak için kullanılabilir.If the circuit breaker raises an event each time it changes state, this information can be used to monitor the health of the part of the system protected by the circuit breaker, or to alert an administrator when a circuit breaker trips to the Open state.

Düzen özelleştirilebilir ve olası başarısızlık türüne uyarlanabilir.The pattern is customizable and can be adapted according to the type of the possible failure. Örneğin, devre kesiciye daha yüksek bir zaman aşımı zamanlayıcısı uygulayabilirsiniz.For example, you can apply an increasing timeout timer to a circuit breaker. Devre kesiciyi başlangıçta birkaç saniye Açık duruma getirebilir ve ardından hata düzeltilmediyse zaman aşımını birkaç dakika artırabilirsiniz ve bu şekilde devam edebilirsiniz.You could place the circuit breaker in the Open state for a few seconds initially, and then if the failure hasn't been resolved increase the timeout to a few minutes, and so on. Bazı durumlarda, Açık durumun hata döndürmesi veya özel durum oluşturması yerine, uygulama için anlamlı bir varsayılan değer döndürmek daha yaralı olabilir.In some cases, rather than the Open state returning failure and raising an exception, it could be useful to return a default value that is meaningful to the application.

Sorunlar ve dikkat edilmesi gerekenlerIssues and considerations

Bu düzeni nasıl uygulayacağınıza karar verirken aşağıdaki noktaları dikkate almalısınız:You should consider the following points when deciding how to implement this pattern:

Özel Durum İşleme.Exception Handling. Devre kesici aracılığıyla bir işlem çağıran uygulama, işlemin kullanılamaz olması durumunda oluşturulan özel durumları işlemeye hazır olmalıdır.An application invoking an operation through a circuit breaker must be prepared to handle the exceptions raised if the operation is unavailable. Özel durumların işlenme şekli uygulamaya özgü olacaktır.The way exceptions are handled will be application specific. Örneğin, uygulama geçici olarak işlevselliğini düşürebilir, aynı görevi yerine getirmeyi veya aynı verileri almayı denemek üzere alternatif bir işlem çağırabilir ya da özel durumu kullanıcıya bildirir ve daha sonra yeniden denemesini ister.For example, an application could temporarily degrade its functionality, invoke an alternative operation to try to perform the same task or obtain the same data, or report the exception to the user and ask them to try again later.

Özel Durum Türleri.Types of Exceptions. İstek birçok nedenle başarısız olabilir ve bu nedenlerden bazıları diğerlerinden daha ciddi bir hata türüne işaret edebilir.A request might fail for many reasons, some of which might indicate a more severe type of failure than others. Örneğin, uzak hizmet kilitlendiği ve kurtarılmasının birkaç dakika süreceği için veya hizmetin geçici olarak aşırı yüklenmesinden dolayı zaman aşımı oluştuğu için istek başarısız olabilir.For example, a request might fail because a remote service has crashed and will take several minutes to recover, or because of a timeout due to the service being temporarily overloaded. Devre kesici oluşan özel durumların türlerini inceleyebilir ve bu özel durumların doğasına bağlı olarak stratejisini ayarlayabilir.A circuit breaker might be able to examine the types of exceptions that occur and adjust its strategy depending on the nature of these exceptions. Örneğin, devre kesiciyi Açık duruma geçirmek için gereken zaman aşımı özel durumlarının sayısı, hizmetin tamamen kullanılamaz olmasından kaynaklanan başarısızlıkların sayısından fazla olabilir.For example, it might require a larger number of timeout exceptions to trip the circuit breaker to the Open state compared to the number of failures due to the service being completely unavailable.

Günlüğe kaydetme.Logging. Yöneticinin işlemin durumunu izleyebilmesi için devre kesici tüm başarısız istekleri (ve bir olasılıkla başarılı istekleri) günlüğe kaydetmelidir.A circuit breaker should log all failed requests (and possibly successful requests) to enable an administrator to monitor the health of the operation.

Kurtarılabilirlik.Recoverability. Devre kesiciyi, koruduğu işlemin olası kurtarma düzeniyle eşleşecek şekilde yapılandırmalısınız.You should configure the circuit breaker to match the likely recovery pattern of the operation it's protecting. Örneğin, devre kesici uzun süre Açık durumda kalırsa, başarısızlığa neden olan hata düzeltilmiş olsa bile özel durumlar oluşturabilir.For example, if the circuit breaker remains in the Open state for a long period, it could raise exceptions even if the reason for the failure has been resolved. Benzer biçimde, devre kesici Açık durumdan Yarı Açık duruma çok hızlı geçirilirse, dalgalanmalar ortaya çıkabilir ve uygulamaların yanıt sürelerini kısaltabilir.Similarly, a circuit breaker could fluctuate and reduce the response times of applications if it switches from the Open state to the Half-Open state too quickly.

Başarısız İşlemleri Test Etme.Testing Failed Operations. Devre kesici Açık durumdayken Yarı Açık duruma ne zaman geçileceğini saptamak için bir zamanlayıcı kullanmak yerine, uzak hizmete veya kaynağa düzenli aralıklarla ping yaparak yeniden kullanılabilir duruma gelip gelmediğini saptayabilir.In the Open state, rather than using a timer to determine when to switch to the Half-Open state, a circuit breaker can instead periodically ping the remote service or resource to determine whether it's become available again. Bu ping daha önce başarısız olan bir işlemi çağırma girişimi biçiminde olabilir veya Sistem Durumu Uç Nokta İzleme düzeni tarafından açıklandığı gibi uzak hizmet tarafından özel olarak hizmetin durumunu test etmek için sağlanmış özel bir işlem de kullanabilir.This ping could take the form of an attempt to invoke an operation that had previously failed, or it could use a special operation provided by the remote service specifically for testing the health of the service, as described by the Health Endpoint Monitoring pattern.

El İle Geçersiz Kılma.Manual Override. Başarısız bir işlemi kurtarma süresinin aşırı değişken olduğu bir sistemde, yöneticiye devre kesiciyi kapatma (ve başarısızlık sayacını sıfırlama) olanağı tanıyan bir el ile sıfırlama seçeneği sağlanması yararlı olacaktır.In a system where the recovery time for a failing operation is extremely variable, it's beneficial to provide a manual reset option that enables an administrator to close a circuit breaker (and reset the failure counter). Benzer biçimde, devre kesici tarafından korunan işlem geçici olarak kullanılamıyorsa, yönetici devre kesiciyi Açık duruma (ve zaman aşımı zamanlayıcısını yeniden başlatmaya) zorlayabilir.Similarly, an administrator could force a circuit breaker into the Open state (and restart the timeout timer) if the operation protected by the circuit breaker is temporarily unavailable.

Eşzamanlılık.Concurrency. Aynı devre kesiciye uygulamanın çok fazla sayıda eş zamanlı örneği erişebilir.The same circuit breaker could be accessed by a large number of concurrent instances of an application. Uygulama sırasında eş zamanlı istekler engellenmemeli veya bir işleme yapılan çağrıya aşırı ek yük getirilmemelidir.The implementation shouldn't block concurrent requests or add excessive overhead to each call to an operation.

Kaynak Ayrımı.Resource Differentiation. Temelde birden çok bağımsız sağlayıcı olma olasılığı varsa, bir kaynak türü için tek devre kesici kullanırken dikkatli olun.Be careful when using a single circuit breaker for one type of resource if there might be multiple underlying independent providers. Örneğin, birden çok parça içeren bir veri deposunda, bir parça tümüyle erişilebilir durumdayken diğeri geçici bir sorunla karşılaşmış olabilir.For example, in a data store that contains multiple shards, one shard might be fully accessible while another is experiencing a temporary issue. Bu senaryolardaki hata yanıtları birleştirilirse, uygulama başarısız olma olasılığı yüksek bile olsa bazı parçalara erişmeyi deneyebilir ve bu arada başarılı olma olasılığı yüksek bile olsa diğer parçalara erişim engellenebilir.If the error responses in these scenarios are merged, an application might try to access some shards even when failure is highly likely, while access to other shards might be blocked even though it's likely to succeed.

Hızlandırılmış Devre Kesme.Accelerated Circuit Breaking. Bazen bir başarısızlık yanıtı devre kesicinin hemen durum geçişi yapmasına kısa bir süre böyle kalmasına yetecek kadar bilgi içeriyor olabilir.Sometimes a failure response can contain enough information for the circuit breaker to trip immediately and stay tripped for a minimum amount of time. Örneğin, paylaşılan aşırı yüklenmiş bir kaynaktan gelen hata yanıtı hemen yeniden denemenin önerilmediğini ve uygulamanın yeniden denemeden önce birkaç dakika beklemesi gerektiğini gösteriyor olabilir.For example, the error response from a shared resource that's overloaded could indicate that an immediate retry isn't recommended and that the application should instead try again in a few minutes.

Not

Hizmet istemcinin bant genişliğini azaltıyorsa HTTP 429 (Çok Fazla İstek Var) veya hizmet şu anda kullanılamıyorsa HTTP 503 (Hizmet Kullanılamıyor) döndürebilir.A service can return HTTP 429 (Too Many Requests) if it is throttling the client, or HTTP 503 (Service Unavailable) if the service is not currently available. Yanıt, gecikmenin beklenen süresi gibi ek bilgiler içerebilir.The response can include additional information, such as the anticipated duration of the delay.

Başarısız İstekleri Yeniden Yürütme.Replaying Failed Requests. Açık durumdayken, devre kesici hızla hataya geçmek yerine her isteğin ayrıntılarını bir günlüğe kaydedebilir ve uzak kaynak veya hizmet kullanılabilir duruma geldiğinde bu isteklerin yeniden yürütülmesi için düzenleme yapabilir.In the Open state, rather than simply failing quickly, a circuit breaker could also record the details of each request to a journal and arrange for these requests to be replayed when the remote resource or service becomes available.

Dış Hizmetlerde Uygun Olmayan Zaman Aşımları.Inappropriate Timeouts on External Services. Devre kesici, uygulamaları daha uzun bir zaman aşımı süresiyle yapılandırılmış dış hizmetlerde başarısız olan işlemlerden tümüyle koruyamayabilir.A circuit breaker might not be able to fully protect applications from operations that fail in external services that are configured with a lengthy timeout period. Zaman aşımı süresi fazla uzunsa, devre kesici işlemin başarısız olduğunu göstermeden önce devre kesiciyi çalıştıran iş parçacığı uzun bir süre engellenebilir.If the timeout is too long, a thread running a circuit breaker might be blocked for an extended period before the circuit breaker indicates that the operation has failed. Bu süre içinde, birçok başka uygulama örneği de devre kesici aracılığıyla hizmeti çağırmayı deneyebilir ve tümü başarısız olana kadar çok sayıda iş parçacığını hareketsiz bırakabilir.In this time, many other application instances might also try to invoke the service through the circuit breaker and tie up a significant number of threads before they all fail.

Bu düzenin kullanılacağı durumlarWhen to use this pattern

Bu düzeni kullanarak:Use this pattern:

  • Uygulamanın bir uzak hizmeti çağırmaya veya paylaşılan bir kaynağa erişmeye çalışmasını, bu işlemin başarısız olma olasılığı yüksekse engelleyebilirsiniz.To prevent an application from trying to invoke a remote service or access a shared resource if this operation is highly likely to fail.

Bu düzenin şunlar için kullanılması önerilmez:This pattern isn't recommended:

  • Uygulamanın bellek içi veri yapısı gibi yerel özel kaynaklarına erişimi işlemek için.For handling access to local private resources in an application, such as in-memory data structure. Bu ortamda, devre kesici kullanmak sisteminize ek yük getirebilir.In this environment, using a circuit breaker would add overhead to your system.
  • Uygulamalarınızın iş mantığında özel durumları işlemeye bir alternatif olarak.As a substitute for handling exceptions in the business logic of your applications.

ÖrnekExample

Bir web uygulamasında, birkaç sayfa bir dış hizmetten alınan verilerle doldurulur.In a web application, several of the pages are populated with data retrieved from an external service. Sistem çok küçük bir arabellek uyguluyorsa, bu sayfalara yönelik isabetlerin çoğu hizmete gidiş dönüş hareketine neden olacaktır.If the system implements minimal caching, most hits to these pages will cause a round trip to the service. Web uygulamasından hizmete bağlantılar bir zaman aşımı süresiyle (normalde 60 saniye) yapılandırılabilir ve hizmet bu süre içinde yanıt vermezse web sayfalarının mantığı hizmetin kullanılamaz olduğunu varsayar ve özel durum oluşturur.Connections from the web application to the service could be configured with a timeout period (typically 60 seconds), and if the service doesn't respond in this time the logic in each web page will assume that the service is unavailable and throw an exception.

Ancak hizmet başarısız olursa ve sistem çok meşgulse, kullanıcılar özel durum oluşmadan önce 60 saniye kadar beklemek zorunda kalabilir.However, if the service fails and the system is very busy, users could be forced to wait for up to 60 seconds before an exception occurs. Sonunda bellek, bağlantı ve iş parçacığı gibi kaynaklar tükenebilir ve hizmetten veri alan sayfalara erişmiyor olsalar bile diğer kullanıcıların sisteme bağlanması engellenir.Eventually resources such as memory, connections, and threads could be exhausted, preventing other users from connecting to the system, even if they aren't accessing pages that retrieve data from the service.

Başka web sunucuları ekleyerek ve yük dengeleme gerçekleştirerek sistemin ölçeklendirilmesi kaynakların tükenmesini geciktirebilir ama sorunu çözmez, çünkü kullanıcı istekleri yine yanıt alamayacaktır ve tüm web sunucularının kaynakları sonunda yine tükenebilir.Scaling the system by adding further web servers and implementing load balancing might delay when resources become exhausted, but it won't resolve the issue because user requests will still be unresponsive and all web servers could still eventually run out of resources.

Hizmete bağlanan ve verileri alan mantığı bir devre kesici içinde sarmalamak bu sorunu çözmeye ve sistem hatasını daha zarif bir şekilde işlemeye yardımcı olabilir.Wrapping the logic that connects to the service and retrieves the data in a circuit breaker could help to solve this problem and handle the service failure more elegantly. Kullanıcı istekleri yine başarısız olur ama bunlar daha hızlı başarısız olacak ve kaynaklar engellenmeyecektir.User requests will still fail, but they'll fail more quickly and the resources won't be blocked.

CircuitBreaker sınıfı devre kesici hakkındaki durum bilgilerini, aşağıdaki kodda gösterilen ICircuitBreakerStateStore arabirimini gerçekleştiren bir nesnede tutar.The CircuitBreaker class maintains state information about a circuit breaker in an object that implements the ICircuitBreakerStateStore interface shown in the following code.

interface ICircuitBreakerStateStore
{
  CircuitBreakerStateEnum State { get; }

  Exception LastException { get; }

  DateTime LastStateChangedDateUtc { get; }

  void Trip(Exception ex);

  void Reset();

  void HalfOpen();

  bool IsClosed { get; }
}

State özelliği devre kesicinin geçerli durumunu gösterir ve durum değeri CircuitBreakerStateEnum sabit listesinde tanımlandığı gibi Open, HalfOpen veya Closed olur.The State property indicates the current state of the circuit breaker, and will be either Open, HalfOpen, or Closed as defined by the CircuitBreakerStateEnum enumeration. IsClosed özelliğinin değeri, devre kesici kapalıysa True, açıksa veya yarı açıksa False olmalıdır.The IsClosed property should be true if the circuit breaker is closed, but false if it's open or half open. Trip yöntemi devre kesiciyi açık duruma geçirir ve durum değişikliğine neden olan özel durumu, bu özel durumun oluştuğu tarih ve saatle birlikte kaydeder.The Trip method switches the state of the circuit breaker to the open state and records the exception that caused the change in state, together with the date and time that the exception occurred. LastException ve LastStateChangedDateUtc özellikleri bu bilgileri döndürür.The LastException and the LastStateChangedDateUtc properties return this information. Reset yöntemi devre kesiciyi kapatır ve HalfOpen yöntemi de devre kesiciyi yarı açık olarak ayarlar.The Reset method closes the circuit breaker, and the HalfOpen method sets the circuit breaker to half open.

Örnekteki InMemoryCircuitBreakerStateStore sınıfı ICircuitBreakerStateStore arabiriminin uygulamasını içerir.The InMemoryCircuitBreakerStateStore class in the example contains an implementation of the ICircuitBreakerStateStore interface. CircuitBreaker sınıfı, devre kesicinin durumunu tutmak için bu sınıfın bir örneğini oluşturur.The CircuitBreaker class creates an instance of this class to hold the state of the circuit breaker.

CircuitBreaker sınıfındaki ExecuteAction yöntemi, bir Action temsilcisi olarak belirtilen işlemi sarmalar.The ExecuteAction method in the CircuitBreaker class wraps an operation, specified as an Action delegate. Devre kesici kapalıysa, ExecuteAction Action temsilcisini çağırır.If the circuit breaker is closed, ExecuteAction invokes the Action delegate. İşlem başarısız olursa, özel durum işleyicisi TrackException çağrısı yapar ve bu da devre kesicinin durumunu açık olarak ayarlar.If the operation fails, an exception handler calls TrackException, which sets the circuit breaker state to open. Aşağıdaki kod örneği bu akışı vurgulamaktadır.The following code example highlights this flow.

public class CircuitBreaker
{
  private readonly ICircuitBreakerStateStore stateStore =
    CircuitBreakerStateStoreFactory.GetCircuitBreakerStateStore();

  private readonly object halfOpenSyncObject = new object ();
  ...
  public bool IsClosed { get { return stateStore.IsClosed; } }

  public bool IsOpen { get { return !IsClosed; } }

  public void ExecuteAction(Action action)
  {
    ...
    if (IsOpen)
    {
      // The circuit breaker is Open.
      ... (see code sample below for details)
    }

    // The circuit breaker is Closed, execute the action.
    try
    {
      action();
    }
    catch (Exception ex)
    {
      // If an exception still occurs here, simply
      // retrip the breaker immediately.
      this.TrackException(ex);

      // Throw the exception so that the caller can tell
      // the type of exception that was thrown.
      throw;
    }
  }

  private void TrackException(Exception ex)
  {
    // For simplicity in this example, open the circuit breaker on the first exception.
    // In reality this would be more complex. A certain type of exception, such as one
    // that indicates a service is offline, might trip the circuit breaker immediately.
    // Alternatively it might count exceptions locally or across multiple instances and
    // use this value over time, or the exception/success ratio based on the exception
    // types, to open the circuit breaker.
    this.stateStore.Trip(ex);
  }
}

Aşağıdaki örnekte, devre kesici kapalı olmadığında yürütülen kod gösterilir (önceki örnekte atlanmıştır).The following example shows the code (omitted from the previous example) that is executed if the circuit breaker isn't closed. Önce devre kesicinin CircuitBreaker sınıfındaki yerel OpenToHalfOpenWaitTime alanında belirtilen süreden daha uzun süre açık kalıp kalmadığını denetler.It first checks if the circuit breaker has been open for a period longer than the time specified by the local OpenToHalfOpenWaitTime field in the CircuitBreaker class. Böyle bir durum söz konusuysa, ExecuteAction yöntemi devre kesiciyi yarı açık olarak ayarlar ve ardından Action temsilcisi tarafından belirtilen işlemi gerçekleştirmeyi dener.If this is the case, the ExecuteAction method sets the circuit breaker to half open, then tries to perform the operation specified by the Action delegate.

İşlem başarılı olursa, devre kesici kapalı duruma sıfırlanır.If the operation is successful, the circuit breaker is reset to the closed state. İşlem başarısız olursa, yeniden açık duruma döner ve özel durumun oluştuğu saat güncelleştirilerek devre kesicinin işlemi gerçekleştirmeyi yeniden denemeden önce bir süre daha beklemesi sağlanır.If the operation fails, it is tripped back to the open state and the time the exception occurred is updated so that the circuit breaker will wait for a further period before trying to perform the operation again.

Devre kesici yalnızca kısa bir süredir açıksa (OpenToHalfOpenWaitTime değerinden daha kısa), ExecuteAction yöntemi yalnızca bir CircuitBreakerOpenException özel durumu oluşturur ve devre kesicinin açık duruma geçmesine neden olan hatayı döndürür.If the circuit breaker has only been open for a short time, less than the OpenToHalfOpenWaitTime value, the ExecuteAction method simply throws a CircuitBreakerOpenException exception and returns the error that caused the circuit breaker to transition to the open state.

Buna ek olarak, devre kesicinin yarı açık durumdayken işleme yönelik eş zamanlı çağrılar yapmaya çalışmasını önlemek için bir kilit kullanır.Additionally, it uses a lock to prevent the circuit breaker from trying to perform concurrent calls to the operation while it's half open. Eş zamanlı işlem çağırma girişimi, devre kesici açık durumdaymış gibi işlenir ve aşağıda açıklandığı gibi bir özel durumla başarısız olur.A concurrent attempt to invoke the operation will be handled as if the circuit breaker was open, and it'll fail with an exception as described later.

    ...
    if (IsOpen)
    {
      // The circuit breaker is Open. Check if the Open timeout has expired.
      // If it has, set the state to HalfOpen. Another approach might be to
      // check for the HalfOpen state that had be set by some other operation.
      if (stateStore.LastStateChangedDateUtc + OpenToHalfOpenWaitTime < DateTime.UtcNow)
      {
        // The Open timeout has expired. Allow one operation to execute. Note that, in
        // this example, the circuit breaker is set to HalfOpen after being
        // in the Open state for some period of time. An alternative would be to set
        // this using some other approach such as a timer, test method, manually, and
        // so on, and check the state here to determine how to handle execution
        // of the action.
        // Limit the number of threads to be executed when the breaker is HalfOpen.
        // An alternative would be to use a more complex approach to determine which
        // threads or how many are allowed to execute, or to execute a simple test
        // method instead.
        bool lockTaken = false;
        try
        {
          Monitor.TryEnter(halfOpenSyncObject, ref lockTaken);
          if (lockTaken)
          {
            // Set the circuit breaker state to HalfOpen.
            stateStore.HalfOpen();

            // Attempt the operation.
            action();

            // If this action succeeds, reset the state and allow other operations.
            // In reality, instead of immediately returning to the Closed state, a counter
            // here would record the number of successful operations and return the
            // circuit breaker to the Closed state only after a specified number succeed.
            this.stateStore.Reset();
            return;
          }
        }
        catch (Exception ex)
        {
          // If there's still an exception, trip the breaker again immediately.
          this.stateStore.Trip(ex);

          // Throw the exception so that the caller knows which exception occurred.
          throw;
        }
        finally
        {
          if (lockTaken)
          {
            Monitor.Exit(halfOpenSyncObject);
          }
        }
      }
      // The Open timeout hasn't yet expired. Throw a CircuitBreakerOpen exception to
      // inform the caller that the call was not actually attempted,
      // and return the most recent exception received.
      throw new CircuitBreakerOpenException(stateStore.LastException);
    }
    ...

CircuitBreaker nesnesi kullanarak işlemi korumak için, uygulama CircuitBreaker sınıfının bir örneğini oluşturur ve gerçekleştirilecek işlemi bir parametre olarak belirtip ExecuteAction yöntemini çağırır.To use a CircuitBreaker object to protect an operation, an application creates an instance of the CircuitBreaker class and invokes the ExecuteAction method, specifying the operation to be performed as the parameter. Uygulama, devre kesici açık olduğundan işlemin başarısız olması durumunda CircuitBreakerOpenException özel durumunu yakalamaya hazır olmalıdır.The application should be prepared to catch the CircuitBreakerOpenException exception if the operation fails because the circuit breaker is open. Aşağıdaki kodda bir örnek gösterilir:The following code shows an example:

var breaker = new CircuitBreaker();

try
{
  breaker.ExecuteAction(() =>
  {
    // Operation protected by the circuit breaker.
    ...
  });
}
catch (CircuitBreakerOpenException ex)
{
  // Perform some different action when the breaker is open.
  // Last exception details are in the inner exception.
  ...
}
catch (Exception ex)
{
  ...
}

Bu düzeni uygularken aşağıdaki düzenler de kullanışlı olabilir:The following patterns might also be useful when implementing this pattern:

  • Yeniden deneme düzeni.Retry pattern. Hizmete veya ağa bağlanmayı denediğinde daha önce başarısız olan bir işlemi saydam bir şekilde yeniden denemesini sağlayarak, uygulamanın beklenen, geçici hataları nasıl işleyebileceğini açıklar.Describes how an application can handle anticipated temporary failures when it tries to connect to a service or network resource by transparently retrying an operation that has previously failed.

  • Sistem durumu uç nokta izleme düzeni.Health Endpoint Monitoring pattern. Devre kesici, hizmet tarafından sunulan bir uç noktaya istek göndererek hizmetin durumunu test edebilir.A circuit breaker might be able to test the health of a service by sending a request to an endpoint exposed by the service. Hizmetin durumunu gösteren bilgileri döndürmesi gerekir.The service should return information indicating its status.