Deus com Dependências de Ordem de Inicialização

Dependências de Deus e da ordem de inicialização

Percebi algumas perguntas sobre como oferecer suporte a dependências de ordem de inicialização usando Deus. Abaixo estão as instruções sobre como usei o God DSL para garantir a ordem de inicialização do processo.

Condições de Deus

Uma nova Condição Divina é necessária e deve ser herdada de uma das classes de Condição Divina .
Uma nova condição tem os seguintes requisitos:

  • O nome da classe de condição é camel case
  • É derivado de uma das três Conditionclasses

PollCondition – pesquisar o sistema com base em um intervalo definido
EventCondition – a condição ocorre com base em um evento do sistema
TriggerCondition – quando uma tarefa está se movendo de um estado para outro

Usei um PollConditionpara validar se o middleware está instalado e funcionando.

def middleware_up?
s
= God.status
(s['mongo'][:state] == :up) && (s['apollo'][:state] == :up)
end

class MiddlewareRunning < God::PollCondition

def valid?
super
end

def test
middleware_up
?
end
end

Use o God.statusmétodo de classe para obter o estado dos servidores mongoe apollo.

Transições de estado de tarefa

Usando o God DSL, você cria um Watch para cada servidor. Um relógio pode estar em um dos seguintes estados:

  1. :init – Quando Deus cria o relógio
  2. :start – Deus está tentando iniciar o processo
  3. :up – Processo em execução
  4. :restart – Deus está tentando reiniciar o processo

As instâncias de observação dependentes do middleware precisarão ser mantidas no :initestado até que o middleware esteja no :upestado. Então, eu defino a transição da seguinte maneira:

w.transition(:init, :start) do |on|
on
.condition(:middleware_running) do |c|
c
.interval = 3.seconds
end
end

Observe que o símbolo é a classe de caixa de camelo suavizada.:middleware_runningMiddlewareRunning

w.transition(:up, :init) do |on|
on
.condition(:process_exits)
end

Além disso, se o processo sair, voltamos ao estado de inicialização e garantimos que o middleware está instalado e funcionando antes de passar para o estado:restart

Adicionando Dependentes à Vigilância

Agora que o middleware está instalado e funcionando, há alguns processos em que desejo garantir a ordem de inicialização.

Um membro para dependentes é adicionado ao Watch. A matriz de dependentes associados é atribuída ao novo dependentsmembro Watch:

# This adds a dependents member array to the watch instance and then adds the dependents to the member
def add_dependents(klass, *dependents)
class << klass
attr_accessor
:dependents
end
klass
.dependents = dependents
end

O Watch DSL se parece com:

God.watch do |w|
w
.group = "stooges_servers"
w
.name = "moe_server"
w
.start = "#{APP_ROOT}/bin/moe_server --log-file #{APP_ROOT}/log/moe.log"
w
.log = "#{APP_ROOT}/log/moe.log"
w
.interval = 30.seconds
add_dependents w
, "larry_server", "curly_server"
.
.
.

Condição dependente

Garante que o middleware esteja ativo e em execução e todos os processos dependentes estejam em execução antes de passar para o estado inicial. Um Condtion está associado a um relógio. Cada instância de Condition tem acesso à instância Watch associada.

class DependentsRunning < God::PollCondition
def valid?
super
end

def test
middleware_up
? ? all_dependents_up? : false
end

def all_dependents_up?
gps
= God.status
@watch.dependents.each do |name|
dependent
= gps[name]
if not dependent.nil?
if dependent_up? dependent
applog
@watch, :info, "Dependent process up: #{name}"
else
return false
end
else
return false
end
end
return true # if for some reason the dependent list is empty
end

def dependent_up?(dependent)
dependent
[:state] == :up ? true : false
end
end

Código Extra

Nas secções sobre tarefas transições de estado apenas as transições para :inita :starte :upa :initsão discutidos. Aqui estão as outras transições de estado que são tiradas basicamente da documentação de Deus.

def life_cycle(w)
# lifecycle
w
.lifecycle do |on|
on
.condition(:flapping) do |c|
c
.to_state = [:start, :restart]
c
.times = 5
c
.within = 5.minute
c
.transition = :unmonitored
c
.retry_in = 10.minutes
c
.retry_times = 5
c
.retry_within = 2.hours
end
end
end

def server_transitions(w)

w
.transition(:start, :up) do |on|
on
.condition(:process_running) do |c|
c
.running = true
end
end

w
.transition([:start, :restart], :up) do |on|
on
.condition(:process_running) do |c|
c
.running = true
end

# failsafe
on
.condition(:tries) do |c|
c
.times = 5
c
.transition = :start
end
end

# init if process is not running
w
.transition(:up, :init) do |on|
on
.condition(:process_exits)
end
life_cycle w

end

Notas de Fechamento

Foi muito fácil usar o God DSL para implantar rapidamente uma infraestrutura de gerenciamento de processos. Eu precisava de uma resposta rápida para gerenciamento de processos e como garantir um pedido inicial. Eu faço muito trabalho no front-end, back-end e em muitos ambientes, eu precisava de uma resposta de baixa curva de aprendizado. Não sou um especialista em Deus, então caveat emptor . Por favor, corrija, compartilhe e melhore.