static void Main(string[] args) { using (var context = new Context(1)) { using (Socket frontend = context.Socket(SocketType.ROUTER), backend = context.Socket(SocketType.ROUTER)) { frontend.Bind("tcp://*:5555"); // For Clients backend.Bind("tcp://*:5556"); // For Workers // 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 var workerQueue = new Queue<byte[]>(); // Handle worker activity on backend backend.PollInHandler += (socket, revents) => { var zmsg = new ZMessage(socket); // Use worker address for LRU routing workerQueue.Enqueue(zmsg.Unwrap()); // Forward message to client if it's not a READY if (!Encoding.Unicode.GetString(zmsg.Address).Equals(LRU_READY)) { zmsg.Send(frontend); } }; frontend.PollInHandler += (socket, revents) => { // Now get next client request, route to next worker // Dequeue and drop the next worker address var zmsg = new ZMessage(socket); zmsg.Wrap(workerQueue.Dequeue(), new byte[0]); zmsg.Send(backend); }; while (true) { int rc = Context.Poller(workerQueue.Count > 0 ? new List<Socket>(new Socket[] {frontend, backend}) : new List<Socket>(new Socket[] {backend})); if (rc == -1) { break; } } } } }
static void Main(string[] args) { using (var context = new Context(1)) { using (var worker = context.Socket(SocketType.REQ)) { var randomizer = new Random(DateTime.Now.Millisecond); var identity = ZHelpers.SetID(worker, Encoding.Unicode); worker.Connect("tcp://localhost:5556"); Console.WriteLine("I: {0} worker ready", identity); worker.Send("READY"); var cycles = 0; while (true) { var zmsg = new ZMessage(worker); cycles += 1; if (cycles > 3 && randomizer.Next(0, 5) == 0) { Console.WriteLine("I: {0} simulating a crash", identity); break; } else if (cycles > 3 && randomizer.Next(0, 5) == 0) { Console.WriteLine("I: {0} simulating CPU overload", identity); System.Threading.Thread.Sleep(3000); } Console.WriteLine("I: {0} normal reply", identity); System.Threading.Thread.Sleep(1000); zmsg.Send(worker); } } } }
public static void Main(string[] args) { var workers = new List<Thread>(); var clients = new List<Thread>(); // Prepare our context and sockets using (var ctx = new Context(1)) { using (Socket frontend = ctx.Socket(SocketType.ROUTER), backend = ctx.Socket(SocketType.ROUTER)) { frontend.Bind("tcp://*:5555"); backend.Bind("tcp://*:5556"); int clientId; for (clientId = 0; clientId < Program.clients; clientId++) { clients.Add(new Thread(ClientTask)); clients[clientId].Start(); } for (int workerId = 0; workerId < Program.workers; workerId++) { workers.Add(new Thread(WorkerTask)); workers[workerId].Start(); } // 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 var workerQueue = new Queue<byte[]>(); // Handle worker activity on backend backend.PollInHandler += (socket, revents) => { var zmsg = new ZMessage(socket); // Use worker address for LRU routing workerQueue.Enqueue(zmsg.Unwrap()); // Forward message to client if it's not a READY if (!Encoding.Unicode.GetString(zmsg.Address).Equals("READY")) { zmsg.Send(frontend); } }; frontend.PollInHandler += (socket, revents) => { // Now get next client request, route to next worker // Dequeue and drop the next worker address var zmsg = new ZMessage(socket); zmsg.Wrap(workerQueue.Dequeue(), new byte[0]); zmsg.Send(backend); }; while (true) { int rc = Context.Poller(workerQueue.Count > 0 ? new List<Socket>(new Socket[] {frontend, backend}) : new List<Socket>(new Socket[] {backend})); if (rc == -1) { break; } } } } }
private static void WorkerTask() { using (var ctx = new Context(1)) { using (var worker = ctx.Socket(SocketType.REQ)) { ZHelpers.SetID(worker, Encoding.Unicode); worker.Connect("tcp://localhost:5556"); // Tell broker we're ready for work worker.Send("READY", Encoding.Unicode); while (true) { var zmsg = new ZMessage(worker); Console.WriteLine("Worker: {0}", Encoding.Unicode.GetString(zmsg.Body)); zmsg.StringToBody("OK"); zmsg.Send(worker); } } } }
static void Main(string[] args) { using (var context = new Context(1)) { int interval = INTERVAL_INIT; int liveness = HEARTBEAT_LIVENESS; while (true) { int cylces = 0; using (Socket worker = ConnectWorker(context)) { worker.PollInHandler += (socket, revents) => { var zmsg = new ZMessage(socket); byte[] identity = zmsg.Unwrap(); switch (Encoding.Unicode.GetString(zmsg.Address)) { case PPP_HEARTBEAT: interval = INTERVAL_INIT; liveness = HEARTBEAT_LIVENESS; break; default: if (zmsg.FrameCount > 1) { if (!doTheWork(cylces++)) { break; } interval = INTERVAL_INIT; liveness = HEARTBEAT_LIVENESS; Console.WriteLine("W: work completed"); zmsg.Send(worker); } else { Console.WriteLine("E: invalied message {0}", identity); } break; }; }; //Send out heartbeats at regular intervals DateTime heartbeat_at = DateTime.Now.AddMilliseconds(HEARTBEAT_INTERVAL); while (true) { List<Socket> pollItems = new List<Socket>(new Socket[] { worker }); Context.Poller(pollItems, HEARTBEAT_INTERVAL * 1000); //If liveness hits zero, queue is considered disconnected if (--liveness <= 0) { Console.WriteLine("W: heartbeat failure, can't reach queue."); Console.WriteLine("W: reconnecting in {0} msecs...", interval); try { Thread.Sleep(interval); } catch (System.Exception ex) { Console.WriteLine(ex.Message); } //Exponential Backoff if (interval < INTERVAL_MAX) interval *= 2; liveness = HEARTBEAT_LIVENESS; //Break the while loop and start the connection over break; } //Send heartbeat to queue if it's time if (DateTime.Now > heartbeat_at) { heartbeat_at = DateTime.Now.AddMilliseconds(HEARTBEAT_INTERVAL); ZMessage zmsg = new ZMessage(PPP_HEARTBEAT); zmsg.Send(worker); } } } } } }
private static void WorkerTask() { using (var ctx = new Context(1)) { using (var worker = ctx.Socket(SocketType.REQ)) { ZHelpers.SetID(worker, Encoding.Unicode); worker.Connect(localBeAddress); var msg = new ZMessage("READY"); msg.Send(worker); while (true) { var recvMsg = new ZMessage(worker); Console.WriteLine("Worker: {0}", recvMsg.BodyToString()); Thread.Sleep(1000); recvMsg.StringToBody("OK"); recvMsg.Send(worker); //var okmsg = new ZMessage("OK"); //okmsg.Send(worker); } } } }
private static void SendReply(ZMessage msg, Socket cloudfe, Socket localfe) { var address = Encoding.Unicode.GetString(msg.Address); // Route reply to cloud if it's addressed to a broker if (peers.Count(peerAddress => peerAddress == address) == 1) { Console.WriteLine("Sending to cloud frontend"); msg.Send(cloudfe); } else { Console.WriteLine("Sending to local frontend"); msg.Send(localfe); } }