gpt4 book ai didi

Erlang:将客户端进程/功能卸载到服务器?

转载 作者:行者123 更新时间:2023-12-04 19:17:16 25 4
gpt4 key购买 nike

我的情况如下 -
我有一个带有函数 foo() 的客户端 C,它执行一些计算。

我想要一个不知道 foo() 的服务器 S 来执行这个函数,并将结果发送回客户端。

我正在尝试确定在 Erlang 中执行此操作的最佳方式。我正在考虑:

  • 热代码交换 - 即“升级” S 中的代码,使其具有函数 foo()。执行并发送回客户端。
  • 在节点都适当注册的分布式方式中,按照 做一些事情。 ! C:foo() - 用于将函数“发送”到进程/节点 S

  • 有没有我没有想到的其他方法(或语言的特征)?

    谢谢您的帮助!

    最佳答案

    如果计算函数是自包含的,即不依赖于客户端 C 上的任何其他模块或函数,那么您需要做的是 fun (功能对象)。 fun 可以通过网络发送并由远程机器和在 fun 中应用,发件人已经嵌入了他们的地址和获取答案的方法。所以执行者可能只看到一个 fun 他们可能会或可能不会提出论点,但在乐趣中,发件人强制使用了一种方法,通过该方法,答案将自动发回。 fun 是一个事物中很多任务的抽象,它可以作为参数移动。
    在客户端,你可以有这样的代码:

    %% 客户端某处
    %% 客户端在 node() == 'client@domain.com' 上运行

    -模块(客户端)。
    -编译(export_all)。
    -定义(服务器,{服务器,'server@domain.com'})。

    give_a_server_a_job(Number)-> ?SERVER ! {build_fun(),Number}。

    build_fun()->
    FunObject = fun(Param)->
    答案 = 参数 * 20/1000,此处计算 %%
    rpc:call('client@domain.com',client,answer_ready,[Answer])
    结尾,
    有趣的对象。

    answer_ready(答案)->
    %%% 使用 Answer 来处理各种有趣的事情....
    io:format("\n\tAnswer is here: ~p~n",[Answer]).

    然后服务器有这样的代码:

    %%% 服务器上的某个地方
    %%% 服务器在 node() == 'server@domain.com' 上运行

    -模块(服务器)。
    -编译(export_all)。

    start()-> register(server,spawn(?MODULE,loop,[]))。

    循环()->
    收到
    {Fun,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> dynamic_compile:load_from_string(String)。
    {模块,添加}
    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)。

    %% 在 String 格式中,这将成为这段代码
    StringCode = "-module(fib).\n -export([fib/1]).\nfib(N) 当 N == 0 -> 0;\n fib(N) 当 (N < 3) and (N > 0) -> 1;\n fib(N) 当 N > 0 -> fib(N-1) + fib(N-2)。\n"。

    %% 然后客户端将上面的这个字符串发送到服务器,服务器将 %% 动态加载代码并执行它
    send_fib_code(Arg)->
    {ServerRegName,ServerNode} ! {string,StringCode,fib,Arg},
    好的。

    get_answer({fib,of,This,is,That}) ->
    io:format("Fibonacci (from server) of ~p is: ~p~n",[This,That])。

    %%% 在服务器
    循环(服务器状态)->
    收到
    {string,StringCode,Fib,Arg} 当 Fib == fib ->
    试试 dynamic_compile:load_from_string(StringCode) 的
    {module,AnyMod} ->
    答案 = AnyMod:fib(Arg),
    %%% 将答复发送回客户端
    %%% 应该是异步的
    %%% 因为 channel 不同而不是
    %% 客户端等待
    rpc:call('client@domain.com',client,get_answer,[{fib,of,Arg,is,Answer}])
    捕获
    _:_ -> error_logger:error_report(["无法从客户端动态编译和加载模块"])
    结尾,
    循环(服务器状态);
    _ -> 循环(服务器状态)
    结尾。

    那段粗略的代码可以告诉你我想说什么。但是,请记住卸载所有不可用的动态模块。您也可以通过一种方法让服务器在再次加载之前尝试检查此类模块是否已加载。我建议你不要复制和粘贴上面的代码。查看并理解它,然后编写自己的版本来完成这项工作。成功 !!!

    关于Erlang:将客户端进程/功能卸载到服务器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7917108/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com