Skip to content

Instantly share code, notes, and snippets.

@t3t5u
Created May 12, 2015 15:49
Show Gist options
  • Save t3t5u/3ebcee9ee1a29d3074ad to your computer and use it in GitHub Desktop.
Save t3t5u/3ebcee9ee1a29d3074ad to your computer and use it in GitHub Desktop.
プロセス管理について

名前でプロセスを管理するモジュール

代表的な実装

名前 スコープ
BIF ローカル
global グローバル
gproc ローカル/グローバル

基本的なI/F

名前 登録 登録解除 検索
BIF register(Name::atom(), pid()) unregister(Name::atom()) whereis(Name::atom())
global register_name(Name::term(), pid()) unregister_name(Name::term()) whereis_name(Name::term())
gproc reg(Key::{n, l | g, term()})*1 unreg(Key::{n, l | g, term()})*1 lookup_pid(Key::{n, l | g, term()})

プロセスのグループを管理するモジュール

代表的な実装

名前 スコープ
pg2 グローバル
gproc ローカル/グローバル
riak_pg グローバル

基本的なI/F

名前 作成 削除 参加 離脱 一覧
pg2 create(Name::term()) delete(Name::term()) join(Name::term(), pid()) leave(Name::term(), pid()) get_members(Name::term())
gproc 明示的な作成はない 明示的な削除はない reg(Key::{p, l | g, term()})*1 unreg(Key::{p, l | g, term()})*1 lookup_pids(Key::{p, l | g, term()})
riak_pg create(Name::term()) delete(Name::term()) join(Name::term(), pid()) leave(Name::term(), pid()) members(Name::term())

各モジュールの実行例

pg2の実行例

1> net_kernel:start([node1, shortnames]).
{ok,<0.35.0>}
(node1@localhost)2> net_kernel:connect_node(node2@localhost).
true
(node1@localhost)3> net_kernel:connect_node(node3@localhost).
true
(node1@localhost)4> nodes().
[node2@localhost,node3@localhost]
(node1@localhost)5> pg2:create(group).
ok
(node1@localhost)6> pg2:get_members(group).
[]
(node1@localhost)7> pg2:join(group, self()).
ok
(node1@localhost)8> pg2:get_members(group).
[<0.33.0>]
(node1@localhost)9> pg2:get_members(group).
[<0.33.0>,<7243.33.0>,<7281.33.0>]
(node1@localhost)10> pg2:leave(group, self()).
ok
(node1@localhost)11> pg2:get_members(group).
[<7243.33.0>,<7281.33.0>]
(node1@localhost)12> pg2:get_members(group).
[]
1> net_kernel:start([node2, shortnames]).
{ok,<0.35.0>}
(node2@localhost)2> nodes().
[node1@localhost,node3@localhost]
(node2@localhost)3> pg2:get_members(group).
{error,{no_such_group,group}}
(node2@localhost)4> pg2:join(group, self()).
ok
(node2@localhost)5> pg2:get_members(group).
[<7280.33.0>,<0.33.0>]
(node2@localhost)6> pg2:leave(group, self()).
ok
(node2@localhost)7> pg2:get_members(group).
[<7281.33.0>]
(node2@localhost)8> pg2:get_members(group).
[]
1> net_kernel:start([node3, shortnames]).
{ok,<0.35.0>}
(node3@localhost)2> nodes().
[node1@localhost,node2@localhost]
(node3@localhost)3> pg2:get_members(group).
{error,{no_such_group,group}}
(node3@localhost)4> pg2:join(group, self()).
ok
(node3@localhost)5> pg2:get_members(group).
[<7280.33.0>,<7281.33.0>,<0.33.0>]
(node3@localhost)6> pg2:leave(group, self()).
ok
(node3@localhost)7> pg2:get_members(group).
[]
(node3@localhost)8> pg2:get_members(group).
[]

gprocの実行例

