Eit*_*tan 5 erlang distributed-computing hotswap
我的情况如下-我有一个带有函数foo()的客户端C,它执行一些计算。
我希望不知道foo()的服务器S执行此功能,然后将结果发送回客户端。
我正在尝试确定在Erlang中执行此操作的最佳方法。我正在考虑:
我还没有想到其他方法(或语言的功能)吗?
谢谢您的帮助!
如果计算功能是自包含的,即不依赖于客户端C上的任何其他模块或功能,那么您需要做的是fun(功能对象)。Afun可以通过网络发送并由远程计算机应用,并且在 中fun,发送者嵌入了他们的地址和获取答案的方法。因此,执行者可能只会看到fun他们可能会或可能不会给出参数的一个,但在乐趣中,发送者强制采用了一种方法,其中答案将自动发回。它fun是一个事物中许多任务的抽象,它可以作为参数移动。
在客户端,您可以使用如下代码:
%% 客户端中的某处
%% 客户端在 node() == 'client@domain.com' 上运行
-模块(客户端)。
-编译(导出全部)。
-define(SERVER,{server,'server@domain.com'})。
Give_a_server_a_job(Number)-> ?服务器!{build_fun(),数字}。
build_fun()->
FunObject = fun(参数)->
答案 = Param * 20/1000, %% 计算在这里
rpc:call('client@domain.com',client,answer_ready,[答案])
结尾,
有趣的对象。
answer_ready(答案)->
%%% 使用 Answer 来处理各种有趣的事情......
io:format("\n\t答案在这里:~p~n",[答案])。
然后服务器有这样的代码:
%%% 服务器上的某处
%%% 服务器在 node() == 'server@domain.com' 上运行
-模块(服务器)。
-编译(导出全部)。
开始()->注册(服务器,生成(?模块,循环,[]))。
循环()->
收到
{有趣,Arg} ->
Fun(Arg), %% 服务器执行作业
%% 作业自动发回应答
%% 给客户
环形();
停止->退出(正常);
_ -> 循环()
结尾。
这样,作业执行者不需要知道如何发回回复,作业本身就知道它将如何发回答案给发送的作业!。我在几个项目中使用过这种通过网络发送功能对象的方法,它太酷了!
#### 编辑######
如果您有递归问题,您可以使用funs. 但是,您在客户端和/或服务器上至少需要一个库函数来协助递归操作。创建一个函数,该函数应位于客户端和服务器的代码路径中。
另一种选择是动态地将代码从服务器发送到客户端,然后使用该库:Dynamic Compile erlang从客户端在服务器上加载并执行 erlang 代码。使用动态编译,下面是一个例子:
1> String = "-module(add).\n -export([add/2]).\n add(A,B) -> A + B.\n"。
"-module(add).\n -export([add/2]).\n add(A,B) -> A + B。\n"
2> 动态编译:从字符串加载(字符串)。
{模块,添加}
3> 添加:添加(2,5)。
7
4>
我们上面看到的是一段从字符串动态编译和加载的模块代码。如果启用此功能的库在服务器和客户端上可用,则每个实体都可以将代码作为字符串发送,并在另一个实体上动态加载和执行。此代码使用后可以卸载。让我们看看斐波那契函数以及如何在服务器上发送和执行它:
%% 这是我们要转换为字符串的普通斐波那契代码: -模块(fib)。 -导出([fib/1])。 fib(N) 当 N == 0 -> 0 时; fib(N) 当 (N < 3) 且 (N > 0) -> 1 时; fib(N) 当 N > 0 -> fib(N-1) + fib(N-2) 时。 %% 在字符串格式中,现在将成为这段代码 StringCode = " -module(fib).\n -export([fib/1]). \nfib(N) 当 N == 0 -> 0;\n fib(N) 当 (N < 3) 和 (N > 0) -> 1;\n fib(N) 当 N > 0 -> fib(N-1) + fib(N-2) 时。\n"。 %% 然后客户端会将上面的这个字符串发送到服务器,服务器将
%% 动态加载代码并执行它
send_fib_code(Arg)-> {服务器注册名称,服务器节点}!{字符串,StringCode,fib,Arg}, 好的。 get_answer({fib,of,这,是,那}) -> io:format("~p 的斐波那契(来自服务器)是:~p~n",[This,That]). %%% 在服务器上 循环(服务器状态)-> 收到 {string,StringCode,Fib,Arg} 当 Fib == fib -> 尝试dynamic_compile:load_from_string(StringCode) 的 {模块,AnyMod} -> 答案 = AnyMod:fib(Arg), %%% 将答案发送回客户端 %%% 应该是异步的 %%% 因为渠道不同&不做 %% 客户端等待 rpc:call('client@domain.com',client,get_answer,[{fib,of,Arg,is,Answer}]) 抓住 _:_ -> error_logger:error_report(["无法从客户端动态编译和加载模块"]) 结尾, 循环(服务器状态); _ -> 循环(服务器状态) 结尾。
那段粗略的代码可以告诉你我想说的是什么。但是,请记住卸载所有不可用的动态模块。您还可以采用一种方法,让服务器在再次加载之前尝试检查此类模块是否已加载。我建议您不要复制并粘贴上面的代码。查看并理解它,然后编写可以完成这项工作的您自己的版本。
成功 !!!