1

我正在寻找扩展一个简单的电路断路器编写的 ruby​​ 以跨多个线程工作......

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

## 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%,但由于过多的锁,执行代码会变慢。

4

1 回答 1

-1

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

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

否则您将遇到竞争条件,例如

  • thread-a 启动(由于网络问题,服务器没有立即响应)
  • thread-b 启动(10 秒后)
  • thread-b 完成一切都很好
  • thread-a 由于超时而中止 -> 用过时的数据打开电路

martin fowlers 博客中提到的一个版本是结合线程池的断路器:https ://martinfowler.com/bliki/CircuitBreaker.html

于 2018-09-24T16:06:09.017 回答