この記事は、Elixir Advent Calendar 2024 シリーズ3 の14日目です
昨日は、@RyoWakabayashi さんで 「KinoStlViewer で Three.js による 3D コンテンツを表示する」 でした
piacere です、ご覧いただいてありがとございます
前回 は、IBMのエッジコンピューティングレポートを土台に、エッジコンピューティングのメリットやアーキテクチャ、資源特性、クラウド/エッジデバイス/エッジサーバーによって発展する未来について紐解きました
その一方、現実問題として、クラウド無を前提とするエッジコンピューティング開発において、「クラウドが無いと開発できない」という現在の開発/プログラマ事情に対し、「Elixirであれば、短期間でエッジコンピューティングを攻略できる」というシンプルな着想を挙げました
今回は、Elixirによる実践的なエッジコンピューティングの構築例で、まずElixirエッジサーバーを構築するところからスタートします
リアルタイム性:エッジコンピューティングに真っ先に求められるもの
IBMレポートにあるエッジコンピューティングの最も顕著なメリットの1つ目に、「リアルタイム性」が挙げられています
このリアルタイム性は、下記のような点で損なわれやすい性質を持っています
その多くは、一般的なWeb開発やAI開発では、「常識」や「当たり前」に使えるものや、ケアしない慣習が強いものばかりであるが故に、その正反対を強く求めるエッジコンピューティングを始める上では、認識上の壁や阻害要因ととなりかねないものばかりです
-
① クラウドで処理を行うと損なわれる
- 通信にかかるオーバーヘッドで損なわれる
- アジア諸国やアフリカ等では通信速度が原因でリアルタイム性が劇的に劣化する
- クラウドの多くが北米や北欧に配置されているため
- ローカルリージョンの設備は北米や北欧と比べ、劣化しているケースが多い
- アジア諸国やアフリカ等では通信速度が原因でリアルタイム性が劇的に劣化する
- 通信の不安定さでMTBF/MTTRが悪化して損なわれる
- クラウドはインターネットを使うことで通信が不安定になりやすい
- クラウドは共有利用のベストエフォートのため、他システムの負荷が影響しやすい
- 通信にかかるオーバーヘッドで損なわれる
-
② 一方で、クラウド設備が無ければリアルタイム性担保のための性能向上が欠落する
- 分散コンピューティング
- ECS/EKSやGKE、App Runner、Cloud Run、AKSのようなマルチクラスタサービス
- LambdaやCloud Functions、Azure FunctionsのようなFaaS
- 分散DB/ストレージ/キャッシュ/キュー
- AuroraやCloud Spanner、Cosmos DBのようなマルチリージョンDB
- S3やGCS、Filestore、Blob Storage、Azure Filesのような分散ストレージ
- ElastiCacheやMemorystore、Azure Cacheのような分散キャッシュ
- SQN/SNSやCloud Pub/Sub、Azure Service Bus、Event Gridのような分散キュー
- 分散コンピューティング
-
③ データ変換/加工のパイプラインやストリーミングが最適化できないと損なわれる
- データ処理の並列化による高速化
- バックプレッシャーによる効率良いデータストリーミング
- パイプライン上のデータ操作最適化
-
④ エッジ側の処理負荷を柔軟に調整できないと損なわれる
- 負荷上昇時のエッジデバイスからエッジサーバーへのオフロード
- 負荷軽減時のエッジデバイスからエッジデバイスへのデオフロード
- エッジサーバーが抱え切れない大量データのクラウドへのオフロード
- 上記をコントロールするロードバランサー
-
⑤ 低遅延/高速プロトコルが気軽に採用できないと損なわれる
- WebSocket
- TCP/IPよりも高速な通信プロトコルの利用
- TCPよりもUDPを重視
-
⑥ 耐障害性が高くないとMTBF/MTTRが悪化して損なわれる
- 外形監視/再起動に頼らない内形監視/再起動
- プロセス異常時の復帰やリカバリー
- (上記した分散コンピューティングによる冗長性の実現)
-
⑦ 無停止アップデートが出来ないとMTBF/MTTRが悪化して損なわれる
- ホットリロード
- ブルーグリーンデプロイ
-
⑧ その他、性能向上策が取れないと損なわれる
- より高速かつ分散に向いた処理系でのコード書き換え
- リアルタイムOSの採用
- FPGAのような非ノイマン型コンピューティングへの載せ替え
これらに対し、以降では、Elixirであれば叶う対策をコード例で示していきます
クラウドを使わずに分散コンピューティングを叶える
上記①のクラウド利用を避けつつ、②の分散コンピューティングを叶えるという「いいとこどり」をElixirは割とカンタンに叶えられます
まず、1台目のマシンでPJを作成し、分散接続可能な起動をします
ここで、--cookie edge-servers
に設定されているのは、同じ分散ノードに属することを示す名前で分散接続可能にしています
mkdir apps
cd apps
mix new a
cd a
iex --name node1@192.168.10.101 --cookie edge-servers -S mix
次に、2台目のマシンでもPJを作成し、やはり分散接続可能な起動をします
mkdir apps
cd apps
mix new b
cd b
iex --name node2@192.168.10.102 --cookie edge-servers -S mix
2台目のマシンから、1台目のマシンに接続し、接続ノードリストを見ると、1台目のマシンが見れます
Node.connect(:"node1@192.168.10.101")
Node.list
[:"node1@192.168.10.101"]
1台目のマシンからも2台目のマシンが見れます
Node.list
[:"node2@192.168.10.102"]
この状態から、1台目のマシンに定義したコードを、2台目のマシンでも利用可能にしてみます
defmodule A do
def func(count) do
for i <- 1..count, do: i
end
end
まず、1台目のマシン上で、これを実行してみます
A.func(5)
[1, 2, 3, 4, 5]
この段階では、2台目のマシン上にこの定義が無いため、エラーになります
A.func(5)
** (UndefinedFunctionError) function A.func/1 is undefined (module A is not available)
A.func(5)
iex:4: (file)
ここで、1台目のマシンにあるコードを、下記コードで2台目に複製できます
nl(A)
{:ok, [{:"node2@192.168.10.102", :loaded, A}]}
これで、2台目のマシン上でも実行できるようになります
A.func(5)
[1, 2, 3, 4, 5]
3台以上の接続がある場合でも、同様に複製できます
nl(A)
{:ok,
[{:"node2@192.168.10.102", :loaded, A}, {:"node3@192.168.10.103", :loaded, A}]
このようにElixirは、クラウドやコンテナを使うことも無く、分散コンピューティングをいとも容易く叶えます
終わりに
今回は、エッジコンピューティングのリアルタイム性担保のために、最も重要な「クラウド無しでの分散コンピューティング」をElixirのみで叶えました
しかも、サードパーティのライブラリやFWも特に導入しておらず、デフォルト状態のElixirのみで実現できています
この土台を中心に、上記②のマルチマスタかつ冗長化された分散DBの実現や、上記⑥の耐障害性とコンピュートエンジンの冗長化など、エッジコンピューティングに求められる「リアルタイム性」を叶える様々な事柄が、やはりカンタンに実現できます
次回は、上記②の分散DBについて、コードと共に実践していきます
p.s.このコラムが、面白かったり、役に立ったら…
明日は、 @ytnobody さんで 「Ash Frameworkに入門しようとしたら準備がちょっと大変だったので、devcontainerを整備して簡単に始められるようにした」 です