Global Dynamic Supervisor в кластере - PullRequest
0 голосов
/ 01 октября 2018

У меня есть уникальная проблема, которую мне не нужно было решать в elxir.

Мне нужно использовать динамический супервизор для динамического запуска (n) количества детей в кластерной среде.Я использую libcluster для управления кластеризацией и использую реестр глобальных процессов для поиска динамического pid супервизора. Вот что происходит:

global: Name conflict terminating {:packer_supervisor, #PID<31555.1430.0>}

Вот код для супервизора:

defmodule EcompackingCore.PackerSupervisor do
  use DynamicSupervisor
  require Logger

  def start_link() do
    DynamicSupervisor.start_link(__MODULE__, :ok, name: {:global, :packer_supervisor})
  end

  def init(:ok) do
    Logger.info("Starting Packer Supervisor")
    DynamicSupervisor.init(strategy: :one_for_one)
  end

  def add_packer(badge_id, packer_name) do
    child_spec = {EcompackingCore.Packer, {badge_id, packer_name}}
    DynamicSupervisor.start_child(:global.whereis_name(:packer_supervisor), child_spec)
  end

  def remove_packer(packer_pid) do
    DynamicSupervisor.terminate_child(:global.whereis_name(:packer_supervisor), packer_pid)
  end

  def children do
    DynamicSupervisor.which_children(:global.whereis_name(:packer_supervisor))
  end

  def count_children do
    DynamicSupervisor.count_children(:global.whereis_name(:packer_supervisor))
  end

end

Кажется, проблема в том, что супервизор запускается на обоих узлах.Что было бы лучшим способом справиться с этим?Мне действительно нужно, чтобы супервизор был динамичным, чтобы я мог эффективно управлять рабочими модулями.Возможно, другой реестр?

Спасибо за вашу помощь.

Ответы [ 3 ]

0 голосов
/ 04 октября 2018

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

Этот центральный узел только запускается, контролировать и использовать базу данных для сохранения других узлов'status and pid.

Когда узел присоединяется и отключается, вы можете получить сообщение о его завершении и обработать его (обновить базу данных).

Единственным недостатком этого метода является то, что вы можете иметь толькоодин центральный узел, но поскольку этот узел делает простые вещи, он практически стабилен, и работает в нашей производственной системе в течение года.

0 голосов
/ 09 октября 2018

Если вам нужно довольно простое решение, которое работает с глобальным реестром процессов, вы можете изменить свой динамический супервизор start_link

defmodule EcompackingCore.PackerSupervisor do
  use DynamicSupervisor
  require Logger

  def start_link() do
    case DynamicSupervisor.start_link(__MODULE__, :ok, name: {:global, :packer_supervisor}) do
      {:ok, pid} ->
        {:ok, pid}
      {:error, {:already_started, pid}} ->
        # you need this pid so on each node supervisor 
        # of this dynamic supervisor can monitor this same pid
        # so each node tracks existence of your process
        {:ok, pid}
      any -> any
    end
  end

  def init(:ok) do
    Logger.info("Starting Packer Supervisor")
    DynamicSupervisor.init(strategy: :one_for_one)
  end

  def add_packer(badge_id, packer_name) do
    child_spec = {EcompackingCore.Packer, {badge_id, packer_name}}
    DynamicSupervisor.start_child(:global.whereis_name(:packer_supervisor), child_spec)
  end

  def remove_packer(packer_pid) do
    DynamicSupervisor.terminate_child(:global.whereis_name(:packer_supervisor), packer_pid)
  end

  def children do
    DynamicSupervisor.which_children(:global.whereis_name(:packer_supervisor))
  end

  def count_children do
    DynamicSupervisor.count_children(:global.whereis_name(:packer_supervisor))
  end
end

Что многие скажут об этом решении, так это то, что вам не следует делать этого, поскольку в случаеразделения сети, вы в конечном итоге с двумя или более глобальными процессами в кластере.Но вы даже можете справиться с этим, если внедрите какой-нибудь узел мониторинга / отслеживания, чтобы вы знали, сколько узлов вы «видите» в кластере.

Например, если размер кластера iz 5, вы можете создать правило проверки, которое проверит, видите ли вы более 3 узлов, если нет, то вы запланируете следующий запуск, скажем, в течение 1 секунды, и попытаетесь зарегистрироваться снова глобально.ваш динамический супервизор до тех пор, пока правило проверки не вернет true (это означает, что вы находитесь в мажоритарной группе, и вы можете предложить согласованность в этой группе).С другой стороны, если ваш узел принадлежит к группе меньшинств и уже содержит глобальный динамический супервизор, выключите его и запланируйте запуск через 1 секунду.

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

  • Swarm имеет встроенные алгоритмы кольца и статического кольца кворума, но использует хеширование для распределения нагрузки по кластеру.Это хорошее решение, если у ваших работников есть ID, для которого вы можете вычислить хеш.
  • Син является другой альтернативой.
0 голосов
/ 04 октября 2018

После небольшого исследования я нашел решение:

Я сейчас использую https://github.com/bitwalker/swarm для обработки регистрации pid.Это позволяет настраивать процессы в кластере и предлагает поддержку передачи обслуживания, если один из узлов выходит из строя.

...