序列化可变状态并通过网络以近乎零拷贝的方式异步发送(Cap'n Proto + ZeroMQ)

Serializing mutable state and sending it asynchronously over the network with nearly-zero-copy (Cap'n Proto + ZeroMQ)

本文关键字:Cap ZeroMQ Proto 异步 方式 状态 网络 拷贝 近乎零 序列化      更新时间:2023-10-16

我有一个应用程序,我想通过网络将其可变状态的一部分发送到另一台机器(将有这些机器的集群)对其进行一些CPU密集型计算并返回结果。就像异步 RPC 一样。在程序执行期间,此类调用会发生多次,因此我想使开销尽可能小,例如尽量减少数据的冗余副本的数量。数据的大小从几十字节到几百KB不等,甚至可能只有几MB。它的结构相对复杂,它由一组对象树组成,但叶子只包含基元类型,内部节点包含最少的元数据。

我正在考虑使用 Cap'n Proto 进行序列化(不过,在这种情况下,我必须为我的数据创建一个冗余模型),以及用于传输的 ZeroMQ。在客户端/主应用程序端,我想使用 azmq,因为我需要 Boost:Asio 的功能(即协程/光纤支持)。语言是C++。

用一个非常粗略的草图总结:

RelativelyComplexState data;
CapnProtoRequest cp_req = buildRequest(data); // traverses my data, creates C'n P object
azmq_socket.async_send(boost::asio::buffer(cp_req, cp_req.size)); //azmq always copies the buffer? Not good.
// do other stuff while request is being processed remotely
// get notification from azmq/Boost:Asio when reply has arrived
azmq::message msg();
azmq_socket.async_receive(some_message_handler?); // get all the data into msg
CapnProtoResponse cp_resp = parseResponse(msg.cbuffer()); // interpret bytes as C'n P object, hopefully no copy
RelativelySimpleResult result = deserialize(cp_resp);

这是可行的,还是有更好的方法?在这种情况下,无架构序列化方法(即 Boost::Serialization)是否会使我的生活更轻松和/或应用程序更高效?

另外,使用 ZeroMQ/azmq 发送和接收 Cap'n Proto 对象的最佳方式是什么,避免不必要的副本?通过查看 azmq 的源代码,似乎对于发送,azmq 总是复制缓冲区内容。更微妙的问题是什么(细分/框架等)?我不熟悉这些库,也没有找到任何解释或好的例子。

谢谢!

我对 ZeroMQ 的接口了解不多,但我可以就如何最小化 Cap'n Proto 的副本提供建议。

在发送端,使用 capnp::MessageBuilder::getSegmentsForOutput()capnp/message.h ) 获取指向消息内容的直接指针,而无需复制。这为您提供了一个字节数组数组(实际上是单词,但您可以将它们转换为字节)。您需要以某种方式将这些提供给 ZeroMQ,而无需复制它们。您需要确保保留段之间的边界 - 目标是在接收端提出完全相同的数组数组。也许 ZeroMQ 明确支持多段消息,可以为您记住分段边界;如果没有,您需要在邮件前面加上细分大小表。

在接收端,一旦你重建了你的段数组,构造一个capnp::SegmentArrayMessageReadercapnp/message.h)并将数组传递给构造函数。这将使用基础数据而不复制。(请注意,您需要确保数据在 64 位边界上对齐。我不确定 ZeroMQ 是否保证这一点。

请注意,如果您的客户端和服务器都C++,您可能需要考虑使用 Cap'n Proto 自己的 RPC 协议,该协议更易于设置,并且已经避免了所有不必要的副本。但是,将 Cap'n Proto 的事件循环与 boost::asio 集成目前并非易事。这是可能的 - 例如,您可以查看将Cap'n Proto与libuv的事件循环集成的node-capnp - 但可能比您想要做的要多。

(披露:我是Cap'n Proto的作者。