分析测试百科网

搜索

喜欢作者

微信支付微信支付
×

断路器模式概述(一)

2020.10.05
头像

王辉

致力于为分析测试行业奉献终身

软件系统对运行在不同进程或者网路中不同的机器的软件进行远程调用是很常见的。内存中调用和远程调用之间的一个主要区别是,远程调用可能会失败,或者在达到某个超时限制之前挂起而没有响应。更糟糕的是,如果一个响应延迟的服务提供方上有许多调用者,那么您可能会耗尽关键资源,导致跨多个系统的连锁故障。Michael Nygard在他的优秀著作《发布》中推广了断路器模式,以防止这种灾难性的连锁故障。

断路器的基本原理很简单。您将一个受保护的函数调用封装在一个断路器对象中,该断路器对象监视故障。一旦故障达到某个阈值,断路器就会跳闸,所有对断路器的继续调用都会返回一个错误,受保护的调用也不会继续。如果断路器跳闸,您通常还需要通过监视器进行警报。

wx_article_20190426102817_VYQsTS.jpg

下面是Ruby写的一个简单示例,用于防止超时。

我使用block (Lambda)设置了断路器,它是受保护的调用。

cb = CircuitBreaker.new {|arg| @supplier.func arg}

断路器存储block,初始化各种参数(阈值、超时和监视功能),并将断路器重置为关闭状态。

class CircuitBreaker...

attr_accessor :invocation_timeout, :failure_threshold, :monitor

def initialize &block

@circuit = block

@invocation_timeout = 0.01

@failure_threshold = 5

@monitor = acquire_monitor

reset

end

如果线路关闭,则调用断路器将调用底层block,如果打开则返回错误

# client code

aCircuitBreaker.call(5)

class CircuitBreaker...

def call args

case state

when :closed

begin

do_call args

rescue Timeout::Error

record_failure

raise $!

end

when :open then raise CircuitBreaker::Open

else raise "Unreachable Code"

end

end

def do_call args

result = Timeout::timeout(@invocation_timeout) do

@circuit.call args

end

reset

return result

end

如果我们调用超时,我们故障计数器计数增加,调用成功则将其重置为零。

class CircuitBreaker...

def record_failure

@failure_count += 1

@monitor.alert(:open_circuit) if :open == state

end

def reset

@failure_count = 0

@monitor.alert :reset_circuit

end

将故障失败数与阈值进行比较,确定断路器的状态

class CircuitBreaker...

def state

(@failure_count >= @failure_threshold) ? :open : :closed

end


互联网
仪器推荐
文章推荐