【问题标题】:Sharing atoms between http-connected erlang clusters在 http 连接的 erlang 集群之间共享原子
【发布时间】:2015-03-05 06:03:07
【问题描述】:

我们的基础架构中有一些非 erlang 连接的集群,目前使用 term_to_binary 对集群之间消息的 erlang 术语进行编码。在接收端,我们使用 binary_to_term(Bin, [safe]) 仅转换为现有原子(如果消息中有任何原子)。

偶尔(尤其是在启动新的集群/堆栈之后),我们会遇到消息中编码的部分已知原子的问题,即发送集群知道这个原子,但接收不知道。这可能是由于各种原因,最常见的是接收节点根本没有加载包含某些记录定义的模块。我们目前采用了一些令人讨厌的变通方法,基本上相当于维护一个简短的可能使用的原子列表,但我们对这种容易出错的方法不太满意。

有没有一种聪明的方法可以在这些集群之间共享原子?还是建议不要将二进制格式用于此类目的?

期待您的见解。

【问题讨论】:

    标签: erlang


    【解决方案1】:

    我会认真思考为什么非 Erlang 节点首先发送原子值。很可能可以对用于通信的协议进行一些调整 - 或者大多数情况下根本没有定义真正的协议,而实际使用的协议随着时间的推移而有机地发展。

    不知道具体情况,有两种解决办法:

    • 深入并使用抽象序列化技术,如 ASN.1 或 JSON 或其他,使用二进制字符串而不是原子。当您有大量易于理解的结构化数据要发送(可能包含非结构化或不透明数据)时,这最有意义。
    • 保持肤浅,而是为您将首先发送/调用的进程/模块编写一个功能性 API 接口,以确保您完全理解您的协议实际是什么,然后通过使每个接口调用对应于一条匹配的网络消息,当接收到该消息时,它会分派与 API 函数调用相同的过程。

    基本问题是非 Erlang 节点能够生成集群可能不知道的原子的想法。这是一个有点棘手的问题。在许多情况下,在您使用原子的地方,您可以使用二进制文件来获得类似的效果并保留相同的语义,而不会混淆运行时。这是{<<"new_message">>, Data}{new_message, Data} 之间的区别;函数头中的匹配以相同的方式工作,只是在语法上稍微嘈杂。

    【讨论】:

    • 感谢您的意见。 JSON 实际上是我们之前使用的(如果我们没有找到足够的解决方案,我们会回到这个),但是发现多余的步骤 Erlang term -> JSON -> Erlang term 没有必要,因为双方都是 Erlang 节点/clusters 并且已经了解 Erlang 术语。
    • 并澄清一下:集群到集群通信的两侧都是 Erlang 节点。目前我们不想通过 Erlang 将它们连接到一个超级集群(这可能会通过分布式消息传递协议解决原子知识问题)。我确实看到了“未指定 API”的意义,并且会再仔细研究一下,但从第一眼确认的角度来看,我们使用明确定义的记录作为我们消息的构建块,只是遇到了有时这些记录的问题尚未加载(或它的嵌套元素)。
    • @Christian 如果流量是从一个内部到另一个我可能会考虑使用“不安全”垃圾箱来定义,因为你控制着一切。如果您不控制所有内容,我可能会制作所有正在使用的记录的头文件,并将其包含在两端首先加载的任何模块中。 OTOH,“正确”的方法是制定适当的 API 规范,但出于商业原因,这可能是不切实际的。如果是这种情况,我认为记录头文件可能是最不被黑客攻击、最容易被发现和最不可怕的(你仍然可以对术语执行“安全”二进制)。
    • 对不起,我忽略了这么久。我们最终进行了双重包装 - 一个外部定义明确的结构,可以安全地编码/解码(即仅使用现有原子)和一个内部有效负载结构,由于外部结构而被认为是安全的,所以我们解码“不安全” ”。感谢您帮助思考问题@zxq9
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-07
    • 2021-04-29
    • 1970-01-01
    • 2017-08-16
    • 1970-01-01
    相关资源
    最近更新 更多