10章あたり
分散プログラムとは、ネットワークを構成するコンピュータで動作するように設計されたプログラムのこと。
Erlangの分散プログラムは、信頼できる動作環境でどのErlangノードでも他のノードに対して
メッセージパッシングだけを使ってお互いの動作の調和をとることができる
Erlangノードを起動して遠隔Erlangノードで遠隔手続き呼び出して実行するため
以下の手順を順番に追いながら簡単な名前サーバを作る。
- ステージ1:分散していない通常のErlang システムで名前サーバを書いてテストする。
- ステージ2:1 つのマシンにある2 つのノードで名前サーバをテストする。
- ステージ3:1 つのローカルエリアネットワークにある2 台の異なるマシンの2 つの異なるノードで名前サーバをテストする。
- ステージ4:2 つの異なる国の2つの異なるドメインに属する2台の異なるマシンで名前サーバをテストする。
・kvs.erl
-module(kvs).
-export([start/0, store/2, lookup/1]).
start() -> register(kvs, spawn(fun() -> loop() end)).
store(Key, Value) -> rpc({store, Key, Value}).
lookup(Key) -> rpc({lookup, Key}).
rpc(Q) ->
kvs ! {self(), Q},
receive
{kvs, Reply} -> Reply
end.
loop() ->
receive
{From, {store, Key, Value}} ->
put(Key, {ok, Value}),
From ! {kvs, true},
loop();
{From, {lookup, Key}} ->
From ! {kvs, get(Key)},
loop()
end.
・Eshell
1> c(kvs).
{ok,kvs}
2> kvs:start().
true
3> kvs:store({location, joe}, "Stookholm").
true
4> kvs:store(weather, raining).
true
5> kvs:lookup(weather).
{ok,raining}
6> kvs:lookup({location, joe}).
{ok,"Stookholm"}
7> kvs:lookup({location, jane}).
undefined
ステージ1で作ったプログラムを2つのEshellで別々のErlangノードとして起動して確認する。
rpc:call
はErlangの標準ライブラリモジュールで以前に書いたrpc関数でない。
・Eshell Server
$ erl -sname server
(server@fujimisakaris-MacBook-Air)1> kvs:start().
true
・Eshell Client
$ erl -sname client
(client@fujimisakaris-MacBook-Air)1> rpc:call('server@fujimisakaris-MacBook-Air',
(client@fujimisakaris-MacBook-Air)1> kvs, store, [weather, fine]).
true
(client@fujimisakaris-MacBook-Air)2> rpc:call('server@fujimisakaris-MacBook-Air',
(client@fujimisakaris-MacBook-Air)2> kvs, lookup, [weather]).
{ok,fine}
dockerにて検証環境を構築(同一LANに別マシンのErlangノードの用意)。
・Server Host
$ docker run -it -v /path/to/erlang_socket_dist:/usr/src/app --name server erlang:latest /bin/bash
root@3c550c1df592:/# cd /usr/src/app
root@3c550c1df592:/usr/src/app# erl -name server@172.17.0.2 -setcookie abc
Erlang/OTP 19 [erts-8.3.1] [source] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V8.3.1 (abort with ^G)
(server@172.17.0.2)1> kvs:start().
true
・Client Host
$ docker run -it -v /path/to/erlang_socket_dist:/usr/src/app --name client erlang:latest /bin/bash
root@351e440c3070:/# cd /usr/src/app
root@351e440c3070:/usr/src/app# erl -name client@172.17.0.3 -setcookie abc
Erlang/OTP 19 [erts-8.3.1] [source] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V8.3.1 (abort with ^G)
# pingで疎通確認
(client@172.17.0.3)1> net_adm:ping('server@172.17.0.2').
pong
(client@172.17.0.3)2> rpc:call('server@172.17.0.2',
(client@172.17.0.3)2> kvs, store, [weather,cold]).
true
(client@172.17.0.3)3> rpc:call('server@172.17.0.2',
(client@172.17.0.3)3> kvs, lookup, [weather]).
{ok,cold}
検証環境がなかったので確認できずorz
2つの分散Erlangノードが通信するには、双方が同じマジッククッキーを持っていなければならない。
クッキーは以下の3 種類の方法で設定できる
このファイルにはランダムな文字列が入っていて、
Erlangをそのマシンで初めて実行したときに自動的に作られる。
分散Erlang セッションに参加するすべてのマシンにこのファイルをコピーすればよい。
もしくは、値を明示的に設定することもできる。
例えば、Linux システムの場合、次のようなコマンドを実行する:
$ cd
$ cat > .erlang.cookie
AFRTY12ESS3412735ASDF12378
$ chmod 400 .erlang.cookie
このフラグはマジッククッキーにC を設定する。
例えば:
$ erl -setcookie AFRTY12ESS3412735ASDF12378 ...
BIFのerlang:set_cookie(node(), C)
を使って、ローカルノードのクッキーにアトムCを設定する。