Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Elixir の GenServer でアクタープログラミングしてみよう

Elixir の GenServer でアクタープログラミングしてみよう

これは関数型まつり2026のプレゼン資料です。
https://fortee.jp/2026fp-matsuri/proposal/904cc5d9-b328-450e-8f60-5c3bf4200b51

Elixir(やその基になる Erlang)の計算実行の単位をプロセスといいます。このプロセスはBEAMと呼ばれる仮想マシン上で実行されます。Elixirで作ったシステム全体は、プロセスがメッセージを交換しあう形で動作します。これをアクターモデルと言います。
ユーザがプロセスプログラミングするのに、ElixirではGenServerという枠組みを用意してます。GenServerは大量のサービスをサーバで並行実行するのや、IoTでデバイスを抽象化してAPIを作るのに向いています。
GenServerプロセスは実行中にいろんな面白い形でいぢることが可能です。例えば実行中に実装を差し替えることができます。またマイグレーションと言って、今動いているBEAMから他のBEAMに移動することもできます。これは他の言語ではあまりみられない特徴で、応用の局面でElixirを実用性の高い言語にしています。
今回はまずElixirのGenServer入門をします。つぎに実際に手元のPCでマイグレーションするところをご覧に入れます。またIoTデバイスを用いてLチカなどの動作を一つのボードコンピュータから他のボードに飛ばすところをお見せします。
ElixirはErlang Clusterという通信基盤がデフォルトで用意されています。この他に最近はPub/Sub通信をするZenohが使えるようになってます。Zenohを用いて広域分散環境でプロセスのマイグレーションするところもお見せします。

Avatar for kikuyuta

kikuyuta

July 12, 2026

More Decks by kikuyuta

Other Decks in Technology

