2013-01-22 9 views
11

Buduję mały system, który zawiera wiele części i chcę używać usługi pub pub/sub do komunikacji między częściami.Potrzebujesz lekkiej usługi/biblioteki pubsub

Przeczytałem o niektórych usługach kolejki komunikatów, takich jak RabbitMQ i ZeroMQ, ale uważam, że są zbyt skomplikowane i mają wrażenie, że zostały stworzone dla systemu rozproszonego. Wszystkie części mojego systemu będą napisane w C++/Linux i umieszczone na małym procesorze Raspberry Pi, więc nie potrzebuję funkcji takich jak skalowalne, wieloplatformowe, inne języki klientów ...

Czy możecie mi doradzić? o usługach lub bibliotekach, które pasują do moich potrzeb? Lub Ty

Dzięki.

+0

Czy potrzebujesz użyć biblioteki lub usługi? A może, biorąc pod uwagę warunki, wystarczy użyć gniazd lub rur? Byłoby to prawdopodobnie bardziej wydajne dla malin. –

+1

ZeroMQ jest bardzo prosty w użyciu. – Kimi

+1

@ dema80: Preferuję usługę, ale lib jest w porządku. Czy możesz zasugerować wykorzystanie gniazd użytkowych? – Yoshi

Odpowiedz

7

Właściwie nie jest to trudne.

Przede wszystkim musisz zdefiniować protokół, który ma być użyty. To może być bardzo proste; jak tylko pole typu komunikatu, pole rozmiaru ładunku i rzeczywisty ładunek. Typy wiadomości, których potrzebujesz: SUBSCRIBE, UNSUBSCRIBE i PUBLISH. Ładunek dla wiadomości SUBSCRIBE i UNSUBSCRIBE to nazwa kanału, z którego subskrybujesz/rezygnujesz z subskrypcji. Ładunek dla wiadomości PUBLISH to nazwa kanału i rzeczywiste dane (wraz z rozmiarem danych oczywiście).

Do połączenia wszystkich subskrybentów potrzebny jest serwer centralny. Wszyscy subskrybenci/wydawcy muszą połączyć się z tym serwerem. Program serwera przechowuje kolekcję kolejek, po jednej dla każdego kanału. Gdy wiadomość subskrybowana lub publikowana zostanie dostarczona do serwera dla kanału, który nie istnieje, utwórz nową kolejkę komunikatów dla tego kanału. Dla każdego kanału serwer potrzebuje również kolekcji wszystkich klientów subskrybujących ten kanał. Gdy wiadomość do opublikowania dotrze do serwera, zostanie dodana na końcu kolejki dla danego kanału. Chociaż kolejka kanałów nie jest pusta, wyślij jej kopię wszystkim subskrybentom tego kanału, a gdy wszyscy ją otrzymają, wiadomość może zostać usunięta z kolejki.

Najtrudniejszą częścią serwera będzie prawdopodobnie część komunikacyjna. Łatwa część będzie wszystkie kolejki i zbiory, jak można użyć C++ standard containers dla wszystkich z nich (np std::queue dla rzeczywistej kolejce std::unordered_map dla kanałów i std::vector do zbierania powiązanych klientów).

Klienci są bardzo proste, wszystko co musisz zrobić, to móc wysyłać subskrypcje i publikować wiadomości na serwer, a także odbierać wiadomości publikowania z serwera. Najtrudniejsza część znów będzie faktyczną częścią komunikacji.


Postscriptum:

Nigdy faktycznie zbudowany taki system moje ja, wszystkie wyżej tylko bezpośrednio z górnej części głowy. Doświadczony programista nie powinien potrzebować więcej niż kilka godzin na wdrożenie podstaw, może kilka dni dla niedoświadczonego.

Do komunikacji można użyć np. Boost ASIO, może użyć jednego kanału threads. Możesz użyć czegoś takiego, jak Boost property tree do konstruowania/analizowania wiadomości: JSON lub XML.

Jednak to wszystko jest rodzajem ponownego wynajdywania koła, kiedy prawdopodobnie za kilka godzin można zacząć używać jednego z istniejących systemów, takich jak RabbitMQ, oszczędzając mnóstwo czasu (i wiele błędów!)

+2

Ja drugi pomysł, ale tylko wtedy, gdy "struktura", którą zamierzasz zbudować, jest super prosta i musi być lekka, inaczej ... nie wymyślaj koła! Zbudowałem tego rodzaju system dla przeszłego projektu, w .NET, w ciągu zaledwie kilku dni, wszystko wliczone w cenę. To było zabawne i płonęło szybko. A ponieważ było to bardzo ekonomiczne, gdy później musieliśmy skalować, wyrzuciliśmy je i zastąpiliśmy bez oglądania się za siebie. W C++ użyłbym również Boost. –

4

Jeśli chodzi o serwery lekkie, Redis obsługuje polecenia pub/sub.

Sam kod Redis jest bardzo napięty (tylko kilka plików), jest jednotomowy (użyj pętli zdarzeń), a zużycie pamięci jest dość niskie (w porównaniu do innych systemów Queing, które widziałem).

+1

Bardzo podoba mi się Redis i już używałem go jako usługi pamięci podręcznej/sklepu w niektórych prywatnych projektach. Ciekawe, czy pasuje do małego procesora takiego jak malinowy PI? – Yoshi

+0

@Yoshi: w porównaniu do innych systemów kolejkowania (ActiveMQ, RabbitMQ, HornetQ, ...) z pewnością jest bardziej prawdopodobne, że pasuje. Byłbym bardziej zainteresowany RAM, ale zawsze możesz usunąć Lua JIT etc ..., aby uzyskać lżejszy proces. –

+0

Wygląda na to, że polecenie redis działa tylko w przypadku wiadomości tekstowych. A co z plikiem binarnym? – liuyanghejerry

3

Wiem, że jest późno, ale może być przydatne dla innych. Zaimplementowałem podstawowy pub/sub w C++ za pomocą boost.

CppPubSub

Użycie jest bardzo proste. Z jednego końca publikuj swoje dane (mapa ogólna) na kanale, a druga strona subskrybuj dla tego samego kanału i otrzymuj ponownie mapę ogólną.

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