2013-01-22 7 views
11

Sto costruendo un piccolo sistema che contiene molte parti e voglio usare un message pub/sub-servizio per comunicare tra le parti.Serve un servizio/libreria leggera per pubblicazioni pubbli

Ho letto di alcuni servizi di messaggi in coda come RabbitMQ e ZeroMQ ma sento che sono troppo complicati e mi sento come se fosse nato per il sistema distribuito. Tutte le parti del mio sistema saranno scritte in C++/Linux e posizionate su una piccola CPU Raspberry Pi, quindi non ho bisogno di funzionalità come client scalabili, multipiattaforma, altre lingue ...

Potete darmi qualche consiglio su servizi o librerie che si adattano alle mie esigenze? Oppure tu

Grazie.

+0

Hai bisogno di utilizzare una lib o un servizio? O potresti, visto i prerequisiti, usare solo prese o tubi? Sarebbe, probabilmente, più efficiente per un Raspberry. –

+1

ZeroMQ è molto semplice da usare. – Kimi

+1

@ dema80: preferisco il servizio ma lib è ok. Puoi suggerire eventuali prese per l'uso degli attrezzi? – Yoshi

risposta

7

Non è difficile da fare in realtà.

Prima di tutto è necessario definire il protocollo da utilizzare. Può essere molto semplice; come solo un campo del tipo di messaggio, un campo di dimensioni del carico utile e il carico utile effettivo. I tipi di messaggi necessari sono SUBSCRIBE, UNSUBSCRIBE e PUBLISH. Il carico utile per i messaggi SUBSCRIBE e UNSUBSCRIBE è il nome di un canale per iscriversi/annullare la sottoscrizione. Il payload per il messaggio PUBLISH è il nome del canale e i dati effettivi (insieme ovviamente alla dimensione dei dati).

Per connettere tutti gli abbonati è necessario un server centrale. Tutti gli abbonati/editori devono connettersi a questo server. Il programma server mantiene una collezione di code, una per ogni canale. Quando un messaggio di iscrizione o pubblicazione arriva al server per un canale che non esiste, creare una nuova coda di messaggi per questo canale. Per ogni canale il server ha anche bisogno di una collezione di tutti i clienti iscritti a quel canale. Quando un messaggio di pubblicazione arriva al server, viene aggiunto alla fine della coda per il canale in questione. Mentre una coda canale non è vuota, invia una copia di essa a tutti gli abbonati per quel canale, e quando tutti lo hanno ricevuto, il messaggio può essere rimosso dalla coda.

La parte difficile del server è probabilmente la parte di comunicazione. La parte più facile sarà tutte le code e le collezioni, come è possibile utilizzare il C++ standard containers per tutti loro (ad esempio std::queue per la coda reale, std::unordered_map per i canali, e std::vector per la raccolta di clienti collegati.)

I clienti sono molto semplice, tutta la necessità di fare è poter inviare l'abbonamento e pubblicare messaggi sul server e ricevere i messaggi di pubblicazione dal server. La parte difficile sarà ancora una volta l'effettiva parte della comunicazione.


Postscript:

non ho mai costruito un sistema del genere la mia auto, tutto quanto sopra era solo direttamente della parte superiore della mia testa. Un programmatore esperto non dovrebbe aver bisogno di più di un paio d'ore per implementare le basi, forse un paio di giorni per un inesperto.

Per la comunicazione che è possibile utilizzare ad es. Boost ASIO, forse usa uno threads per canale. E puoi usare qualcosa come Boost property tree per costruire/analizzare i messaggi JSON o XML.

Tuttavia, tutto questo è un po 'come reinventare la ruota, quando probabilmente potresti iniziare a utilizzare uno dei sistemi esistenti come RabbitMQ in un paio d'ore, risparmiando un sacco di tempo (e un sacco di bug!)

+2

I secondo l'idea, ma solo se il "framework" che si sta per costruire è super-semplice e deve essere leggero, altrimenti .. non reinventare la ruota! Ho costruito questo tipo di sistema per un progetto passato, in .NET, in un paio di giorni, tutto incluso. È stato divertente ed è stato velocissimo. E poiché era molto economico quando in seguito dovevamo ridimensionare, lo gettammo via e lo sostituimmo senza voltarci indietro. In C++, vorrei usare anche Boost. –

4

Per quanto riguarda i server leggeri, Redis supporta i comandi pub/sub.

Il codice Redis è estremamente stretto (solo un paio di file), è a thread singolo (utilizza un ciclo di eventi) e il consumo di memoria è piuttosto basso (rispetto agli altri sistemi di Queing che ho visto).

+1

Mi piacciono molto i Redis e l'ho già usato come servizio cache/store su alcuni progetti privati. Sei curioso di sapere se si adatta a una piccola CPU come il Raspberry PI? – Yoshi

+0

@Yoshi: rispetto a qualsiasi altro sistema di accodamento (ActiveMQ, RabbitMQ, HornetQ, ...) è sicuramente più facile da adattare. Sarei più interessato alla RAM, ma puoi sempre rimuovere Lua JIT ecc. Per ottenere un processo più leggero. –

+0

Sembra che redis sia valido solo per i messaggi basati su testo. Che dire del binario? – liuyanghejerry

3

So che è tardi ma potrebbe essere utile per gli altri. Ho implementato un pub/sub di base in C++ usando boost.

CppPubSub

uso è molto semplice. Da un lato pubblichi i tuoi dati (mappa generica) su un canale e l'altro lato sottoscriva lo stesso canale e riceve di nuovo la mappa generica.

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