Elixir 分佈式 Application 故障轉移和接管

Elixir 能夠運行在主/從, 故障轉移/接管模式下. 要使Elixir應用程序可以執行故障轉移/接管, Elixir應用程序必須是一個OTP應用程序.php

下面來建立一個包含Supervisor的Elixir項目node

mix new distro --sup

修改distro.ex添加logger模塊. 以記錄當觸發故障轉移/接管操做時的日誌記錄.git

defmodule Distro do
  use Application
  require Logger
  def start(type, _args) do
    import Supervisor.Spec, warn: false
    Logger.info("Distro application in #{inspect type} mode")
    children = [
      worker(Distro.Worker, [])
    ]
    opts = [strategy: :one_for_one, name: Distro.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

Distro.Worker是一個GenServer: 它使用全局名稱註冊, 假設其運行在集羣中的一個節點上, 全局註冊讓咱們不用考慮其實際的運行位置, 只須要提供註冊名稱就能夠訪問.github

defmodule Distro.Worker do
  use GenServer
  require Logger
  def start_link do
    GenServer.start_link(__MODULE__, [], name: {:global, __MODULE__})
  end
  def init([]) do
    {:ok, [], 1000}
  end
  def handle_info(:timeout, state) do
    Logger.debug "timeout"
    {:noreply, state, 1000}
  end
end

編譯app

$ mix compile

應用程序分佈

本節闡述瞭如何把一個應用程序分佈到多個節點上分佈式

假設應用程序運行在3個節點上, 名稱分別爲abc, bcd, def. 建立三個配置文件以下:ui

touch config/abc.config
touch config/bcd.config
touch config/def.config

配置文件中有3個重要的鍵值對. distributed, sync_nodes_mandatorysync_nodes_timeout, 其中:debug

  1. distributed 定義了分佈式應用的啓動延遲, 備用節點.日誌

  2. sync_nodes_mandatory 定義強制要求的節點code

  3. sync_nodes_timeout 定義了distributed中全部節點都啓動完成須要等待的時間, 若是在此時間內要求的節點沒有所有啓動, 那麼全部節點上的應用啓動失敗.

abc.config

[
  {logger,[{console,[{format,<<"$date $time $metadata[$level] $message\n">>}]}]},
  {kernel,
    [{distributed, [
        {'distro', 5000, ['abc@192.168.8.104', {'bcd@192.168.8.104', 'def@192.168.8.104'}]}]},
        {sync_nodes_mandatory, ['bcd@192.168.8.104', 'def@192.168.8.104']},
        {sync_nodes_timeout, 30000}
]}].

bcd.config

[
  {logger,[{console,[{format,<<"$date $time $metadata[$level] $message\n">>}]}]},
  {kernel,
    [{distributed, [
        {distro,5000, ['abc@192.168.8.104', {'bcd@192.168.8.104', 'def@192.168.8.104'}]}]},
        {sync_nodes_mandatory, ['abc@192.168.8.104', 'def@192.168.8.104']},
        {sync_nodes_timeout, 30000}
]}].

def.config

[
  {logger,[{console,[{format,<<"$date $time $metadata[$level] $message\n">>}]}]},
  {kernel,
    [{distributed, [
        {distro,5000, ['abc@192.168.8.104', {'bcd@192.168.8.104', 'def@192.168.8.104'}]}]},
        {sync_nodes_mandatory, ['abc@192.168.8.104', 'bcd@192.168.8.104']},
        {sync_nodes_timeout, 30000}
]}].

在不一樣的終端自動所有3個節點

iex --name abc@192.168.8.104 -pa _build/dev/lib/distro/ebin/ --app distro \
--erl "-config config/abc"

iex --name bcd@192.168.8.104 -pa _build/dev/lib/distro/ebin/ --app distro \
--erl "-config config/bcd"

iex --name def@192.168.8.104 -pa _build/dev/lib/distro/ebin/ --app distro \
--erl "-config config/def"

驗證步驟

bcd, defabc 的備用節點. bcd 優先於def, 若是abc死掉, 應用程序會在bcd上重啓, 若是bcd死掉, 應用程序會轉移到def, 這時候abc, bcd 修復啓動後, 應用會被abc接管.

  1. 終止(Ctrl+C兩次)節點abc@192.168.8.104後,5秒內會在節點bcd@192.168.8.104上重啓應用

  2. 再次啓動節點abc@192.168.8.104後,應用在bcd@192.168.8.104上中止, 應用被恢復後的abc@192.168.8.104節點接管(Takeover)

參考資料

  1. Elixir Application Failover/Takeover

  2. Distributed OTP Applications

  3. 源碼倉庫

  4. 分佈式應用

相關文章
相關標籤/搜索