Transcript

  1. Acknowledgement • NICT ◦ • Government of Kochi Prefecture, Japan

    ◦ • Budget: The commissioned research (No.04001) by the National Institute of Information and Communications Technology, Japan. Budget: Research promotion projects for industry creation through industry-academia-government collaboration (2020) Softbank ◦ 広域分散実行基盤の実現に寄与する通信技術に関する共同研究 ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 3
  2. Elixir はこんな風 defmodule Fib do def onacci(0), do: 0 def

    onacci(1), do: 1 def onacci(n) do onacci(n-2)+onacci(n-1) end end ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 iex(1)> Fib.onacci(0) 0 iex(2)> Fib.onacci(1) 1 iex(3)> Fib.onacci(6) 8 5
  3. パイプ使った例 defmodule Fib do def onacci(0), do: 0 def onacci(1),

    do: 1 def onacci(n) do onacci(n-2)+onacci(n-1) end def seq(n) do 0..n |> Enum.map(&onacci/1) |> Enum.each(&IO.puts/1) end end ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 iex(1)> Fib.seq(5) 0 1 1 2 3 5 :ok 6
  4. パイプでこんな風にも書ける defmodule Fib do def onacci(0), do: 0 def onacci(1),

    do: 1 def onacci(n) do onacci(n-2) |> Kernel.+(onacci(n-1)) end end ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 h(g(f(x))) を x |> f |> g |> h と書ける 7
  5. I/O 抽象化との親和性 • 全部 API プロセスでくるむ P1 アプリケーション ソフトウェア P2

    でも関数型で状態をどうあつかうの? ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 P3 10
  6. Erlang/OTP (1986〜, 1998〜) Ericsson のATM交換機に採用された (Wikipedia:en) • イミュータブルな変数 • パターンマッチ

    • アクターモデル • ◦ ◦ 軽量プロセスとメッセージパッシング スーパバイザ、プロセスツリー、Let it Crash Prolog ライクな文法 • BEAM VM ⇒ Elixir, Gleam • ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 11
  7. Elixir (2012〜) José Valim • Erlang ベースでもっとプログラミングを楽しく… • ◦ 文法:Prolog

    風 → Ruby 風 新機能:パイプ演算子、マクロ、Protocol、mix、hex… • プラットフォーム • ◦ ◦ ◦ Web開発用:Phoenix, Liveview IoT・組込み用:Nerves AI用:Nx, Axon, Bumblebee ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 12
  8. Elixir ならではなのは何? • たいがいの機能は他の言語でも実現できそう ◦ • 実際に実装するかどうかは別として… では Elixir がぶっ飛んでるのは…

    ◦ ◦ ◦ 並行プログラミング(これ自体は Erlang/OTP 由来) 特に GenServer によるプロセスプログラミング ▪ Erlang にもあるけど、Elixir のほうがいろいろと簡単 スーパバイザツリーと Let it Crash ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 13
  9. GenServer とは • Elixir/Erlang でプロセスを使うための標準ラ イブラリ (behaviour) • サーバ・クライアント型サービスを作成 •

    スーパバイザツリーによる監視・再起動 • 状態変数あり • • • • • 初期化・動作開始 クライアントとの同期通信動作 クライアントとの非同期通信動作 プロセスからのメッセージ 終了 start or start_link stop handle_call GenServer handle_cast terminate Process state handle_info message other (or self) process ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 init call cast
  10. GenServer で Stack を作る defmodule Stack do use GenServer def

    start_link(pname) do GenServer.start_link(__MODULE__, nil, name: pname) end def init(_arg) do {:ok, []} end def push(pname, ele) do GenServer.cast(pname, {:push, ele}) end def handle_cast({:push, ele}, state) do {:noreply, [ele, state]} end def pop(pname) do GenServer.call(pname, :pop) end def handle_call(:pop, _from, [ele|rest]) do {:reply, {:ok, ele}, rest} end end ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12
  11. Stack プロセスの動作 iex(1)> Stack.start_link(:afo) {:ok, #PID<0.147.0>} iex(2)> Stack.push(:afo, 0) :ok

    iex(3)> Stack.push(:afo, 1) :ok iex(4)> Stack.pop(:afo) {:ok, 1} iex(5)> Stack.start_link(:bar) {:ok, #PID<0.148.0>} iex(6)> Stack.push(:bar, "hello") :ok iex(7)> Stack.pop(:bar) {:ok, "hello"} iex(8)> Stack.pop(:afo) {:ok, [0, []]} ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 push pop #PID<0.147.0> [1, 0] Iex (REPL) :afo #PID<0.148.0> pop push [“hello”] :bar
  12. マイグレーションの考え方 計算エンティティA なるべく環境によらず通信可能に なにか事前準備をしておく なにか事前準備をしておく なにか計算する動作が始まる なるべく面倒くさくなく なるべく簡単に、速く、少なく … お仕事を続ける

    … 計算動作を止める 必要な情報を送り出す 渡せるものを多く 渡せないものを少なく ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 計算エンティティB 必要な情報を受け取る それに従って計算する動作を始める … お仕事を続ける … 26
  13. 何をマイグレートするか GenServer! • 物理サーバそのもの ◦ • 仮想マシン/仮想OS ◦ • サーバ本体やホストOSは動かさない

    ERTS (Erlang Run Time System) ◦ • どうしてもやるとおっしゃるなら止めませんが… 仮想マシンやゲストOSは動かさない Elixir/Erlang プロセス(アクター) ◦ ERTS は動かさない ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 27
  14. Erlang Cluster の制約 Node • Node.connect で簡単にクラスタリ ングできるのではあるものの… • 完全グラフを作るのでスケールす

    るか疑わしい • TCP/UDP/IP 通信が透過的でないと ならない Node Node Node Node Node ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 Node Node 29
  15. TCP/UDP/IP通信の透過性 • 典型的には NAPT がある ◦ ◦ IPv4アドレスの消費を押さえる グローバル側からの侵入を止める •

    CGN なんてのも導入されてる • 携帯網内がグローバル環境でない • TCP/UDP セッションをローカル からグローバル方向にしか張れな い ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 Router Router NAPT Node Node Node Node.connect() Node.connect() true false 30
  16. IP通信の透過性を実現する手法 常に使えるとは限らない • 状況を維持し続けるのが大変 • Router Router Router NAPT Node

    NAPT Node VPN Tunneling ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 Router Node Node NAPT hole punching 31
  17. Zenoh とは • Pub/Sub モデル ◦ ◦ ◦ • •

    Pub が発信したメッセージを Sub が受信 事前に共通の key (topic) を決めておく Zenoh: Pub/Sub、Queryable、Storage 非中央集権型 ◦ ◦ • https://zenoh.io/ 完全な分散型 MQTTのようなブローカが不要 key に構造を持たせられる ◦ UNIX ディレクトリ風 Open Source (Linux Foundation) ◦ https://github.com/eclipse-zenoh ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 33
  18. Zenohex: Elixir 用の API ライブラリ https://hex.pm/packages/zenohex • https://github.com/biyooon-ex/zenohex • Elixir

    App Zenohex Rustler Zenoh TCP/UDP IP ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 Go App Rust App Python App C App C++ App Zenoh TCP/UDP IP Zenoh TCP/UDP IP Zenoh TCP/UDP IP Zenoh TCP/UDP IP Zenoh TCP/UDP IP 34
  19. Zenoh で複雑さの軽減 Node Node Node Node Node Node Node Node

    Node Node Node Node Node ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 Node Node Node 35
  20. Zenoh を用いたGenServerプロセスのマイグレーション Zenoh での通信手段を持っている use GenServer use GenServer GenServer でプロセスを起動

    … プロセスがお仕事を続ける … プロセスを止める モジュールと状態を送り出す ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 モジュールと状態を受け取る モジュールをロードする GenServer でもらった状態でプロセス起動 … プロセスがお仕事を続ける … 36
  21. GenServer プロセスのマイグレーション (その1) Zenoh で通信できるものと仮定 use GenServer use GenServer start/3

    で GenServer 起動 :code.get_object_code/1 で module ゲット stop/3 で停止 terminate/3 の返り値 (reason, state) ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 :code.load_binary/3 で module をロード start/3 で state を初期値として起動 37
  22. GenServer プロセスのマイグレーション (その2) Zenoh で通信できることを仮定 use GenServer use GenServer :code.get_object_code/1

    to get module :code.load_binary/3 to load the module start/3 で GenServer プロセスを起動 start/3 で GenServer プロセスを起動 :sys.suspend/1 で直ちに停止しておく :sys.suspend/1 でサスペンドする :sys.get_state/2 で状態をゲット :sys.replace_state/2 で状態注入 :sys.resume/1 でプロセス再開 ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 38
  23. Subscribing the same key Subscriber Elixir ubuntu Subscriber Elixir ubuntu

    ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 Subscriber Elixir ubuntu Elixir Apps Publisher Elixir MacOS 43
  24. 参考文献・コード • Giocci についてより詳しくは… ◦ • ElixirConf Goatmire 2025 in

    Varberg, Sweden 小水力発電システムへの応用については… ◦ ◦ NervesConf EU 2025 in Varberg, Sweden CodeBeam America 2022 in Mountain View, US Giocci: https://github.com/biyooon-ex/giocci_platform • Zenohex: https://github.com/biyooon-ex/zenohex • ModBuzz: https://github.com/tombo-works/modbuzz • ◦ Yet another sophisticated MODBUS library on both TCP and RTU (RS485) ⾼知⼯科⼤学 菊池豊 関数型まつり 2026-07-12 47