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
Condition
classes
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 PollCondition
para 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.status
método de classe para obter o estado dos servidores mongo
e 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:
:init
– Quando Deus cria o relógio:start
– Deus está tentando iniciar o processo:up
– Processo em execução:restart
– Deus está tentando reiniciar o processo
As instâncias de observação dependentes do middleware precisarão ser mantidas no :init
estado até que o middleware esteja no :up
estado. 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_running
MiddlewareRunning
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 dependents
membro 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 :init
a :start
e :up
a :init
sã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.