Есть ли рекомендуемые облегченные сервисы/библиотеки pubsub?

Я строю небольшую систему, которая содержит много частей, и я хочу использовать паб/суб- сервис сообщений для связи между частями.

Я читал о некоторых службах очереди сообщений, таких как RabbitMQ и ZeroMQ, но чувствую, что они слишком сложны и чувствую, что они созданы для распределенной системы. Все части моей системы будут написаны на C++/Linux и размещены на небольшом процессоре Raspberry Pi, поэтому мне не нужны такие функции, как масштабируемые, кроссплатформенные, другие языковые клиенты...

Ребята, можете ли вы дать мне несколько советов об услугах или библиотеках, которые соответствуют моим потребностям?

Ответ 1

Это не так уж сложно сделать на самом деле.

Прежде всего вам нужно определить используемый протокол. Это может быть очень просто; как поле типа сообщения, поле размера полезной нагрузки и фактическая полезная нагрузка. Для типов сообщений вам нужны SUBSCRIBE, UNSUBSCRIBE и PUBLISH. Полезная нагрузка для сообщений SUBSCRIBE и UNSUBSCRIBE - это название канала для подписки на/отписки от. Полезной нагрузкой для сообщения PUBLISH является имя канала и фактические данные (вместе с размером данных, конечно).

Для подключения всех абонентов вам нужен центральный сервер. Все подписчики/издатели должны подключиться к этому серверу. Программа сервера хранит набор очередей, по одному для каждого канала. Когда сообщение подписки или публикации поступает на сервер для канала, который не существует, создайте новую очередь сообщений для этого канала. Для каждого канала серверу также нужна коллекция всех клиентов, которые подписываются на этот канал. Когда сообщение публикации поступает на сервер, оно добавляется в конец очереди для рассматриваемого канала. Пока очередь каналов не пуста, отправьте ее копию всем подписчикам для этого канала, и когда все они ее получили, сообщение может быть удалено из очереди.

Жесткая часть сервера, вероятно, будет частью связи. Легкой частью будут все очереди и коллекции, так как вы можете использовать стандартные контейнеры С++ для всех из них (например, std::queue для текущей очереди std::unordered_map для каналов, а std::vector для коллекции подключенных клиентов.)

Клиенты очень просты, все, что нужно сделать, это возможность отправлять подписку и публиковать сообщения на сервере и получать сообщения публикации с сервера. Твердая часть снова станет фактической коммуникационной частью.


Постскриптум:

Я никогда не строил такую ​​систему самостоятельно, все вышеизложенное было прямо на моей голове. У опытного программиста не должно быть больше двух часов, чтобы реализовать основы, возможно, пару дней для неопытного.

Для связи, которую вы могли бы использовать, например. Boost ASIO, возможно, используйте один потоки для каждого канала. И вы можете использовать что-то вроде Дерево свойств Boost для создания/разбора JSON или XML.

Тем не менее, все это как бы заново изобретает колесо, когда вы, вероятно, можете начать использовать одну из существующих систем, таких как RabbitMQ, через пару часов, экономя много времени (и много ошибок!)

Ответ 2

Что касается облегченных серверов, Redis поддерживает команды pub/sub.

Код Redis сам по себе чрезвычайно трудный (всего пара файлов), он однопоточный (использует цикл обработки событий), а потребление памяти довольно низкое (по сравнению с другими системами очередей, которые я видел).

Ответ 3

Я знаю, что это поздно, но может быть полезно для других. Я реализовал базовый pub/sub на С++, используя boost.

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);