编写具有线程支持的简单断路器

时间:2018-09-22 15:03:24

标签: ruby multithreading circuit-breaker

我正在扩展一个simple circuter breaker编写的红宝石,以跨多线程工作...

到目前为止,我设法完成了这样的事情..

## following is a simple cicruit breaker implementation with thread support.
## https://github.com/soundcloud/simple_circuit_breaker/blob/master/lib/simple_circuit_breaker.rb
class CircuitBreaker
  class Error < StandardError
  end

  def initialize(retry_timeout=10, threshold=30)
    @mutex = Mutex.new
    @retry_timeout = retry_timeout
    @threshold = threshold
    reset!
  end

  def handle
    if tripped?
      raise CircuitBreaker::Error.new('circuit opened')
    else
      execute
    end
  end

  def execute
    result = yield
    reset!
    result
    rescue Exception => exception
      fail!  
    raise exception
  end

  def tripped?
    opened? && !timeout_exceeded?
  end

  def fail!
    @mutex.synchronize do
      @failures += 1
      if @failures >= @threshold
        @open_time = Time.now
        @circuit = :opened
      end
    end
  end

  def opened?
    @circuit == :opened
  end

  def timeout_exceeded?
    @open_time + @retry_timeout < Time.now
  end

  def reset!
    @mutex.synchronize do 
      @circuit = :closed
      @failures = 0
    end
  end
end

http_circuit_breaker = CircuitBreaker.new
http_circuit_breaker.handle { make_http_request }

但是我不确定几件事...

  • 多线程代码始终使我感到困惑,因此,我对这种说法似乎是正确的方法并不完全自信。

  • 读取操作不在互斥下: 尽管(我认为,我确保两个线程之间不会发生任何数据争用情况)互斥锁适用于写操作,但读操作不包含互斥锁。现在,由于存在这样一种情况,线程1在更改@circuit或@failure变量时具有保持的互斥体,而另一个线程读取了过时的值。 因此,我不能认为通过实现完全一致性(同时应用读取锁定)来进行彻底的操作值得在这里进行权衡。一致性可能是100%,但是由于过多的锁定,执行代码会变慢。

1 个答案:

答案 0 :(得分:0)

您在问什么还不清楚,所以我想您的帖子将被关闭。

尽管如此,我认为实现断路器的唯一线程安全方法将是在所有数据操作周围使用互斥锁,这将导致顺序流,因此基本上没有用。

否则,您将遇到诸如以下的竞态条件

  • 线程-a启动(由于网络问题服务器无法立即响应)
  • 线程-b启动(10秒后)
  • thread-b一切都很好
  • 线程a由于超时而中止->使用陈旧数据打开电路

马丁·福勒斯博客中提到的一个版本是结合线程池的断路器:https://martinfowler.com/bliki/CircuitBreaker.html