1> net_kernel:start([node1, shortnames]).
{ok,<0.35.0>}
(node1@localhost)2> net_kernel:connect_node(node2@localhost).
true
(node1@localhost)3> net_kernel:connect_node(node3@localhost).
true
(node1@localhost)4> nodes().
[node2@localhost,node3@localhost]
(node1@localhost)5> application:ensure_all_started(gproc).
{ok,[gproc]}
(node1@localhost)6> gproc_dist:start_link(all).
{ok,<0.62.0>}
(node1@localhost)7> gproc:lookup_pids({p, g, group}).
[]
(node1@localhost)8> gproc:reg({p, g, group}).
true
(node1@localhost)9> gproc:lookup_pids({p, g, group}).
[<0.33.0>]
(node1@localhost)10> gproc:lookup_pids({p, g, group}).
[<0.33.0>,<7243.33.0>,<7281.33.0>]
(node1@localhost)11> gproc:unreg({p, g, group}).
true
(node1@localhost)12> gproc:lookup_pids({p, g, group}).
[<7243.33.0>,<7281.33.0>]
(node1@localhost)13> gproc:lookup_pids({p, g, group}).
[]
1> net_kernel:start([node2, shortnames]).
{ok,<0.35.0>}
(node2@localhost)2> nodes().
[node1@localhost,node3@localhost]
(node2@localhost)3> application:ensure_all_started(gproc).
{ok,[gproc]}
(node2@localhost)4> gproc_dist:start_link(all).
{ok,<0.62.0>}
(node2@localhost)5> gproc:reg({p, g, group}).
true
(node2@localhost)6> gproc:lookup_pids({p, g, group}).
[<7280.33.0>,<0.33.0>]
(node2@localhost)7> gproc:lookup_pids({p, g, group}).
[<7280.33.0>,<0.33.0>,<7281.33.0>]
(node2@localhost)8> gproc:unreg({p, g, group}).
true
(node2@localhost)9> gproc:lookup_pids({p, g, group}).
[<7280.33.0>,<0.33.0>,<7281.33.0>]
(node2@localhost)10> gproc:lookup_pids({p, g, group}).
[<7280.33.0>,<0.33.0>,<7281.33.0>]
1> net_kernel:start([node3, shortnames]).
{ok,<0.35.0>}
(node3@localhost)2> nodes().
[node1@localhost,node2@localhost]
(node3@localhost)3> application:ensure_all_started(gproc).
{ok,[gproc]}
(node3@localhost)4> gproc_dist:start_link(all).
{ok,<0.62.0>}
(node3@localhost)5> gproc:reg({p, g, group}).
true
(node3@localhost)6> gproc:lookup_pids({p, g, group}).
[<7280.33.0>,<7281.33.0>,<0.33.0>]
(node3@localhost)7> gproc:lookup_pids({p, g, group}).
[<7280.33.0>,<7281.33.0>,<0.33.0>]
(node3@localhost)8> gproc:unreg({p, g, group}).
true
(node3@localhost)9> gproc:lookup_pids({p, g, group}).
[<7280.33.0>,<7281.33.0>,<0.33.0>]
(node3@localhost)10> gproc:lookup_pids({p, g, group}).
[<7280.33.0>,<7281.33.0>,<0.33.0>]

riak_pgの実行例

{error,{riak_core,{{shutdown,{failed_to_start_child,riak_core_ring_manager,
                                                    {bad_return_value,{error,enoent}}}},
                   {riak_core_app,start,[normal,[]]}}}}

従来のモジュールの問題点

pg2の問題点

同じグループに複数回、参加できてしまう。

A process can join a group several times;

グループの状態を更新するときに、グローバルなロックが掛かる。

gprocの問題点

動的なグループの状態の更新において、gen_leaderの実装に起因するネットスプリットの問題がある。

riak_pgとは

特徴

  • 従来のモジュールの問題点を解消することを目標としている。
  • まだWork in progress, not for production use.な状態。
  • 内部的にriak_dtriak_coreを利用している。
  • 全面的にgen_fsmを利用している。

ソースコード

参考資料

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment