serialization - Erlang序列化

标签 serialization erlang

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

谢谢

最佳答案

首先,如果您要发送匿名函数,请务必小心。或者,干脆不这样做

在某些情况下,该函数甚至不会被执行,或者会以完全错误的方式执行。

Erlang 中的每个函数,即使是匿名函数,都属于某个模块,确切地说,是在它内部构造的模块中。如果这个函数是用 REPL 构建的,它就会绑定(bind)到 erl_eval 模块,这会更加危险(我会进一步解释为什么)。

假设您启动了两个节点,其中一个有一个名为“foo”的模块,而其中一个没有加载这样的模块(并且无法加载它)。如果您在模块“foo”内构造一个 lambda,将其发送到第二个节点并尝试调用它,您将失败并显示 {error, undef}。

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

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

其次,有很多方法可以在事先不知道的情况下获取 lambda 中的进程或端口

尽管有一种方法可以从 lambda 捕获闭包变量(如果您看一下二值化 lambda,会发现其中使用的所有外部变量都从第二个字节开始列出),但它们并不是潜在 pid 或端口的唯一来源。

考虑一个简单的示例:您在 lambda 中调用 self() 函数。它会返回什么?对了,一个pid。好吧,我们也许可以解析二进制文件并捕获这个函数调用,以及十几个其他内置函数。但是当你调用一些外部函数时你会做什么呢? ets:lookup(sometable, somekey)? some_module:some_function_that_returns_god_knows_what()?你不知道他们会返回什么。

现在,看看您实际上可以在这里做什么

  1. 处理文件时,始终发送文件名,而不是描述符。如果您需要文件的位置或其他信息,也请发送。文件描述符不应该被打开的进程之外的人所知。

  2. 正如我所提到的,尽一切努力避免将 lambda 表达式发送到其他节点。很难说如何避免这种情况,因为我不知道你的确切任务。也许,您可以发送要执行的函数列表,例如:

    [{module1, parse_query},
     {module1, dispatch_parsed_query},
     {module2, validate_response},
     {module2, serialize_query}]
    

    并通过此函数序列传递参数(确保所有模块都存在)。也许,您实际上可以坚持使用某些将经常更改并部署在整个集群上的模块。也许,您可能想切换到 JS/Lua 并使用外部启动的端口(Riak 正在使用 Spidermonkey 来处理用于 Map/Reduce 请求的 JS 编写的 lambda)。最后,您实际上可以获取模块的目标代码,将其发送到另一个节点并在那里加载。请记住,这也不安全。您可能会中断一些正在运行的进程,丢失一些构造的 lambda,等等。

关于serialization - Erlang序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13660267/

相关文章:

java - 为什么可序列化的内部类不可序列化?

python - 类型错误 : object is not JSON serializable in DJango 1. 8 Python 3.4

list - 在 Erlang 中,如何从给定 id 值的记录列表中返回整个记录?

sql-server - Erlang 和 MS SQL Server

erlang - 如何使用 hackney 在 elixir 中发送 body 参数

serialization - golang stringize struct 结构(没有数据)

C++设计——网络数据包和序列化

erlang - 我怎样才能编译erdis?

c# - Json.net 只序列化某些属性

Erlang Shell 工作目录