5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ElixirAdvent Calendar 2024

Day 22

④Elixirエッジコンピューティング:Elixirエッジサーバのクラスタリング入門

Last updated at Posted at 2024-12-22

この記事は、Elixir Advent Calendar 2024 シリーズ3 の21日目です

昨日は、@RyoWakabayashi さんで 「Advent of code 2015 Day 10 Part 1 & Part 2 を Livebook で楽しむ」 でした


piacere です、ご覧いただいてありがとございます :bow:

前回 は、クラウドを使わずにリアルタイム性を担保するElixirならではの分散コンピューティングの基礎を示しました

今回は、その基礎を土台にモダンなクラスタリング機能群を備える libcluster というライブラリを使って、Elixirにおける「クラスタリング」に入門していきます

なお今回の内容は、libcluster無しでも実現できますが、次回以降に必要なオートスケールやダウン時自動復帰も簡単に実現したいため、今回からlibclusterを使っていきます

本シリーズの全体像は、下記になります

:xmas-tree: There are 13 Elixir Advent Calendar, making for a hot winter! :xmas-tree:

Over the past 7 years, Elixir has consistently been a top-ranking language in the programming category of the Advent Calendar, claiming the #1 spot last year. This year, too, Elixir is sure to stay at the top.

We’re feeling the excitement again this year… Please support or subscribe! :bow:

https://qiita.com/advent-calendar/2024/elixir
https://qiita.com/advent-calendar/2024/ranking/feedbacks/categories/programming_languages
image.png

Elixirクラスタリング入門

まず、1台目のマシンでPJを作成し、分散接続可能な起動をします

--sup を付けると、libclusterを使うために必要なスーパーバイザー設定が標準で入ります

【1台目のマシン】
mkdir apps
cd apps
mix new a --sup
cd a

次に、2台目のマシンでもPJを作成します

【2台目のマシン】
mkdir apps
cd apps
mix new b
cd b

ここで、1台目の方に、libclusterのインストールを行います

mix.exs【1台目のマシン】
defmodule A.MixProject do
  use Mix.Project

  # Run "mix help deps" to learn about dependencies.
  defp deps do
    [
      # {:dep_from_hexpm, "~> 0.3.0"},
      # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
+     {:libcluster, "~> 3.4"}
    ]
  end

「EPMD」というElixirノードの位置共有/解決を行うメカニズムをクラスター化の戦略として使います

このEPMDは、前回行った Node.connectNode.list を支えるメカニズムでもあります

lib/a/application.ex【1台目のマシン】
defmodule A.Application do
  # See https://hexdocs.pm/elixir/Application.html

    def start(_type, _args) do
+   topologies = [
+     clusters1: [
+       strategy: Cluster.Strategy.Epmd,
+       config: [hosts: [:"node1@172.24.176.1", :"node2@172.24.176.2"]]
+     ]
+   ]
    children = [
      # Starts a worker by calling: A.Worker.start_link(arg)
      # {A.Worker, arg}
+     {Cluster.Supervisor, [topologies, [name: A.ClusterSupervisor]]}
    ]

これで1台目のマシンが、2台目のマシンを自動認識/接続し、クラスターを構成してくれるようになりました

なお、下記のように config.ex で設定することも可能です

では、クラスター化をするので、まず2台目のマシンを起動します

【2台目のマシン】
iex --name node2@172.24.176.2 --cookie edge-servers -S mix

その後、libclusterが動く1台目のマシンを起動します

【1台目のマシン】
mix deps.get
iex --name node1@172.24.176.1 --cookie edge-servers -S mix

その際、下記のようなメッセージが出れば、クラスター化に成功しています

[info] [libcluster:clusters1] connected to :"node1@172.24.176.1

ノードを見ると、自動接続していることが確認できます

【1台目のマシン】
iex> Node.list
[:"node1@172.24.176.1"]

なお、2台目のiexが起動していなかったり、ポートが閉じていたりすると、warningが出て、Node.listしても空のリストのままです

[warning] [libcluster:clusters1] unable to connect to :"node1@172.24.176.1"

3台以上のノードも、下記のように追記することで追加していけます

lib/a/application.ex【1台目のマシン】
defmodule A.Application do
  # See https://hexdocs.pm/elixir/Application.html

    def start(_type, _args) do
    topologies = [
      clusters1: [
        strategy: Cluster.Strategy.Epmd,
+       config: [hosts: [:"node1@172.24.176.1", :"node2@172.24.176.2", :"node3@172.24.176.3"]]

3台以上のノードがあると、下記のようになります

【1台目のマシン】
iex> Node.list
[:"node2@172.24.176.2", :"node3@172.24.176.3"]

クラスターのノード間アクセスの確認

さて、クラスター内の別ノードにアクセスしてみましょう

2台目のマシンのiexのプロセスIDを取得します

【2台目のマシン】
iex> self
#PID<0.138.0>

1台目のマシンから、この2台目のマシンのiexプロセス情報を取得できれば、クラスター化された別ノードへのアクセスが可能であることになります

【1台目のマシン】
iex> :erlang.list_to_pid('<0.138.0>') |> Process.info
[
  registered_name: :ssl_connection_sup,
  current_function: {:gen_server, :loop, 7},
  initial_call: {:proc_lib, :init_p, 5},
  status: :waiting,
  message_queue_len: 0,
  links: [#PID<0.139.0>, #PID<0.146.0>, #PID<0.133.0>],
  dictionary: [
    "$initial_call": {:supervisor, :ssl_connection_sup, 1},
    "$ancestors": [:ssl_sup, #PID<0.129.0>]
  ],

1台目のマシン上で2台目のマシンのiexプロセス情報が取得できました

ここまでで何が可能となったのか?

複数Elixirノードを1つのクラスターとして扱えるようになったことで、下記のようなことが可能となっています

これらにより、クラウドを使わずともクラスタリングが実現できるので、複数ノードで構成されるエッジサーバを簡単に実現できます

ただし、デフォルトのEPMD戦略だけでは、下記のようなモダンなクラスタリング制御は残念ながら出来ません

  • クラスターをオートスケールできない
  • ノードダウン後のアップ時にクラスターに自動復帰できない

これは、libclusterの限界では無く、あくまでEPMD戦略の限界なため、他の戦略を使う以降のコラムで解決していきます

終わりに

Elixirのクラスタリングが、思った以上に簡単に構築できることが共有できたら幸いです

一方で、現段階では実用的なクラスタリングのようにも見えないため、次回はそこを解決すべく、モダンなクラスタリング制御であるオートスケール/ダウン後自動復帰を実現 してきます

p.s.このコラムが、面白かったり、役に立ったら…

image.png にて、どうぞ応援よろしくお願いします :bow:


明日は、 @mokichi さんで 「Stripeで従量課金を実現する」 です

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?