hotch-potch, Note to self

いろいろ作業記録

Elixirでネットワーク越しのプロセス通信

1.はじめに

Elixirを使った2ホスト間の通信例です。 ホストで用意した関数を、ゲストから実行する2つの例です。

  • 例1
    • ゲストのiexから、直接ホストの関数を呼び出して結果を得る
  • 例2
    • ゲストのiexから、ホストのiexに入り込んで、ホストの関数を呼び出して結果を得る

試験環境

パソコン OS IP iexでつける名前
ホストA Ubuntu 22 192.168.9.5 kate
ゲストB Ubuntu 22 192.168.9.8 alex

2.準備

ホストA・受け側

$ cd 

#作業ディレクトリを用意
$ mkdir -p ~/gitwork/elixir

#テスト用スクリプトを作成
$ cd !$
$ nano kate.ex

ファイルkate.exの内容

defmodule Kate do
  def say_name(message \\ "Kate") do
    IO.puts "Hi, my name is #{inspect(message)}"
  end
end

iexを立ち上げる際に、下記オプションを加えると、iexごとにユニークな情報が付加されて、別のiex同士の通信が可能になります。

オプション 意味 フォーマット
--name iexに名前を付けます。異なるホストを繋げるときに使用 <名前>@IPアドレス
--sname 〃。同じホスト内のiexで通信するときに使用 <名前>
--cookie 別のiex同士で通信するときに同じトークン同士のiexで通信します <英数字>
# iexを引数付きで立ち上げ
$ iex --name kate@192.168.9.5 --cookie secret_token 
Erlang/OTP 24 [erts-12.3.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]

Interactive Elixir (1.13.4) - press Ctrl+C to exit (type h() ENTER for help)

# 先ほど作成したスクリプトを読み込み
iex(kate@192.168.9.5)1> c("kate.ex")
[Kate]

#現在のノードの接続状況
iex(kate@192.168.9.5)2> Node.list   
[]

この状態にしておきます。

ゲストB・送り側

$ cd 
$ mkdir -p ~/gitwork/elixir
$ cd !$
$ iex --name alex@192.168.9.8 --cookie secret_token
Erlang/OTP 24 [erts-12.1.5] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]

Interactive Elixir (1.13.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(alex@192.168.9.8)1>

この状態にしておきます。

3.通信例

例1:ゲストのiexから、ホストの関数を呼び出す

ホストAのsay_name/0関数を呼び出します。

ゲストB・送り側

先ほどの状態から、ホストAの操作を始めます。

#呼び出します。自動的にNode.connectされます
iex(alex@192.168.9.8)2> pid = Node.spawn_link(:"kate@192.168.9.5", fn -> Kate.say_name end)
#PID<11212.125.0>            
Hi, my name is "Kate"        

#引数を与えて呼び出します
iex(alex@192.168.9.8)3> pid = Node.spawn_link(:"kate@192.168.9.5", fn -> Kate.say_name("HOGE") end)
Hi, my name is "HOGE"        
#PID<11212.126.0>        

#現在のノードの接続状況を確認します
iex(alex@192.168.9.8)4> Node.list                                                                      
[:"kate@192.168.9.5"]    

#ノードを切ります
iex(alex@192.168.9.8)5> Node.disconnect(:"kate@192.168.9.5")                                       
true                     
    
#現在のノードの接続状況を確認します
iex(alex@192.168.9.8)6> Node.list                               
[]                           

例2:ゲストのiexから、ホストのiexに入り込んで、ホストの関数を呼び出す

iexのUser switch commandを使います。

#ここで [Ctrl-G] を入力
iex(alex@192.168.9.8)3> 

# コマンド入力に切り替わります。下記の順に入力
# r <接続先名> 'Elixir.IEx'
# c
User switch command
 --> r 'kate@192.168.9.5' 'Elixir.IEx'
 --> c

#接続先のiexに入ります。接続先の関数を実行できます
Interactive Elixir (1.13.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(kate@192.168.9.5)1> Kate.say_name
Hi, my name is "Kate"
:ok
iex(kate@192.168.9.5)2> Kate.say_name
say_name/0    say_name/1    
iex(kate@192.168.9.5)2> Kate.say_name("FUGA")
Hi, my name is "FUGA"
:ok

#ノードがつながっています
iex(kate@192.168.9.5)3> Node.list   
[:"alex@192.168.9.8"]

iex起動時に直接ホストに入る

先ほどはUser switch commandを使いましたが、iexのオプションを指定すると、直接ホストのiexに入れます。

オプション 意味
--remsh 接続先の名前を与えます <名前>@IPアドレス
tailway@dicom-sv9:~$ iex --name alex@192.168.9.8 --cookie secret_token --remsh kate@192.168.9.5
Erlang/OTP 24 [erts-12.1.5] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]

Interactive Elixir (1.13.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(kate@192.168.9.5)1> Kate.say_name
Hi, my name is "Kate"
:ok
iex(kate@192.168.9.5)2> Kate.say_name("FOO")
Hi, my name is "FOO"
:ok
iex(kate@192.168.9.5)3> tailway@dicom-sv9:~$ 

参考資料