有没有推荐的轻量级pubsub服务/库?

时间:2013-01-22 08:54:32

标签: c++ linux static-libraries message-queue publish-subscribe

我正在构建一个包含许多部分的小型系统,我想使用消息pub/sub服务在各部分之间进行通信。

我读到了一些像RabbitMQ和ZeroMQ这样的消息队列服务,但我觉得它们太复杂了,感觉它是为分布式系统而生的。我的系统的所有部分都将用C ++ / Linux编写并放在一个小的Raspberry Pi CPU上,所以我不需要像可扩展的跨平台的其他语言客户端这样的功能......

你们可以给我一些适合我需要的服务或图书馆的建议吗?

3 个答案:

答案 0 :(得分:8)

实际上做自己并不难。

首先,您需要定义要使用的协议。它可以很简单;就像消息类型字段,有效负载大小字段和实际有效负载一样。您需要的邮件类型SUBSCRIBEUNSUBSCRIBEPUBLISHSUBSCRIBEUNSUBSCRIBE消息的有效负载是要订阅/取消订阅的频道的名称。 PUBLISH消息的有效负载是通道名称和实际数据(当然还有数据大小)。

要连接所有订阅者,您需要一个中央服务器。所有订阅者/发布者都需要连接到此服务器。服务器程序保留一组队列,每个通道一个。当订阅或发布消息到达服务器以查找不存在的通道时,请为此通道创建新的消息队列。对于每个通道,服务器还需要订阅该通道的所有客户端的集合。当发布消息到达服务器时,它会被添加到相关频道的队列末尾。当通道队列不为空时,将其副本发送给该通道的所有订户,当所有订户都收到该通道时,可以从队列中删除该消息。

服务器的困难部分可能是通信部分。简单的部分将是所有队列和集合,因为您可以对所有队列和集合使用C++ standard containers(例如std::queue表示实际队列,std::unordered_map表示频道,std::vector用于收集连接的客户。)

客户端非常简单,所有需要做的就是能够发送订阅并将消息发布到服务器,并从服务器接收发布消息。困难的部分将再次成为实际的沟通部分。


后记:

我从来没有真正建立过这样一个系统,以上所有这些都只是我的头脑。经验丰富的程序员不需要花费几个小时来实现基础知识,对于没有经验的程序员来说可能需要几天时间。

对于您可以使用的通信,例如Boost ASIO,也许每个频道使用一个threads。您可以使用类似Boost property tree的内容来构建/解析JSONXML条消息。

然而,当你可能在几个小时内开始使用像RabbitMQ这样的现有系统时,所有这些都重新发明了轮子,为你节省了大量的时间(以及很多错误!)

答案 1 :(得分:7)

就轻量级服务器而言,Redis支持pub / sub命令。

Redis代码本身非常紧凑(只有几个文件),它是单线程的(使用事件循环),内存消耗非常低(与我见过的其他Queing系统相比)。

答案 2 :(得分:3)

我知道它已经晚了但可能对其他人有用。我使用boost在C ++中实现了一个基本的pub / sub。

CppPubSub

用法非常简单。从一端发布您的数据(通用地图)在一个频道上,另一边订阅相同的频道并再次接收通用地图。

// you should create a singleton object of NotificationService class, make it accessible throughout your application. 
INotificationService* pNotificationService = new NotificationService();

// Subscribe for the event.
function<NotificationHandler> fnNotificationHandler = bind(&SubscriberClass::NotificationHandlerFunction, this, std::placeholders::_1);
subscriptionToken = pNotificationService->Subscribe("TEST_CHANEL", fnNotificationHandler);

// Publish event
NotificationData _data;
_data["data1"] = "Hello";
_data["data2"] = "World";
pNotificationService->Publish("TEST_CHANEL", _data);

// Unsubscribe event.
pNotificationService->Unsubscribe(subscriptionToken);