写点什么

【设计模式】断路器模式

用户头像
soolaugust
关注
发布于: 2021 年 01 月 12 日
【设计模式】断路器模式

在目前微服务和云端化日益盛行的今天,软件开发变得原来越复杂。传统的设计模式已经无法应对新出的业务场景。因此诞生了很多新的设计模式。这些设计模式针对特定的业务场景提供了设计上的最佳实践。今天所说的断路器模式就是其中的一种。

场景

在微服务中,服务之间不再是通过直接调用的方式来交互。更多的可能是通过网络访问接口或者数据通信的方式来完成。服务甚至都不布在一个地方,可能使用着不同的硬件资源。这就导致我们访问服务可能会出现异常,但是这个异常并不是逻辑上的问题,可能是网络暂时较弱,或者资源被其他占用。所以我们不能以传统的函数交互的方式来处理返回的异常。

思路

既然返回的异常可能是暂时的,那么我们可以想到设置失败机制来保证当服务可用时继续访问服务。当然不能无限的尝试,因为尝试也是需要占用资源的,如果有大量的服务不可用,我们的尝试线程可能会占用大量的系统资源从而导致我们服务本身出现不可用的状态。


那么当我们重试次数超过了一定次数,那么我们就暂停尝试,等过段时间再进行尝试,如果还是不行,则再等待一段时间,依次类推。而如果服务可用的话,那么我们就正常访问服务即可。

设计

从我们上面的思路不难看出,我们可以设计一个状态机来抽象我们上面的思路。如下图:


image.png


  • CLOSE:断路器处于关闭状态,表示可以直接访问服务,服务正常

  • OPEN:断路器处于开启状态,表示服务暂时不可用,将直接返回错误

  • HALF_CLOSE:断路器处于半开状态,这个时候如果接下来访问服务正常,则进入到 CLOSE 状态,如果访问仍然异常,则重新进入到 OPEN 状态。


我们可以用如下的代码来简单理解我们这个状态机(Go 语言):


func NewCircuitBreaker() *CircuitBreaker {    // define a state machine    cb := &CircuitBreaker{        StateMachine: NewStateMachine(Close),    }    // CLOSE -> OPEN : failed count reached threshold    cb.AddHandler(Close, ReachFailedThreshold, cb.ReachFailedThreshold)    // OPEN -> HALF_CLOSE : timeout    cb.AddHandler(Open, Timeout, cb.Timeout)    // HALF_OPEN -> OPEN : failed again    cb.AddHandler(HalfOpen, FailedAgain, cb.FailedAgain)    // HALF_OPEN -> CLOSE : success    cb.AddHandler(HalfOpen, Success, cb.Success)    return cb}
复制代码

我们简单测试一下:

func TestNewCircuitBreaker(t *testing.T) {    cb := NewCircuitBreaker()    result := cb.Call(ReachFailedThreshold)    if result != Open {        t.Fatal("circuit breaker status should be OPEN\n")    }    result = cb.Call(Timeout)    if result != HalfOpen {        t.Fatal("circuit breaker status should be HALF_OPEN\n")    }    result = cb.Call(FailedAgain)    if result != Open {        t.Fatal("circuit breaker status should be OPEN\n")    }    cb.setStatus(HalfOpen)    result = cb.Call(Success)    if result != Close {        t.Fatal("circuit breaker status should be CLOSE\n")    }}
复制代码


我们从日志的输出可以到上面我们画的状态机过程:


image.png


总结

我们上面实现了一个简单的断路器模式,实际上根据自己的业务场景,可以实现更为复杂的断路器模式,达到熔断,降级等功能。


代码已经放到 Github 上了,欢迎 star 和提 issue:https://github.com/soolaugust/circuit-breaker-go


发布于: 2021 年 01 月 12 日阅读数: 21
用户头像

soolaugust

关注

公众号:雨夜随笔 2018.09.21 加入

公众号:雨夜随笔

评论

发布
暂无评论
【设计模式】断路器模式