Serialization Erlang序列化

Serialization Erlang序列化,serialization,erlang,Serialization,Erlang,我需要在Erlang中序列化一个函数,将它发送到另一个note,反序列化并在那里执行它。我遇到的问题是文件。如果函数读取的文件不在第二个节点中,则会出现错误。有没有办法区分Erlang中可序列化和不可序列化的结构?因此,如果函数使用文件或pid,那么它无法序列化 谢谢首先,如果要发送匿名函数,请格外小心。或者,更确切地说,就是不要这样做 有两种情况下,此函数甚至不会执行或将以完全错误的方式执行 Erlang中的每个函数,甚至是匿名函数,都属于某个模块,确切地说,它是在其中构造的。如果这个函数是在

我需要在Erlang中序列化一个函数,将它发送到另一个note,反序列化并在那里执行它。我遇到的问题是文件。如果函数读取的文件不在第二个节点中,则会出现错误。有没有办法区分Erlang中可序列化和不可序列化的结构?因此,如果函数使用文件或pid,那么它无法序列化

谢谢

首先,如果要发送匿名函数,请格外小心。或者,更确切地说,就是不要这样做 有两种情况下,此函数甚至不会执行或将以完全错误的方式执行

Erlang中的每个函数,甚至是匿名函数,都属于某个模块,确切地说,它是在其中构造的。如果这个函数是在REPL中构建的,那么它将绑定到erl_eval模块,这更危险(我将进一步解释原因)

比如说,启动两个节点,其中一个节点有一个名为“foo”的模块,另一个节点没有加载这样的模块(并且无法加载)。如果在模块“foo”中构造lambda,将其发送到第二个节点并尝试调用它,则会失败,并出现{error,undf}

可能还有另一个有趣的问题。尝试制作两个版本的模块“foo”,在每个模块中实现一个“bar”函数,并在其中实现一个lambda(但lambda将不同)。在尝试调用已发送的lambda时,您将遇到另一个错误

我认为,将lambda发送到不同的节点可能会有其他棘手的部分,但是相信我,这已经相当多了

其次,有很多方法可以在不事先知道的情况下在lambda中获得进程或端口 即使有一种方法可以从lambda捕获closured变量(如果您查看二进制lambda,其中使用的所有外部变量都从第2个字节开始列出),它们也不是潜在PID或端口的唯一来源

考虑一个简单的例子:在lambda中调用
self()
函数。它会返回什么?对,一个pid。好的,我们可能可以解析二进制文件并捕获这个函数调用,以及十几个其他内置函数。但是当你调用一些外部函数时,你会怎么做呢<代码>ets:查找(sometable,sometkey)<代码>一些模块:一些函数返回什么()?你不知道他们会回来什么

现在,来看看你在这里能做些什么
  • 处理文件时,始终发送文件名,而不是描述符。如果您需要文件的位置或其他信息,也可以发送。文件描述符不应在已打开的进程之外被知道

  • 正如我提到的,尽一切努力避免lambda被发送到其他节点。很难说如何避免,因为我不知道你的确切任务。也许,您可以发送要执行的函数列表,如:

    [{module1, parse_query},
     {module1, dispatch_parsed_query},
     {module2, validate_response},
     {module2, serialize_query}]
    
    并通过这个函数序列传递参数(确保所有模块都存在于任何地方)。也许,您实际上可以坚持使用一些将在整个集群上频繁更改和部署的模块。也许,您可能希望切换到JS/Lua并使用外部启动的端口(Riak使用spidermonkey来处理JS编写的lambda,用于Map/Reduce请求)。最后,您可以实际获取模块的目标代码,将其发送到另一个节点并加载到该节点。记住这也不安全。您可以中断一些正在运行的进程,丢失一些构造的lambda,等等


  • 看看这个问题及其答案:@Muzaaya Joshua我在将函数发送到远程节点、编译和使用它们方面没有问题。我在识别他们正在使用的资源时遇到问题,例如在客户端而不是服务器上找到的文件。true。这意味着如果从一个节点发送到另一个节点的
    Funs
    依赖于某些
    Module:Function(Args)
    调用,则必须确保模块
    Module
    位于所有节点上的代码路径中。