16

我正在构建一个包含许多部件的小型系统,我想使用消息发布/订阅服务在部件之间进行通信。

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

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

4

3 回答 3

8

其实做自己并不难。

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

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

服务器最难的部分可能是通信部分。最简单的部分是所有队列和集合,因为您可以为所有队列和集合使用C++ 标准容器(例如std::queue,用于实际队列、std::unordered_map通道和std::vector连接客户端的集合。)

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


后记:

我自己从来没有真正构建过这样的系统,以上所有内容都只是我的头脑。一个有经验的程序员不应该需要超过几个小时来实现基础知识,对于一个没有经验的程序员来说可能需要几天。

对于您可以使用的通信,例如Boost ASIO ,可能每个通道使用一个线程。您可以使用Boost 属性树之类的东西来构造/解析JSONXML消息。

然而,所有这一切都是在重新发明轮子,当您可能在几个小时内开始使用 RabbitMQ 等现有系统之一时,为您节省了大量时间(还有很多错误!)

于 2013-01-22T09:22:23.853 回答
7

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

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

于 2013-01-22T09:38:59.813 回答
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);
于 2015-11-19T15:49:04.957 回答