2015-02-11 70 views
0

我是Erlang的初学者。我想用它来观察“教科书”分布式算法(领导选举,共识......)的教学目的的执行情况。在那个阶段,我将我的系统的拓扑描述为一个图(int从int到int列表),并基于此,我创建并初始化其邻居列表。它工作正常,但它似乎有点特设。必须有更通用的方法来做到这一点。常见的库或工具可以帮助吗?erlang中的分布式算法模拟

如果不是,你认为我在做什么有意义吗?见下文。

-module(control). 
-export([init/1, init/4]). 

% create N processes 1 .. N and return a dict from 
% 1..N to Pids 
create(_, 0, Dict) -> Dict ; 
create(Module, N, Dict) -> 
    Id = spawn(Module, proc, [nil]), 
    Id ! init_state, 
    create(Module, N-1, dict:append(N, Id, Dict)). 

% broadcast a Signal to all processes in Dict 
broadcast(Dict, Signal) -> 
    F = fun (_, [Y]) -> Y ! Signal end, 
    dict : map (F, Dict), 
    ok. 

% send a Signal to process Dict(I) 
send(Dict, I, Signal) -> 
    [Id] = dict : fetch(I, Dict), 
    Id ! Signal, 
    ok. 

% wait for N ok signals 
syncr(0) -> ok; 
syncr(N) -> 
    receive 
    ok -> io : format("ok received ~n", []), syncr(N-1) 
    end. 

% init neighbors according to topology Graph 
init_topology(Dict, Graph) -> 
    F = fun(X) -> [Res] = dict : fetch(X, Dict), Res end, 
    IdToPId = fun(L) -> lists : map(F, L) end, 
    G = fun (I, [Y]) -> 
     [LId] = dict : fetch(I, Graph), 
     LPId = IdToPId(LId), 
     Y ! {neighbors, LPId, self()} end, 
    dict : map (G, Dict), 
    ok. 

% init all states with unary function Signal : I -> term. 
init_state(Dict, Signal) -> 
    F = fun (I, [Y]) -> Y ! {init, Signal(I), self()} end, 
    dict : map (F, Dict), 
    ok. 

% init all process according to the given topology and Signal : I -> term 
% returns a pair of function Send and Broadcast 
init(Module, N, Graph, Signal) -> 
    Dict = create(Module, N, dict:new()), 
    init_topology(Dict, Graph), 
    init_state(Dict, Signal), 
    syncr(2 * N), 
    Send = fun (I, S) -> send(Dict, I, S) end, 
    Broadcast = fun (S) -> broadcast(Dict, S) end, 
    { Send, Broadcast }. 

% this is a particular instanciation of a consensus algorithm with 
% N nodes 
% a complete graph topology 
% some initialisation of the process states 
% the S and B returned functions allows me to interact with the system 
% to start the algorithm for instance 
init(N) -> {S, B} = control : init(consensus, N, topology : complete(N), fun(_) 
     -> random : uniform(1000) end), {S,B}. 

回答

1

OTP有一些处理上述任务的方式。我说“死记硬背”而不是“通用”,因为它们是OTP惯例,而不是普遍接受的通用分布式算法实现解决方案。

诸如初始化进程图,发送消息,终止消息,同步信令等等是OTP在概念中提供解决方案的一类事物。维护进程注册表可以由global模块,gproc等实用程序或使用进程组来处理 - 但是您处理进程组的方式似乎更可能是PID列表比进程注册表更适合,或者甚至你当前的进程字典(分配给给定进程的整数标签是毫无意义的,并且你不太可能需要将消息发送到特定的进程N,而没有它自己启动了消息链,在这种情况下,你可以知道它的PID) 。

在任何情况下,启动过程图的OTP方式在尝试解决真实的现实问题而非理论问题时最有用。在理论系统中没有任何失败,代码是完美的,并且没有用户 - 你正在建模一个理想的案例。在现实世界中,事情破裂,需要监控,错误比比皆是,人们通过电线和网络电缆绊倒,日常生活中常见的情况一般都是一团糟。这种现实世界的混乱性实际上是OTP旨在帮助解决的问题,它只是偶然地以一种方式提供了一种将程序声明为过程图的方式 - 这是偶然的事实是为什么“演员模型”的语言和分布式计算理论在Erlang/OTP文档中并没有太多用处。

启动系统的OTP方式的一个副作用是,监测,监督和其他一些实际有用的(如,“在生产环境中非常有用,用户所依赖的系统是可用的”)的事情application给你“只是发生“而不需要添加一堆用于监控,调试或临时监管策略的代码。但这些可能不是你真正关心的事情。

Something OTP does not provide是通用集合的一致性算法实现。在大多数实际的系统中(这也是Erlang真正关注的重点)做出了一个决定,即将共识的复杂性降到最低,并依靠任意条件强制遵守领导模型,即使这是暂时的破坏性。因此,一方面“是”,Erlang/OTP提供了强大的方法来处理上面编写的大部分代码,但另一方面“否”,Erlang/OTP没有设计任何特定的理论模型考虑到分布式计算,因此其编程文化及其框架已作出有意识的决定,将更高的优先级放在提供生产环境中快速部署强健系统的捷径上,并且实施或遵守理论基础的优先级较低,因此某些功能你可能会期望可能会失踪。

+0

Erlang社区的“实用性第一”思维模式的一个很好的例子在这个关于分布式进程注册表环境中的容错的ML线程中进行了说明:http://erlang.org/pipermail/erlang-questions/ 2015年,2月/ 083194.html – zxq9 2015-02-11 22:19:43