③Elixirエッジコンピューティング：クラウドを使わないElixir分散コンピューティング

この記事は、[Elixir Advent Calendar 2024 シリーズ3](https://qiita.com/advent-calendar/2024/elixir) の21日目です

昨日は、@RyoWakabayashi さんで [「KinoLink で Livebook に OGP 対応のリッチなリンクを表示する」](https://qiita.com/RyoWakabayashi/items/e4e546e87066ee04aa54) でした

---

[piacere](https://twitter.com/piacere_ex) です、ご覧いただいてありがとございます :bow:

[前回](https://qiita.com/piacerex/items/979cfa7575b880144c4c) は、エッジコンピューティングで最も重要なのは「リアルタイム性」であり、それを阻害するのは一般的なWeb／AI開発の「常識」や「当たり前」であるクラウドにある点を言及した後、クラウド無しでも分散コンピューティングを叶えるElixirのイディオムを紹介しました

今回は、クラウドを使わずにリアルタイム性を担保するために、複数台のエッジサーバをElixirノード群で構成する基礎について解説します

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

:::note warn
[①クラウドからエッジ／エッジサーバに拡がる未来とElixir](https://qiita.com/piacerex/items/ba0143f784cf360dda5f)
[②Elixiが叶えるエッジコンピューティングで最も重要なこと](https://qiita.com/piacerex/items/979cfa7575b880144c4c)
[③クラウドを使わないElixir分散コンピューティング](https://qiita.com/piacerex/items/401cbe7bb5898c3d8308)
[④Elixirエッジサーバのクラスタリング入門](https://qiita.com/piacerex/items/f49b9531f86d7aa02b2a)
[⑤Elixirエッジサーバのオートスケール／ダウン後自動復帰](https://qiita.com/piacerex/items/3a19a3a43f3d49bf3f63)
:::

### :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](https://speakerdeck.com/piacerex/7nian-jian-sok-ke-totupurankaru-risitaelixirniyoukoso?slide=13) in the programming category of the Advent Calendar, [claiming the #1 spot last year](https://qiita.com/advent-calendar/2023/ranking/feedbacks/categories/programming_languages). 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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/74211dea-90bd-3de9-d700-24d25414aa05.png)](https://qiita.com/advent-calendar/2024/ranking/feedbacks/categories/programming_languages)

# 複数ノードを接続する

「① クラウドで処理すると損なわれる」を加味してクラウド利用を避けつつ、「② とは言え、クラウド相当が無ければ担保が大変」の「分散コンピューティング」を叶えるという「いいとこどり」をElixirは割とカンタンに叶えられます

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

ここで、`--cookie edge-servers` に設定されているのは、同じ分散ノードに属することを示す名前で分散接続可能にしています

```diff_elixir:【1台目のマシン】
mkdir apps
cd apps
mix new a
cd a
iex --name node1@172.24.176.1 --cookie edge-servers -S mix
```

次に、2台目のマシンでもPJを作成し、やはり分散接続可能な起動をします

```diff_elixir:【2台目のマシン】
mkdir apps
cd apps
mix new b
cd b
iex --name node2@172.24.176.2 --cookie edge-servers -S mix
```

2台目のマシンから、1台目のマシンに接続し、接続ノードリストを見ると、1台目のマシンが見れます

ただし、ポート番号4369をファイアウォール等で閉じていると使えないので、あらかじめ空けておいてください


```diff_elixir:【2台目のマシン】
iex> Node.connect(:"node1@172.24.176.1")
iex> Node.list
[:"node1@172.24.176.1"]
```

1台目のマシンからも2台目のマシンが見れます

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

# ノード間でプロセスを連携させる

2台が接続した状態で、プロセス連携をしてみましょう

1台目のマシンから2台目のマシンのiexにメッセージを送るために、まず2台目のマシンのiexにプロセス名を付けます

```:【2台目のマシン】
iex> :global.register_name(:iex2, self)
:yes
```

1台目のマシンから、この2台目のマシンのiexプロセスにメッセージを送るには、`send` を使います

```diff_elixir:【1台目のマシン】
iex> send(:global.whereis_name(:iex2), "hello")
"hello"
```

2台目のマシンのiexプロセスにて `receive` で受信し、受信したメッセージを表示しました

```diff_elixir:【2台目のマシン】
iex> receive do
...>   message -> message
...> end
"hello"
```

1台目のマシンから、2台目のマシン上のモジュールを呼び出すことも出来ます

```diff_elixir:【1台目のマシン】
iex> send(:global.whereis_name(:iex2), &B.hello/0)
"hello"
```

2台目のマシン上にしか無いモジュールの関数を呼び出しました

```diff_elixir:【2台目のマシン】
iex> receive do
...>   func -> func.()
...> end
:world
```

このように、ノード間を跨いだプロセス連携による分散処理が可能です

# ノード間でモジュールを複製する

先ほどは、1台目のマシンから2台目のマシン上の関数を呼びましたが、今度は1台目のマシンに定義したコードを、2台目のマシンでも利用可能にしてみます

```diff_elixir:lib/a.ex 【1台目のマシン】
defmodule A do
  def func(count) do
    for i <- 1..count, do: i
  end
end
```

まず、1台目のマシン上で、これを実行してみます

```diff_elixir:【1台目のマシン】
iex> A.func(5)
[1, 2, 3, 4, 5]
```

この段階では、2台目のマシン上にこの定義が無いため、エラーになります

```diff_elixir:【2台目のマシン】
iex> A.func(5)
** (UndefinedFunctionError) function A.func/1 is undefined (module A is not available)
    A.func(5)
    iex:4: (file)
```

ここで、1台目のマシンにあるコードを、下記コードで2台目に複製できます

```diff_elixir:【1台目のマシン】
iex> nl(A)
{:ok, [{:"node2@172.24.176.2", :loaded, A}]}
```

これで、2台目のマシン上でも実行できるようになります

```diff_elixir:【2台目のマシン】
iex> A.func(5)
[1, 2, 3, 4, 5]
```

3台以上の接続がある場合でも、同様に複製できます

```diff_elixir:【1台目のマシン】
iex> nl(A)
{:ok,
 [{:"node2@172.24.176.2", :loaded, A}, {:"node3@172.24.176.3", :loaded, A}]
```

このようにElixirは、クラウドやコンテナを使うこと無く、分散コンピューティングをいとも容易く叶えます

# 終わりに

今回は、エッジコンピューティングのリアルタイム性担保のために、最も重要な「クラウド無しでの分散コンピューティング」をElixirのみで叶えました

しかも、サードパーティのライブラリやFWも特に導入しておらず、デフォルト状態のElixirのみで実現できています

この土台を中心に、上記②のマルチマスタかつ冗長化された分散DBの実現や、「⑥ 耐障害性が高くないとMTBF／MTTRが悪化して損なわれる」で述べた耐障害性とコンピュートエンジンの冗長化など、エッジコンピューティングに求められる「リアルタイム性」を叶える様々な事柄が、やはりカンタンに実現できます

[次回は、クラウド無しでの分散コンピューティングの基本要素である「クラスタリング」を構築](https://qiita.com/piacerex/items/f49b9531f86d7aa02b2a) していきます

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/907a8695-4d83-1b5c-8052-d0ce52de5f66.png) にて、どうぞ応援よろしくお願いします :bow:

---

明日は、 @RyoWakabayashi さんで [「Advent of code 2015 Day 11 Part 1 & Part 2 を Livebook で楽しむ」](https://qiita.com/RyoWakabayashi/items/61c3dbce3948623fb326) です