ノード間の通信でNode.ping/1が便利だなと思ったのでメモ。
ただノードの接続を確認するだけではなく、未接続の場合には接続を確立してくれます。Livebookでも使用されています。
この記事も参考になりました。
Erlangの分散機能について
ポイントがいくつかあります。
ノードの名前
分散ノードを起動する方法は2つあります。
-
--sname
オプション- 短い名前
- 同一のホスト上にクラスターを設けるときに便利
-
--name
オプション- ノードの場所(例、IPアドレス)を含む完全修飾名
Erlangクッキー
- クラスターを識別するためのもの
- セキュリティ用ではない
- ノードを接続するためには同じErlangクッキーを共有する必要
epmd (Erlang Port Mapper Daemon)
- 登録されたノードのポートを追跡するプロセス
- 分散ノードでBEAMを起動するときに起動
- デフォルトではポート
4369
で動作 - ノードが他のノードへの接続が成功した時点でランダムなポートが割り当てられるらしい
epmd -names
コマンドですべてのノードのポートが確認できます。
$ epmd -names
epmd: up and running on port 4369 with data:
name piyo at port 63110
name fuga at port 63108
name hoge at port 63106
メッシュネットワーク
- 新しいノードがクラスタに加わると、メッシュネットワークが形成されます。
- クラスタの全てのノードは他の全てのノードに接続されます。
論よりRun
<
同一PC上でクラスタを作ってみる
シェルを複数起動
複数のシェルを起動します。
IExセッションからノードを起動
hoge
、fuga
、piyo
の三つのノードをそれぞれ別々のIExセッションで起動します。
--sname
オプションでノード名を指定します。
iex --sname hoge@localhost
iex --sname fuga@localhost
iex --sname piyo@localhost
Erlangクッキーを設定
ノードが接続する際に必要になります。あるクラスターに属するすべてのノードが同じクッキーを共有することになります。
Node.set_cookie(:mycookie)
ちなみにiexコマンドの--cookie
オプションまたは--erl
オプションを用いることにより、Erlangランタイムシステム起動時にクッキーを設定することも可能です。
iex --sname hoge --cookie mycookie
iex --sname hoge --erl "-setcookie mycookie"
Node.ping/1でノードを接続
hoge
ノードのIExから他のノードに接続します。
:pong = Node.ping(:"fuga@localhost")
:pong = Node.ping(:"piyo@localhost")
Node.ping/1は、成功した場合は :pong
、失敗した場合は:pang
を返します。
Node.list/0で現在接続されているノードのリストが確認できます。この時点で全てのノードが他の全てのノードに接続されているはずです。
別ノードでコードを実行
fuga
ノードのIExにToukon
モジュールを貼り付けて定義します。
defmodule Toukon do
def aisatsu, do: "元氣ですかーーーーッ!"
end
piyo
ノードのIExからfuga
ノードで定義されたToukon
モジュールを実行します。
Node.spawn(
:"fuga@localhost",
fn -> Toukon.aisatsu() |> IO.puts() end
)
Nodeモジュール
Nodeモジュールの関数はすべて、Erlangの実装に委譲されています。分散ノードに関連する関数を便宜上まとめたものと言えます。
Node.ping/1が便利なのでいまいちNode.connect/1の使い道がわかりません。LivebookではNode.ping/1でノードを接続しているので、深く考えずNode.ping/1でいいんじゃないかなと思ってます。
ご参考までに