int main (void) { s_version_assert (2, 1); void *context = zmq_init (1); // Socket to talk to clients void *publisher = zmq_socket (context, ZMQ_PUB); zmq_bind (publisher, "tcp://*:5561"); // Socket to receive signals void *syncservice = zmq_socket (context, ZMQ_REP); zmq_bind (syncservice, "tcp://*:5562"); // Get synchronization from subscribers int subscribers = 0; while (subscribers < SUBSCRIBERS_EXPECTED) { // - wait for synchronization request char *string = s_recv (syncservice); free (string); // - send synchronization reply s_send (syncservice, ""); subscribers++; } // Now broadcast exactly 1M updates followed by END int update_nbr; for (update_nbr = 0; update_nbr < 1000000; update_nbr++) s_send (publisher, "Rhubarb"); s_send (publisher, "END"); zmq_close (publisher); zmq_close (syncservice); zmq_term (context); return 0; }
int main () { s_version_assert (2, 1); void *context = zmq_init (1); // Socket to talk to clients void *clients = zmq_socket (context, ZMQ_XREP); zmq_bind (clients, "tcp://*:5555"); // Socket to talk to workers void *workers = zmq_socket (context, ZMQ_XREQ); zmq_bind (workers, "inproc://workers"); // Launch pool of worker threads int thread_nbr; for (thread_nbr = 0; thread_nbr != 5; thread_nbr++) { pthread_t worker; pthread_create (&worker, NULL, worker_routine, context); } // Connect work threads to client threads via a queue zmq_device (ZMQ_QUEUE, clients, workers); // We never get here but clean up anyhow zmq_close (clients); zmq_close (workers); zmq_term (context); return 0; }
int main (int argc, char *argv []) { int verbose = (argc > 1 && streq (argv [1], "-v")); s_version_assert (2, 1); s_catch_signals (); broker_t *self = s_broker_new (verbose); s_broker_bind (self, "tcp://*:5555"); // Get and process messages forever or until interrupted while (!s_interrupted) { zmq_pollitem_t items [] = { { self->socket, 0, ZMQ_POLLIN, 0 } }; zmq_poll (items, 1, HEARTBEAT_INTERVAL * 1000); // Process next input message, if any if (items [0].revents & ZMQ_POLLIN) { zmsg_t *msg = zmsg_recv (self->socket); if (self->verbose) { s_console ("I: received message:"); zmsg_dump (msg); } char *sender = zmsg_pop (msg); char *empty = zmsg_pop (msg); char *header = zmsg_pop (msg); if (streq (header, MDPC_CLIENT)) s_client_process (self, sender, msg); else if (streq (header, MDPW_WORKER)) s_worker_process (self, sender, msg); else { s_console ("E: invalid message:"); zmsg_dump (msg); zmsg_destroy (&msg); } free (sender); free (empty); free (header); } // Disconnect and delete any expired workers // Send heartbeats to idle workers if needed if (s_clock () > self->heartbeat_at) { s_broker_purge_workers (self); worker_t *worker = zlist_first (self->waiting); while (worker) { s_worker_send (self, worker, MDPW_HEARTBEAT, NULL, NULL); worker = zlist_next (self->waiting); } self->heartbeat_at = s_clock () + HEARTBEAT_INTERVAL; } } if (s_interrupted) printf ("W: interrupt received, shutting down...\n"); s_broker_destroy (&self); return 0; }
int main (void) { s_version_assert (2, 1); // Prepare our context and sockets void *context = zmq_init (1); void *frontend = zmq_socket (context, ZMQ_XREP); void *backend = zmq_socket (context, ZMQ_XREP); zmq_bind (frontend, "tcp://*:5555"); // For clients zmq_bind (backend, "tcp://*:5556"); // For workers // Queue of available workers int available_workers = 0; char *worker_queue [MAX_WORKERS]; while (1) { zmq_pollitem_t items [] = { { backend, 0, ZMQ_POLLIN, 0 }, { frontend, 0, ZMQ_POLLIN, 0 } }; // Poll frontend only if we have available workers if (available_workers) zmq_poll (items, 2, -1); else zmq_poll (items, 1, -1); // Handle worker activity on backend if (items [0].revents & ZMQ_POLLIN) { zmsg_t *zmsg = zmsg_recv (backend); // Use worker address for LRU routing assert (available_workers < MAX_WORKERS); worker_queue [available_workers++] = zmsg_unwrap (zmsg); // Return reply to client if it's not a READY if (strcmp (zmsg_address (zmsg), "READY") == 0) zmsg_destroy (&zmsg); else zmsg_send (&zmsg, frontend); } if (items [1].revents & ZMQ_POLLIN) { // Now get next client request, route to next worker zmsg_t *zmsg = zmsg_recv (frontend); // REQ socket in worker needs an envelope delimiter zmsg_wrap (zmsg, worker_queue [0], ""); zmsg_send (&zmsg, backend); // Dequeue and drop the next worker address free (worker_queue [0]); DEQUEUE (worker_queue); available_workers--; } } // We never exit the main loop return 0; }
// This main thread simply starts several clients, and a server, and then // waits for the server to finish. // int main () { s_version_assert (2, 1); pthread_t client_thread; pthread_create (&client_thread, NULL, client_task, NULL); pthread_create (&client_thread, NULL, client_task, NULL); pthread_create (&client_thread, NULL, client_task, NULL); pthread_t server_thread; pthread_create (&server_thread, NULL, server_task, NULL); pthread_join (server_thread, NULL); return 0; }
mdcli (std::string broker, int verbose) { assert (broker.size()!=0); s_version_assert (4, 0); m_broker = broker; m_context = new zmq::context_t(1); m_verbose = verbose; m_timeout = 2500; // msecs m_retries = 3; // Before we abandon m_client = 0; s_catch_signals (); connect_to_broker (); }
int main (int argc, char *argv []) { int verbose = (argc > 1 && strcmp (argv [1], "-v") == 0); s_version_assert (4, 0); s_catch_signals (); broker brk(verbose); brk.bind ("tcp://*:5555"); brk.start_brokering(); if (s_interrupted) printf ("W: interrupt received, shutting down...\n"); return 0; }
mdwrk (std::string broker, std::string service, int verbose) { s_version_assert (2, 1); m_broker = broker; m_service = service; m_context = new zmq::context_t (1); m_worker = 0; m_expect_reply = false; m_verbose = verbose; m_heartbeat = 2500; // msecs m_reconnect = 2500; // msecs s_catch_signals (); connect_to_broker (); }
mdcli_t * mdcli_new (char *broker) { mdcli_t *self; assert (broker); s_version_assert (2, 1); self = malloc (sizeof (mdcli_t)); memset (self, 0, sizeof (mdcli_t)); self->broker = strdup (broker); self->context = zmq_init (1); s_connect_to_broker (self); return (self); }
mdcli_t * mdcli_new (char *broker, int verbose) { assert (broker); s_version_assert (2, 1); mdcli_t *self = (mdcli_t *) calloc (1, sizeof (mdcli_t)); self->broker = strdup (broker); self->context = zmq_init (1); self->verbose = verbose; self->timeout = 2500; // msecs s_catch_signals (); s_mdcli_connect_to_broker (self); return self; }
int main (void) { s_version_assert (2, 1); srandom ((unsigned) time (NULL)); void *context = zmq_init (1); void *worker = s_worker_socket (context); // If liveness hits zero, queue is considered disconnected size_t liveness = HEARTBEAT_LIVENESS; size_t interval = INTERVAL_INIT; // Send out heartbeats at regular intervals uint64_t heartbeat_at = s_clock () + HEARTBEAT_INTERVAL; int cycles = 0; while (1) { zmq_pollitem_t items [] = { { worker, 0, ZMQ_POLLIN, 0 } }; zmq_poll (items, 1, HEARTBEAT_INTERVAL * 1000); if (items [0].revents & ZMQ_POLLIN) { // Get message // - 3-part envelope + content -> request // - 1-part "HEARTBEAT" -> heartbeat zmsg_t *msg = zmsg_recv (worker); if (msg_parts (msg) == 3) { // Simulate various problems, after a few cycles cycles++; if (cycles > 3 && randof (5) == 0) { printf ("I: (%s) simulating a crash\n", identity); zmsg_destroy (&msg); break; } else if (cycles > 3 && randof (5) == 0) { printf ("I: (%s) simulating CPU overload\n", identity); sleep (5); } printf ("I: (%s) normal reply - %s\n", identity, zmsg_body (msg)); zmsg_send (&msg, worker); liveness = HEARTBEAT_LIVENESS; sleep (1); // Do some heavy work } else if (msg_parts (msg) == 1 && strcmp (msg_body (msg), "HEARTBEAT") == 0) liveness = HEARTBEAT_LIVENESS; else { printf ("E: (%s) invalid message\n", identity); zmsg_dump (msg); } interval = INTERVAL_INIT; } else if (--liveness == 0) { printf ("W: (%s) heartbeat failure, can't reach queue\n", identity); printf ("W: (%s) reconnecting in %zd msec...\n", identity, interval); s_sleep (interval); if (interval < INTERVAL_MAX) interval *= 2; zmq_close (worker); worker = s_worker_socket (context); liveness = HEARTBEAT_LIVENESS; } // Send heartbeat to queue if it's time if (s_clock () > heartbeat_at) { heartbeat_at = s_clock () + HEARTBEAT_INTERVAL; printf ("I: (%s) worker heartbeat\n", identity); s_send (worker, "HEARTBEAT"); } } zmq_close (worker); zmq_term (context); return 0; }
int main (void) { s_version_assert (2, 1); srand ((unsigned) time (NULL)); zmq::context_t context (1); zmq::socket_t * worker = s_worker_socket (context); // If liveness hits zero, queue is considered disconnected size_t liveness = HEARTBEAT_LIVENESS; size_t interval = INTERVAL_INIT; // Send out heartbeats at regular intervals int64_t heartbeat_at = s_clock () + HEARTBEAT_INTERVAL; int cycles = 0; while (1) { zmq::pollitem_t items [] = { { *worker, 0, ZMQ_POLLIN, 0 } }; zmq::poll (items, 1, HEARTBEAT_INTERVAL * 1000); if (items [0].revents & ZMQ_POLLIN) { // Get message // - 3-part envelope + content -> request // - 1-part "HEARTBEAT" -> heartbeat zmsg msg (*worker); if (msg.parts () == 3) { // Simulate various problems, after a few cycles cycles++; if (cycles > 3 && within (5) == 0) { std::cout << "I: (" << identity << ") simulating a crash" << std::endl; msg.clear (); break; } else { if (cycles > 3 && within (5) == 0) { std::cout << "I: (" << identity << ") simulating CPU overload" << std::endl; s_sleep (5000); } } std::cout << "I: (" << identity << ") normal reply - " << msg.body() << std::endl; msg.send (*worker); liveness = HEARTBEAT_LIVENESS; s_sleep (1000); // Do some heavy work } else { if (msg.parts () == 1 && strcmp (msg.body (), "HEARTBEAT") == 0) { liveness = HEARTBEAT_LIVENESS; } else { std::cout << "E: (" << identity << ") invalid message" << std::endl; msg.dump (); } } interval = INTERVAL_INIT; } else if (--liveness == 0) { std::cout << "W: (" << identity << ") heartbeat failure, can't reach queue" << std::endl; std::cout << "W: (" << identity << ") reconnecting in " << interval << " msec..." << std::endl; s_sleep (interval); if (interval < INTERVAL_MAX) { interval *= 2; } delete worker; worker = s_worker_socket (context); liveness = HEARTBEAT_LIVENESS; } // Send heartbeat to queue if it's time if (s_clock () > heartbeat_at) { heartbeat_at = s_clock () + HEARTBEAT_INTERVAL; std::cout << "I: (" << identity << ") worker heartbeat" << std::endl; s_send (*worker, "HEARTBEAT"); } } delete worker; return 0; }
int main (void) { s_version_assert (4, 0); // Prepare our context and sockets zmq::context_t context(1); zmq::socket_t frontend(context, ZMQ_ROUTER); zmq::socket_t backend (context, ZMQ_ROUTER); frontend.bind("tcp://*:5555"); // For clients backend.bind ("tcp://*:5556"); // For workers // Queue of available workers std::vector<worker_t> queue; // Send out heartbeats at regular intervals int64_t heartbeat_at = s_clock () + HEARTBEAT_INTERVAL; while (1) { zmq::pollitem_t items [] = { { static_cast<void *>(backend), 0, ZMQ_POLLIN, 0 }, { static_cast<void *>(frontend), 0, ZMQ_POLLIN, 0 } }; // Poll frontend only if we have available workers if (queue.size()) { zmq::poll (items, 2, HEARTBEAT_INTERVAL); } else { zmq::poll (items, 1, HEARTBEAT_INTERVAL); } // Handle worker activity on backend if (items [0].revents & ZMQ_POLLIN) { zmsg msg (backend); std::string identity(msg.unwrap ()); // Return reply to client if it's not a control message if (msg.parts () == 1) { if (strcmp (msg.address (), "READY") == 0) { s_worker_delete (queue, identity); s_worker_append (queue, identity); } else { if (strcmp (msg.address (), "HEARTBEAT") == 0) { s_worker_refresh (queue, identity); } else { std::cout << "E: invalid message from " << identity << std::endl; msg.dump (); } } } else { msg.send (frontend); s_worker_append (queue, identity); } } if (items [1].revents & ZMQ_POLLIN) { // Now get next client request, route to next worker zmsg msg (frontend); std::string identity = std::string(s_worker_dequeue (queue)); msg.push_front((char*)identity.c_str()); msg.send (backend); } // Send heartbeats to idle workers if it's time if (s_clock () > heartbeat_at) { for (std::vector<worker_t>::iterator it = queue.begin(); it < queue.end(); it++) { zmsg msg ("HEARTBEAT"); msg.wrap (it->identity.c_str(), NULL); msg.send (backend); } heartbeat_at = s_clock () + HEARTBEAT_INTERVAL; } s_queue_purge(queue); } // We never exit the main loop // But pretend to do the right shutdown anyhow queue.clear(); return 0; }
int main (int argc, char *argv[]) { s_version_assert (2, 1); // Prepare our context and sockets void *context = zmq_init (1); void *frontend = zmq_socket (context, ZMQ_XREP); void *backend = zmq_socket (context, ZMQ_XREP); zmq_bind (frontend, "ipc://frontend.ipc"); zmq_bind (backend, "ipc://backend.ipc"); int client_nbr; for (client_nbr = 0; client_nbr < NBR_CLIENTS; client_nbr++) { pthread_t client; pthread_create (&client, NULL, client_thread, NULL); } int worker_nbr; for (worker_nbr = 0; worker_nbr < NBR_WORKERS; worker_nbr++) { pthread_t worker; pthread_create (&worker, NULL, worker_thread, NULL); } // Logic of LRU loop // - Poll backend always, frontend only if 1+ worker ready // - If worker replies, queue worker as ready and forward reply // to client if necessary // - If client requests, pop next worker and send request to it // Queue of available workers int available_workers = 0; char *worker_queue [10]; while (1) { // Initialize poll set zmq_pollitem_t items [] = { // Always poll for worker activity on backend { backend, 0, ZMQ_POLLIN, 0 }, // Poll front-end only if we have available workers { frontend, 0, ZMQ_POLLIN, 0 } }; if (available_workers) zmq_poll (items, 2, -1); else zmq_poll (items, 1, -1); // Handle worker activity on backend if (items [0].revents & ZMQ_POLLIN) { // Queue worker address for LRU routing char *worker_addr = s_recv (backend); assert (available_workers < NBR_WORKERS); worker_queue [available_workers++] = worker_addr; // Second frame is empty char *empty = s_recv (backend); assert (empty [0] == 0); free (empty); // Third frame is READY or else a client reply address char *client_addr = s_recv (backend); // If client reply, send rest back to frontend if (strcmp (client_addr, "READY") != 0) { empty = s_recv (backend); assert (empty [0] == 0); free (empty); char *reply = s_recv (backend); s_sendmore (frontend, client_addr); s_sendmore (frontend, ""); s_send (frontend, reply); free (reply); if (--client_nbr == 0) break; // Exit after N messages } free (client_addr); } if (items [1].revents & ZMQ_POLLIN) { // Now get next client request, route to LRU worker // Client request is [address][empty][request] char *client_addr = s_recv (frontend); char *empty = s_recv (frontend); assert (empty [0] == 0); free (empty); char *request = s_recv (frontend); s_sendmore (backend, worker_queue [0]); s_sendmore (backend, ""); s_sendmore (backend, client_addr); s_sendmore (backend, ""); s_send (backend, request); free (client_addr); free (request); // Dequeue and drop the next worker address free (worker_queue [0]); DEQUEUE (worker_queue); available_workers--; } } zmq_close (frontend); zmq_close (backend); zmq_term (context); return 0; }