Написание простого выключателя с поддержкой потока - PullRequest
0 голосов
/ 22 сентября 2018

Я хочу расширить простой автоматический выключатель письменный рубин для работы в нескольких потоках ...

И до сих пор мне удается достичь чего-то подобного ..

## 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 голосов
/ 24 сентября 2018

неясно, что вы спрашиваете, поэтому я думаю, что ваше сообщение будет закрыто.

тем не менее, я думаю, что единственный потокобезопасный способ реализации автоматического выключателя - это иметь мьютекс вокруг всех операций с данными, что приведет к последовательному потоку, так что это в основном бесполезно.

в противном случае вы будете иметь условия гонки, такие как

  • Запускается thread-a (сервер не отвечает сразу из-за проблем с сетью)
  • Запускается thread-b (через 10 секунд)
  • thread-b завершает все исправления
  • thread-a прерывает работу из-за тайм-аута -> размыкает цепь с устаревшими данными

версия, упомянутая в мартин Фаулерахblog - это автоматический выключатель в сочетании с пулом потоков: https://martinfowler.com/bliki/CircuitBreaker.html

...