针对 C/C++ 远程消息队列的建议

Posted

技术标签:

【中文标题】针对 C/C++ 远程消息队列的建议【英文标题】:Recommendations for C/C++ remote message queues 【发布时间】:2012-05-13 11:54:15 【问题描述】:

我正在开展一个项目,该项目涉及多个 C++ 程序,每个程序都接受输入并生成输出。数据(几十到几百个字节,可能是 JSON)本质上是(异步)向一个方向流动,程序需要位于 LAN 周围的不同 Linux 计算机上。

由于数据只在一个方向流动,我认为我不需要像 HTTP 这样的事务模型。我认为消息队列模型(即发即弃)最有意义,并且应该简化每个程序的逻辑。仅注意消息已成功添加到远程队列可能就足够了。

我正在寻找有关如何在 C 或 C++ 中实现此消息队列的建议。似乎POSIX 和Boost 消息队列仅限于单个主机,RabbitMQ 似乎对 C/C++ 的支持较弱,而MQ4CPP 似乎不足以支持关键业务角色。我错了吗? Boost ASIO 或 ACE 或自己编写套接字代码怎么样?我期待您的建议。

【问题讨论】:

ZeroMQ is pretty nice. 很好的答案,每个人,但我真的很喜欢 ZeroMQ 的简单性。如果@sixlettervariables 是一个答案,我会接受。 【参考方案1】:

在简单消息支持方面,ZeroMQ is hard to beat。它在许多语言绑定中可用,并支持从简单的发送和接收到发布/订阅、扇出甚至消息传递管道的所有内容。代码也很容易消化,并且很容易在模式之间切换。

查看他们的Weather Update Server sample(使用 20 种奇怪的语言)可以看出创建发布/订阅设置是多么容易:

zmq::context_t context (1);
zmq::socket_t publisher (context, ZMQ_PUB);
publisher.bind("tcp://*:5556");
publisher.bind("ipc://weather.ipc");

while(1) 
    //  Send message to all subscribers
    zmq::message_t message(20);
    snprintf ((char *) message.data(), 20 ,
        "%05d %d %d", zipcode, temperature, relhumidity);
    publisher.send(message);

我已经在一些混合的 C# 和 Python 进程中使用它,没有太多麻烦。

【讨论】:

【参考方案2】:

另一个消息传递解决方案是 ICE (http://www.zeroc.com/)。它是多平台、多语言的。它更多地使用 RPC 方法。

【讨论】:

虽然它是一款很棒的产品,但 ICE is GPLed。除非您的代码也是 GPL 或愿意为商业许可证付费,否则我会避开它。【参考方案3】:

RabbitMQ 只是AMQP 的一种实现。您可能想要调查 Apache Qpid 或其他可能对 C/C++ 更友好的变体。尽管我没有第一手经验,但 C 有一个 libamqp。我不知道您的具体要求是什么,但正确实施的 AMQP 具有工业实力,应该比您在短时间内手工构建的任何东西都要快几个数量级且更稳定。

【讨论】:

【参考方案4】:

另一个推荐是分布式框架OpenCL。文档The OpenCL C++ Wrapper for API 提供了有关该库的更多信息。特别是,API 函数 cl::CommandQueue 可能对在网络设置中的设备上创建队列感兴趣。

【讨论】:

【参考方案5】:

就个人而言,如果我理解了这个问题,我认为您应该使用较低级别的 TCP 连接。它具有您想要的所有保证交付,并且具有相当好的 Berkley Sockets API。 我发现如果你愿意实现一个非常简单的协议(例如,四字节的 NBO 消息长度,n 个字节的数据),你可以得到非常简单、非常可定制和非常简单的。如果你这样做,你也(如前所述)得到很好的 C 支持(这意味着 C++ 支持,虽然东西不在类和方法中)。套接字代码也很简单,它们具有异步 IO,具有用于 Linux/UNIX/POSIX IO 功能的标准异步标志(这是其他好处之一,如果您对 POSIX 编程有所了解,那么您基本上知道套接字 API) .

学习套接字 API 的最佳资源之一是:

Beej 的网络编程指南:http://beej.us/guide/bgnet/,如果除了细节之外还需要整体编程模型,这非常好 手册页:如果您只需要函数签名、返回值和参数,这些就是您所需要的。我发现 Linux 编写得非常好并且很有用(证明:看看我的控制台:manmanmanmanmanmakeman、.. .)

此外,为了使数据可通过网络发送,如果您的数据是 JSON,则无需担心。因为 JSON 只是 ASCII(或 UTF-8),所以它可以通过网络以原始形式发送,只有一个长度标头。除非您尝试发送复杂的二进制文件,否则这应该是完美的(如果您需要复杂的二进制文件,请查看序列化或准备大量Segmentation Fault)。


另外,如果您使用套接字路径,您可能想要使用 TCP。尽管 UDP 会为您提供单向方面,但使其可靠这一事实使您的自制解决方案与 Linux 内核提供的*** TCP 相抗衡,但 TCP 是一个明显的选择。

【讨论】:

【参考方案6】:

我正在为类似的应用程序使用 Boost 序列化和套接字发送。你可以在这里找到一个序列化的例子:

http://code.google.com/p/cloudobserver/wiki/TutoriaslBoostSerialization

在这个页面上:

http://www.boost.org/doc/libs/1_38_0/doc/html/boost_asio/examples.html

在序列化下,您将找到有关如何制作服务器和客户端的示例。在特定端口上创建一个服务器,您可以在多台计算机上生成多个可以与该端口通信的客户端。

使用 boost 序列化的缺点是,如果您有一个要序列化的简单数据结构,它会产生很大的开销,但它确实很容易。

【讨论】:

以上是关于针对 C/C++ 远程消息队列的建议的主要内容,如果未能解决你的问题,请参考以下文章

消息队列rabitMq

如何使用NODEJS+REDIS开发一个消息队列

python RabbitMQ消息队列

MQ消息队列(Message Queue)

企业级消息队列 RabbitMQ

企业级消息队列 RabbitMQ