LoginSignup
15
2

More than 1 year has passed since last update.

Elixirで気軽に分散ノード間で遠隔手続き呼出し(RPC)

Last updated at Posted at 2022-12-04

分散Erlang・Elixirノード間の通信する際に使える便利なrpcというErlangモジュールがあります。ネット調べてもあまり情報が出てきません。忘れないうちにメモしておきます。

rpcphoenix_live_dashboardで利用されています。

一般論としてのRPC

ウィキペディアによると、一般論としては

遠隔手続き呼出し(英: remote procedure call、リモートプロシージャコール、略してRPC)とは、プログラムから別のアドレス空間(通常、共有ネットワーク上の別のコンピュータ上)にあるサブルーチンや手続きを実行することを可能にする技術。

Erlangのrpcモジュール

ErlangのrpcモジュールはErlang・Elixirノード間限定で使用できるものであるようです。ですので、BEAM (Erlang virtual machine)が使えないシステムに対して遠隔手続き呼出ししたい場合は別途調査が必要と思われます。

ドキュメントの内容をざっくり要約すると

  • 遠隔手続き呼出しに似た機能
  • 遠隔ノードで情報を収集したり、 遠隔ノードで特定の副作用を伴う機能を実行したりするために使用される
  • :rpc.call/4やそれに似た関数では、成功した結果、発生した例外、およびその他のエラーを区別することが非常に困難
  • 互換性の理由により変更できないため、異なる結果を区別できるerpcモジュールがOTP 23から新しく導入された

ちなみにerl -manコマンドをOSのシェルに打ち込んでドキュメントを閲覧することもできます。

CMD
erl -man rpc

論よりRun

  • 二つのノードをそれぞれ別々のIExセッションで起動
  • 二つのノードを接続
  • :rpc.call/4関数を使い遠隔ノード内でコード実行

ノードを起動

IExセッションで起動時に以下のオプションを指定します。

  • --snameオプションで一意のノード名を指定
  • --cookieオプションに同じクッキー(クラスターの名前ようなもの)を指定

二つのノード(hogefuga)をそれぞれ別々のIExセッションで起動します。

CMD
iex --sname hoge@localhost --cookie mycookie
CMD
iex --sname fuga@localhost --cookie mycookie

ノードを起動.png

ノードを接続

ここではhogeノードのIExからfugaノードに接続します。逆でも構いません。

hogeノードのIEx
:pong = Node.ping(:"fuga@localhost")

Node.ping/1は、接続に成功した場合は :pong、失敗した場合は:pangを返します。

新しいノードがクラスタに加わると、メッシュネットワークが形成されます。クラスタの全てのノードは他の全てのノードに接続されます。

Node.list/0で現在接続されているノードのリストが確認できます。

ノードを接続.png

遠隔ノード内でコード実行

:rpc.call/4を用いて別ノード内でコードを実行します。Node.spawn/2と似ていますが、:rpc.call/4を使うと別ノード内で計算した結果を簡単に受信できます。

検証用に簡単な挨拶をする関数を定義します。この関数はノードを受け取り、挨拶の文字列を返します。

それぞれのノードのIExに貼り付ける
defmodule Person do
  @spec say_hello(Node.t()) :: String.t()
  def say_hello(other_node) do
    "Hello, #{node_name_string(other_node)}! My name is #{node_name_string(Node.self())}."
  end

  defp node_name_string(other_node) do
    node
    |> to_string()
    |> String.split("@")
    |> hd()
    |> String.capitalize()
  end
end

hogeノードのIExからfugaノードに挨拶させます。

hogeノードのIEx
:rpc.call(:"fuga@localhost", Person, :say_hello, [node()])

fugaノードのIExからhogeノードに挨拶させます。

fugaノードのIEx
:rpc.call(:"hoge@localhost", Person, :say_hello, [node()])

遠隔ノード内でコード実行.png

この技を使うといろんな情報を遠隔ノードから収集することができます。

phoenix_live_dashboard

phoenix_live_dashboardではシステムの情報を収集する目的で:rpc.call/4が利用されています。

ご参考までに

15
2
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
15
2