riak_coreを使ってみる その1¶
riak はBasho社が作成している分散データベース です。実はRiakはriak_coreという分散処理を行う機能と、riakというデータベー ス機能(Riak K/V)とに分かれています。
そして、riak_coreは汎用的なフレームワークになっており、riakというデータ ベース以外の用途にも使えるようになっています。
今回は、途中までではありますが、触ってみたところを書きます。
riak_coreが提供する機能¶
http://www.slideshare.net/argv0/riak-coredevnation 参照
Virtual Node
Preference Lists
Ring Event Watcher
Node Event Watcher
参考文献¶
- 最初に読む場所
- サンプルアプリケーション
http://docs.basho.com/riak/1.4.0/references/appendices/community/Sample-Applications/
- 37ページからBuilding an Application on Riak Core
- riak_core 入門 by kuenishiせんせい
https://github.com/kuenishi/riak_scr_jp/blob/master/%234/ss-riak-core-intro.rst
- riak_core モジュールドキュメント
サンプルコード¶
- try-try-try サンプルコード
- howl
古いものなのですが、そのまま通用するのがすごいところ。
作ってみる¶
riak_coreを使ったアプリケーションを作成するにはまず https://github.com/basho/rebar_riak_core を使ってテンプレートを作成します。 (rebarは事前に入れておいてください)
% git clone git://github.com/basho/rebar_riak_core.git
% mkdir -p ~/.rebar/templates
% cp rebar_riak_core/* ~/.rebar/templates
% mkdir <プロジェクト名>
% cd <プロジェクト名>
% rebar create template=riak_core appid=<プロジェクト名>
これでテンプレートの出来上がりです。以下のようなファイル構造が出来上が ります。src以下は重要なので中身も書いてみました。
今回は、プロジェクト名をdpingにしたので、そのつもりで読んでください。
apps/
Makefile
README.md
rebar
rebar.config
rel/
src/
├── dping_app.erl
├── dping.app.src
├── dping_console.erl
├── dping.erl
├── dping.hrl
├── dping_node_event_handler.erl
├── dping_ring_event_handler.erl
├── dping_sup.erl
├── dping_vnode.erl
└── dping_wm_ping.erl
そのあとは、以下のようにすれば動きます。
% make rel
% ./rel/dping/bin/dping console
14:13:42.486 [info] Waiting for application dping to start (0 seconds).
14:13:42.489 [info] Application dping started on node 'dping@127.0.0.1'
Eshell V5.9.1 (abort with ^G)
(dping@127.0.0.1)1> 14:13:42.588 [info] Wait complete for
application dping (0 seconds)
(dping@127.0.0.1)2> dping:ping().
{pong,959110449498405040071168171470060731649205731328}
consoleでdping:ping()を実行して、というのが出れば成功です。 q() で終わります。
これは単一ノードだけですが、devrelを使うと4つのノードを作ってくれます。
% make devrel
mkdir -p dev
rel/gen_dev dev1 rel/vars/dev_vars.config.src
rel/vars/dev1_vars.config
Generating dev1 - node='dping1@127.0.0.1' http=10018 handoff=10019
(cd rel && ../rebar generate target_dir=../dev/dev1
overlay_vars=vars/dev1_vars.config)
==> rel (generate)
mkdir -p dev
rel/gen_dev dev2 rel/vars/dev_vars.config.src
rel/vars/dev2_vars.config
Generating dev2 - node='dping2@127.0.0.1' http=10028 handoff=10029
(cd rel && ../rebar generate target_dir=../dev/dev2
overlay_vars=vars/dev2_vars.config)
==> rel (generate)
mkdir -p dev
rel/gen_dev dev3 rel/vars/dev_vars.config.src
rel/vars/dev3_vars.config
Generating dev3 - node='dping3@127.0.0.1' http=10038 handoff=10039
(cd rel && ../rebar generate target_dir=../dev/dev3
overlay_vars=vars/dev3_vars.config)
==> rel (generate)
mkdir -p dev
rel/gen_dev dev4 rel/vars/dev_vars.config.src
rel/vars/dev4_vars.config
Generating dev4 - node='dping4@127.0.0.1' http=10048 handoff=10049
(cd rel && ../rebar generate target_dir=../dev/dev4
overlay_vars=vars/dev4_vars.config)
==> rel (generate)
こうしておいて、
以下のようにしてstartとjoinをします。
shirou@rudi:~/Works/dping$ for d in dev/dev*; do $d/bin/dping start;
done
shirou@rudi:~/Works/dping$ dev/dev3/bin/dping-admin join dping1@127.0.0.1
Sent join request to dping1@127.0.0.1
shirou@rudi:~/Works/dping$ for d in dev/dev*; do $d/bin/dping stop;
done
書いてみる¶
rebarで作成された中のdping_vnode.erlをみてみると、こんな感じの行があります。 これらを埋めていけばいいわけですね。
%% Sample command: respond to a ping
handle_command(ping, _Sender, State) ->
{reply, {pong, State#state.partition}, State};
handle_command(Message, _Sender, State) ->
?PRINT({unhandled_command, Message}),
{noreply, State}.
handle_handoff_command(_Message, _Sender, State) ->
{noreply, State}.
handoff_starting(_TargetNode, State) ->
{true, State}.
handoff_cancelled(State) ->
{ok, State}.
handoff_finished(_TargetNode, State) ->
{ok, State}.
handle_handoff_data(_Data, State) ->
{reply, ok, State}.
encode_handoff_item(_ObjectName, _ObjectValue) ->
<<>>.
is_empty(State) ->
{true, State}.
delete(State) ->
{ok, State}.
handle_coverage(_Req, _KeySpaces, _Sender, State) ->
{stop, not_implemented, State}.
handle_exit(_Pid, _Reason, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
nodeの追加/更新が起きた場合にnodeのリストを取る場合には dping_ring_event_handler.erl にこう書きます。
handle_event({ring_update, _Ring}, State) ->
Members = riak_core_ring:active_members(_Ring),
io:format("ring update ~p~n",[Members]),
{ok, State}.
こうしておいて、joinすると、attachしておいた端末にこう表示されます。
(dping1@127.0.0.1)1> 14:40:46.977 [info] 'dping3@127.0.0.1' joined cluster with status 'valid'
ring update ['dping1@127.0.0.1','dping3@127.0.0.1']
ring update ['dping1@127.0.0.1','dping3@127.0.0.1']
ring update ['dping1@127.0.0.1','dping3@127.0.0.1']
出てきた疑問点¶
なんでring updateが複数回呼ばれるの?
joined cluster with ... と書かれている部分はgosip部分で、それはAPI としては呼べない、のかな?
handoff_staringが何度も呼ばれる
なのに、handof_finishedが呼ばれてない。
うーん。もう少し挙動を調べる必要がある様子。
まとめ¶
riak_coreという分散処理のフレームワークがある
rebarでテンプレートを作成できる
テンプレートで作成された関数を埋めていけばいい
まだまだ理解不足ですが、一旦ここまで。
続きます。次はコマンドの作成です。
Comments
comments powered by Disqus