Erlang-分布式基础

2011-05-31 创建
2014-09-29 更新

知识点

  • 具有相同cookie而且彼此互相连接的节点集称为Erlang 集群
  • 设置Cookie的三种方式
    • $HOME/.erlang.cookie
    • erl -setcookie AFRTY12ESS3412735ASDF12378
    • erlang:set_cookie(node(),C)

Example

1
-module(kvs).
%% Include files
%% Exported Functions
-export([start/0, store/2, lookup/1]).
%% API Functions
start() ->
    io:format("starting server...~n"),
    % 启动kvs服务,派生一个新进程,进入循环
    register(kvs, spawn(fun()-> loop() end)).
store(Key, Value) ->
    io:format("store~n"),
    rpc({store, Key, Value}).
lookup(Key) ->
    io:format("call lookup~n"),
    rpc({lookup, Key}).
% Local Functions
% 消息代理函数
rpc(Q) ->
    io:format("rpc~n"),
    % 向进程kvs发送消息 {self(), Q},其中self()表示当前进程Pid, Q为参数
    kvs ! {self(), Q},
    receive
        {kvs, Reply} ->
            Reply
    end.
loop() ->
    io:format("entering loop...~n"),
    receive
        {From, {store, Key, Value}} ->
            io:format("value ~p with ~p stored~n", [Value, Key]),
            put(Key, {ok,Value}),
            From ! {kvs, true},
            loop();
        {From, {lookup, Key}} ->
            io:format("get the value of key: ~p~n", [Key]),
            From ! {kvs, get(Key)},
            loop()
    end

操作步骤

  • 启动两个终端, 分别输入
1
erl -sname server
erl -sname client
  • 在真实的分布式环境中,请使用
1
erl -name server
erl -name client

-name需要使用到DNS服务,而-sname不需要使用DNS,可用于本机测试,局域网也可以使用-sname启动Erlang系统.

启动服务器, 派生一个新进程,立即进入循环

1
(server@localhost) > kvs:start().
starting server...
entering loop...
true
  • 客户端通过RPC调用服务器函数 store 存储一个值
1
(client@localhost) > rpc:call('server@localhost',kvs,store,[google, "http://www.google.com"]).
  • 服务器输出,再次进入loop等待下一个消息:
1
(server@localhost) > value "http://www.google.com" with google stored
(server@localhost) > loop
  • 客户端查询
1
(client@localhost) > rpc:call('server@localhost',kvs,lookup,[google]).
call lookup
rpc
{ok,"http://www.google.com"}
  • 服务器输出
1
(server@localhost) > get the value of key: google
(server@localhost) > loop
  • 本地调用实际上也是通过rpc向kvs服务器发送消息
1
(server@localhost)2> kvs:lookup(google).
call lookup
rpc
get the value of key: google
loop
{ok,"http://www.google.com"}

消息传递图示

消息传递图示

结语

  • 本文使用进程字典作为Key,Value存储仅作为示例,真实环境中是不可能的.切忌照搬.
  • 可以把loop()函数中的put和get剥离到两个实现函数中
  • 采用什么后端存储就是你的事情了.