Esempio n. 1
0
        //  ---------------------------------------------------------------------
        //  This is our client task
        //  It connects to the server, and then sends a request once per second
        //  It collects responses as they arrive, and it prints them out. We will
        //  run several client tasks in parallel, each with a different random ID.
        static void ClientTask()
        {
            using (Context ctx = new Context(1)) {
                using (Socket client = ctx.Socket(SocketType.XREQ)) {
                    //  Generate printable identity for the client
                    ZHelpers.SetID(client, Encoding.Unicode);
                    string identity = client.IdentityToString(Encoding.Unicode);
                    client.Connect("tcp://localhost:5570");

                    client.PollInHandler += (skt, revents) => {
                        ZMessage zmsg = new ZMessage(skt);
                        Console.WriteLine("{0} : {1}", identity, zmsg.BodyToString());
                    };

                    int requestNbr = 0;
                    while (true) {
                        //  Tick once per second, pulling in arriving messages
                        for (int centitick = 0; centitick < 100; centitick++) {
                            Context.Poller(new List<Socket>(new Socket[] { client }), 10000);
                        }
                        ZMessage zmsg = new ZMessage("");
                        zmsg.StringToBody(String.Format("request: {0}", ++requestNbr));
                        zmsg.Send(client);
                    }
                }
            }
        }
Esempio n. 2
0
        static void Main(string[] args)
        {
            using (var context = ZmqContext.Create())
            {
                using (ZmqSocket frontend = context.CreateSocket(SocketType.ROUTER), backend = context.CreateSocket(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.ReceiveReady += (s, e) =>
                                                 {
                                                     var zmsg = new ZMessage(e.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.ReceiveReady += (s, e) =>
                                                  {
                                                      //  Now get next client request, route to next worker
                                                      //  Dequeue and drop the next worker address
                                                      var zmsg = new ZMessage(e.Socket);
                                                      zmsg.Wrap(workerQueue.Dequeue(), new byte[0]);
                                                      zmsg.Send(backend);
                                                  };

                    var poller = new Poller(new ZmqSocket[] { frontend, backend });

                    while (true)
                    {
                        //int rc = ZmqContext.Poller(workerQueue.Count > 0
                        //                            ? new List<ZmqSocket>(new ZmqSocket[] {frontend, backend})
                        //                            : new List<ZmqSocket>(new ZmqSocket[] {backend}));

                        int rc = poller.Poll();

                        if (rc == -1)
                        {
                            break;
                        }
                    }
                }
            }
        }
Esempio n. 3
0
        //  Accept a request and reply with the same text a random number of
        //  times, with random delays between replies.
        //
        static void ServerWorker(object ctx)
        {
            Random rand = new Random(DateTime.Now.Millisecond);

            using (Socket worker = ((Context)ctx).Socket(SocketType.DEALER)) {
                worker.Connect("inproc://backend");
                while (true)
                {
                    //  The DEALER socket gives us the address envelope and message
                    ZMessage zmsg = new ZMessage(worker);
                    //  Send 0..4 replies back
                    int replies = rand.Next(5);
                    for (int reply = 0; reply < replies; reply++)
                    {
                        Thread.Sleep(rand.Next(1, 1000));
                        zmsg.Send(worker);
                    }
                }
            }
        }
Esempio n. 4
0
        //  Worker using REQ socket to do LRU routing
        //
        static void WorkerTask()
        {
            using (Context ctx = new Context(1)) {
                using (Socket 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)
                    {
                        ZMessage zmsg = new ZMessage(worker);
                        Console.WriteLine("Worker: {0}", Encoding.Unicode.GetString(zmsg.Body));
                        zmsg.StringToBody("OK");
                        zmsg.Send(worker);
                    }
                }
            }
        }
Esempio n. 5
0
        //  ---------------------------------------------------------------------
        //  This is our server task
        //  It uses the multithreaded server model to deal requests out to a pool
        //  of workers and route replies back to clients. One worker can handle
        //  one request at a time but one client can talk to multiple workers at
        //  once.
        private static void ServerTask()
        {
            var workers = new List <Thread>(5);

            using (var context = ZmqContext.Create())
            {
                using (ZmqSocket frontend = context.CreateSocket(SocketType.ROUTER), backend = context.CreateSocket(SocketType.DEALER))
                {
                    frontend.Bind("tcp://*:5570");
                    backend.Bind("inproc://backend");

                    for (int workerNumber = 0; workerNumber < 5; workerNumber++)
                    {
                        workers.Add(new Thread(ServerWorker));
                        workers[workerNumber].Start(context);
                    }

                    //  Switch messages between frontend and backend
                    frontend.ReceiveReady += (s, e) =>
                    {
                        var zmsg = new ZMessage(e.Socket);
                        zmsg.Send(backend);
                    };

                    backend.ReceiveReady += (s, e) =>
                    {
                        var zmsg = new ZMessage(e.Socket);
                        zmsg.Send(frontend);
                    };

                    var poller = new Poller(new List <ZmqSocket> {
                        frontend, backend
                    });

                    while (true)
                    {
                        poller.Poll();
                    }
                }
            }
        }
Esempio n. 6
0
        //  ---------------------------------------------------------------------
        //  This is our server task
        //  It uses the multithreaded server model to deal requests out to a pool
        //  of workers and route replies back to clients. One worker can handle
        //  one request at a time but one client can talk to multiple workers at
        //  once.
        private static void ServerTask()
        {
            var workers = new List <Thread>(5);

            using (var context = new Context(1))
            {
                using (Socket frontend = context.Socket(SocketType.ROUTER), backend = context.Socket(SocketType.DEALER))
                {
                    frontend.Bind("tcp://*:5570");
                    backend.Bind("inproc://backend");

                    for (int workerNumber = 0; workerNumber < 5; workerNumber++)
                    {
                        workers.Add(new Thread(ServerWorker));
                        workers[workerNumber].Start(context);
                    }

                    //  Switch messages between frontend and backend
                    frontend.PollInHandler += (socket, revents) =>
                    {
                        var zmsg = new ZMessage(socket);
                        zmsg.Send(backend);
                    };

                    backend.PollInHandler += (socket, revents) =>
                    {
                        var zmsg = new ZMessage(socket);
                        zmsg.Send(frontend);
                    };

                    var sockets = new List <Socket> {
                        frontend, backend
                    };

                    while (true)
                    {
                        Context.Poller(sockets);
                    }
                }
            }
        }
Esempio n. 7
0
        static void Main(string[] args)
        {
            using (var context = ZmqContext.Create())
            {
                using (var worker = context.CreateSocket(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", Encoding.Unicode);

                    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);
                    }
                }
            }
        }
Esempio n. 8
0
        //  ---------------------------------------------------------------------
        //  This is our client task
        //  It connects to the server, and then sends a request once per second
        //  It collects responses as they arrive, and it prints them out. We will
        //  run several client tasks in parallel, each with a different random ID.
        public static void ClientTask()
        {
            using (var context = ZmqContext.Create())
            {
                using (ZmqSocket client = context.CreateSocket(SocketType.DEALER))
                {
                    //  Generate printable identity for the client
                    string identity = ZHelpers.SetID(client, Encoding.Unicode);
                    client.Connect("tcp://localhost:5570");

                    client.ReceiveReady += (s, e) =>
                    {
                        var zmsg = new ZMessage(e.Socket);
                        Console.WriteLine("{0} : {1}", identity, zmsg.BodyToString());
                    };

                    int requestNumber = 0;

                    var poller = new Poller(new List <ZmqSocket> {
                        client
                    });

                    while (true)
                    {
                        //  Tick once per second, pulling in arriving messages
                        for (int centitick = 0; centitick < 100; centitick++)
                        {
                            poller.Poll(TimeSpan.FromMilliseconds(10));
                        }
                        var zmsg = new ZMessage("");
                        zmsg.StringToBody(String.Format("request: {0}", ++requestNumber));
                        zmsg.Send(client);
                    }
                }
            }
        }
Esempio n. 9
0
        //  Worker using REQ socket to do LRU routing
        //
        static void WorkerTask()
        {
            using (Context ctx = new Context(1)) {
                using (Socket 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) {
                        ZMessage zmsg = new ZMessage(worker);
                        Console.WriteLine("Worker: {0}", Encoding.Unicode.GetString(zmsg.Body));
                        zmsg.StringToBody("OK");
                        zmsg.Send(worker);
                    }
                }
            }
        }
Esempio n. 10
0
        //  ---------------------------------------------------------------------
        //  This is our server task
        //  It uses the multithreaded server model to deal requests out to a pool
        //  of workers and route replies back to clients. One worker can handle
        //  one request at a time but one client can talk to multiple workers at
        //  once.
        static void ServerTask()
        {
            List<Thread> workers = new List<Thread>(5);
            using (Context ctx = new Context(1)) {
                using (Socket frontend = ctx.Socket(SocketType.XREP),
                    backend = ctx.Socket(SocketType.XREQ)) {
                    //  Frontend socket talks to clients over TCP
                    frontend.Bind("tcp://*:5570");
                    //  Backend socket talks to workers over inproc
                    backend.Bind("inproc://backend");

                    //  Launch pool of worker threads, precise number is not critical
                    for (int threadNbr = 0; threadNbr < 5; threadNbr++) {
                        workers.Add(new Thread(ServerWorker));
                        workers[threadNbr].Start(ctx);
                    }

                    //  Connect backend to frontend via a queue device
                    //  We could do this:
                    //      zmq_device (ZMQ_QUEUE, frontend, backend);
                    //  But doing it ourselves means we can debug this more easily

                    //  Switch messages between frontend and backend
                    frontend.PollInHandler += (skt, revents) => {
                        ZMessage zmsg = new ZMessage(skt);
                        zmsg.Send(backend);
                    };

                    backend.PollInHandler += (skt, revents) => {
                        ZMessage zmsg = new ZMessage(skt);
                        zmsg.Send(frontend);
                    };
                    List<Socket> sockets = new List<Socket>();
                    sockets.Add(frontend);
                    sockets.Add(backend);
                    while(true){
                        Context.Poller(sockets);
                    }
                }
            }
        }
Esempio n. 11
0
        private static void WorkerTask()
        {
            using (var ctx = ZmqContext.Create())
            {
                using (var worker = ctx.CreateSocket(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);
                    }
                }
            }
        }
Esempio n. 12
0
 //  Accept a request and reply with the same text a random number of
 //  times, with random delays between replies.
 //
 static void ServerWorker(object ctx)
 {
     Random rand = new Random(DateTime.Now.Millisecond);
     using (Socket worker = ((Context)ctx).Socket(SocketType.XREQ)) {
         worker.Connect("inproc://backend");
         while (true) {
             //  The XREQ socket gives us the address envelope and message
             ZMessage zmsg = new ZMessage(worker);
             //  Send 0..4 replies back
             int replies = rand.Next(5);
             for (int reply = 0; reply < replies; reply++) {
                 Thread.Sleep(rand.Next(1, 1000));
                 zmsg.Send(worker);
             }
         }
     }
 }
Esempio n. 13
0
        //  ---------------------------------------------------------------------
        //  This is our server task
        //  It uses the multithreaded server model to deal requests out to a pool
        //  of workers and route replies back to clients. One worker can handle
        //  one request at a time but one client can talk to multiple workers at
        //  once.
        private static void ServerTask()
        {
            var workers = new List <Thread>(5);

            using (var context = ZmqContext.Create())
            {
                using (ZmqSocket frontend = context.CreateSocket(SocketType.ROUTER), backend = context.CreateSocket(SocketType.DEALER))
                {
                    frontend.Bind("tcp://*:5570");
                    backend.Bind("inproc://backend");

                    for (int workerNumber = 0; workerNumber < 5; workerNumber++)
                    {
                        workers.Add(new Thread(ServerWorker));
                        workers[workerNumber].Start(context);
                    }

                    //  Switch messages between frontend and backend
                    frontend.ReceiveReady += (s, e) =>
                    {
                        var zmsg = new ZMessage(e.Socket);
                        zmsg.Send(backend);
                    };

                    backend.ReceiveReady += (s, e) =>
                    {
                        var         zmsg = new ZMessage(e.Socket);
                        string      lol  = zmsg.BodyToString();
                        JSONMessage m    = JsonConvert.DeserializeObject <JSONMessage>(lol);
                        if (m.Function != null)
                        {
                            switch (m.Function)
                            {
                            case "RegisterService":
                                Console.WriteLine("RegisterService");
                                m.ReponseString = "OK";
                                Repository.RegisterService(m.Parameters[0], m.Parameters[1]);
                                break;

                            case "GetServiceLocation":
                                Console.WriteLine("GetServiceLocation");
                                string locat = Repository.GetServiceLocation(m.Parameters[0]);
                                m.ReponseString = locat;
                                break;

                            case "Alive":
                                Console.WriteLine("Alive");
                                Repository.Alive(m.Parameters[0]);
                                m.ReponseString = "OK";
                                break;

                            case "Unregister":
                                Console.WriteLine("Unregister");
                                Repository.Unregister(m.Parameters[0]);
                                m.ReponseString = "OK";
                                break;

                            default:
                                Console.WriteLine("Unknown: " + m.Function);
                                break;
                            }
                        }
                        string json = JsonConvert.SerializeObject(m);
                        zmsg.StringToBody(json);
                        zmsg.Send(frontend);
                    };

                    var poller = new Poller(new List <ZmqSocket> {
                        frontend, backend
                    });

                    while (true)
                    {
                        poller.Poll();
                    }
                }
            }
        }
Esempio n. 14
0
        private static void SendReply(ZMessage msg, ZmqSocket cloudfe, ZmqSocket 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);
            }
        }
Esempio n. 15
0
        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);
                            }
                        }
                    }
                }
            }
        }
Esempio n. 16
0
        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;
                        }
                    }
                }
            }
        }
Esempio n. 17
0
        static void Main(string[] args)
        {
            List <Thread> workers = new List <Thread>();
            List <Thread> clients = new List <Thread>();

            //  Prepare our context and sockets
            using (Context 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 clientNbr;
                    for (clientNbr = 0; clientNbr < NBR_CLIENTS; clientNbr++)
                    {
                        clients.Add(new Thread(ClientTask));
                        clients[clientNbr].Start();
                    }

                    for (int workerNbr = 0; workerNbr < NBR_WORKERS; workerNbr++)
                    {
                        workers.Add(new Thread(WorkerTask));
                        workers[workerNbr].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
                    Queue <byte[]> workerQueue = new Queue <byte[]>();

                    //  Handle worker activity on backend
                    backend.PollInHandler += (skt, revents) => {
                        ZMessage zmsg = new ZMessage(skt);
                        //  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);
                            clientNbr--; //  Exit after N messages
                        }
                    };
                    frontend.PollInHandler += (skt, revents) => {
                        //  Now get next client request, route to next worker
                        //  Dequeue and drop the next worker address
                        ZMessage zmsg = new ZMessage(skt);
                        zmsg.Wrap(workerQueue.Dequeue(), new byte[0]);
                        zmsg.Send(backend);
                    };


                    while (clientNbr > 0)   //  Exit after N messages
                    {
                        if (workerQueue.Count > 0)
                        {
                            Context.Poller(new List <Socket>(new Socket[] { frontend, backend }));
                        }
                        else
                        {
                            Context.Poller(new List <Socket>(new Socket[] { backend }));
                        }
                    }
                }
            }
        }
Esempio n. 18
0
        static void Main(string[] args)
        {
            List<Thread> workers = new List<Thread>();
            List<Thread> clients = new List<Thread>();

            //  Prepare our context and sockets
            using (Context ctx = new Context(1)) {
                using (Socket frontend = ctx.Socket(SocketType.XREP),
                    backend = ctx.Socket(SocketType.XREP)) {

                    frontend.Bind("tcp://*:5555");
                    backend.Bind("tcp://*:5556");

                    int clientNbr;
                    for (clientNbr = 0; clientNbr < NBR_CLIENTS; clientNbr++) {
                        clients.Add(new Thread(ClientTask));
                        clients[clientNbr].Start();
                    }

                    for (int workerNbr = 0; workerNbr < NBR_WORKERS; workerNbr++) {
                        workers.Add(new Thread(WorkerTask));
                        workers[workerNbr].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
                    Queue<byte[]> workerQueue = new Queue<byte[]>();

                    //  Handle worker activity on backend
                    backend.PollInHandler += (skt, revents) => {
                        ZMessage zmsg = new ZMessage(skt);
                        //  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);
                            clientNbr--; //  Exit after N messages
                        }
                    };
                    frontend.PollInHandler += (skt, revents) => {
                        //  Now get next client request, route to next worker
                        //  Dequeue and drop the next worker address
                        ZMessage zmsg = new ZMessage(skt);
                        zmsg.Wrap(workerQueue.Dequeue(), new byte[0]);
                        zmsg.Send(backend);
                    };

                    while (clientNbr > 0) { //  Exit after N messages
                        if (workerQueue.Count > 0) {
                            Context.Poller(new List<Socket>(new Socket[] { frontend, backend }));
                        } else {
                            Context.Poller(new List<Socket>(new Socket[] { backend }));
                        }
                    }
                }
            }
        }
Esempio n. 19
0
        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

                    //  Queue of available workers
                    var workerQueue = new List <Worker>();

                    backend.PollInHandler += (socket, revents) =>
                    {
                        var zmsg = new ZMessage(socket);

                        byte[] identity = zmsg.Unwrap();

                        //Any sign of life from worker means it's ready, Only add it to the queue if it's not in there already
                        Worker worker = null;

                        if (workerQueue.Count > 0)
                        {
                            var workers = workerQueue.Where(x => x.address.SequenceEqual(identity));

                            if (workers.Count() > 0)
                            {
                                worker = workers.Single();
                            }
                        }

                        if (worker == null)
                        {
                            workerQueue.Add(new Worker(identity));
                        }

                        //Return reply to client if it's not a control message
                        switch (Encoding.Unicode.GetString(zmsg.Address))
                        {
                        case PPP_READY:
                            Console.WriteLine("Worker " + Encoding.Unicode.GetString(identity) + " is ready...");
                            break;

                        case PPP_HEARTBEAT:
                            bool found = false;

                            //Worker Refresh
                            if (worker != null)
                            {
                                found = true;
                                worker.ResetExpiry();
                            }

                            if (!found)
                            {
                                Console.WriteLine("E: worker " + Encoding.Unicode.GetString(identity) + " not ready...");
                            }
                            break;

                        default:
                            zmsg.Send(frontend);
                            break;
                        }
                        ;
                    };

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

                        Worker w = workerQueue[0];
                        zmsg.Wrap(w.address, new byte[0]);
                        workerQueue.RemoveAt(0);

                        zmsg.Send(backend);
                    };

                    DateTime heartbeat_at = DateTime.Now.AddMilliseconds(HEARTBEAT_INTERVAL);

                    while (true)
                    {
                        //Only poll frontend only if there are workers ready
                        if (workerQueue.Count > 0)
                        {
                            List <Socket> pollItems = new List <Socket>(new Socket[] { frontend, backend });
                            Context.Poller(pollItems, HEARTBEAT_INTERVAL * 1000);
                        }
                        else
                        {
                            List <ZMQ.Socket> pollItems = new List <Socket>(new Socket[] { backend });
                            Context.Poller(pollItems, HEARTBEAT_INTERVAL * 1000);
                        }

                        //Send heartbeats to idle workers if it's time
                        if (DateTime.Now >= heartbeat_at)
                        {
                            foreach (var worker in workerQueue)
                            {
                                ZMessage zmsg = new ZMessage(PPP_HEARTBEAT);
                                zmsg.Wrap(worker.address, new byte[0]);
                                zmsg.Send(backend);
                            }

                            heartbeat_at = DateTime.Now.AddMilliseconds(HEARTBEAT_INTERVAL);
                        }
                    }
                }
            }
        }
Esempio n. 20
0
        static void Main(string[] args)
        {
            using (var context = ZmqContext.Create())
            {
                using (ZmqSocket frontend = context.CreateSocket(SocketType.ROUTER), backend = context.CreateSocket(SocketType.ROUTER))
                {
                    frontend.Bind("tcp://*:5555"); // For Clients
                    backend.Bind("tcp://*:5556"); // For Workers

                    //  Queue of available workers
                    var workerQueue = new List<Worker>();

                    backend.ReceiveReady += (socket, e) =>
                    {
                        var zmsg = new ZMessage(e.Socket);

                        byte[] identity = zmsg.Unwrap();

                        //Any sign of life from worker means it's ready, Only add it to the queue if it's not in there already
                        Worker worker = null;

                        if (workerQueue.Count > 0)
                        {
                            var workers = workerQueue.Where(x => x.address.SequenceEqual(identity));

                            if (workers.Any())
                                worker = workers.Single();
                        }

                        if (worker == null)
                        {
                            workerQueue.Add(new Worker(identity));
                        }

                        //Return reply to client if it's not a control message
                        switch (Encoding.Unicode.GetString(zmsg.Address))
                        {
                            case PPP_READY:
                                Console.WriteLine("Worker " + Encoding.Unicode.GetString(identity) + " is ready...");
                                break;
                            case PPP_HEARTBEAT:
                                bool found = false;

                                //Worker Refresh
                                if (worker != null)
                                {
                                    found = true;
                                    worker.ResetExpiry();
                                }

                                if (!found)
                                {
                                    Console.WriteLine("E: worker " + Encoding.Unicode.GetString(identity) + " not ready...");
                                }
                                break;
                            default:
                                zmsg.Send(frontend);
                                break;
                        };
                    };

                    frontend.ReceiveReady += (socket, e) =>
                    {
                        //  Now get next client request, route to next worker
                        //  Dequeue and drop the next worker address
                        var zmsg = new ZMessage(e.Socket);

                        Worker w = workerQueue[0];
                        zmsg.Wrap(w.address, new byte[0]);
                        workerQueue.RemoveAt(0);
                        
                        zmsg.Send(backend);
                    };

                    var poller = new Poller(new List<ZmqSocket> { frontend, backend });

                    DateTime heartbeat_at = DateTime.Now.AddMilliseconds(HEARTBEAT_INTERVAL);

                    while (true)
                    {
                        //Only poll frontend only if there are workers ready
                        if (workerQueue.Count > 0)
                        {
                            //List<ZmqSocket> pollItems = new List<ZmqSocket>(new ZmqSocket[] { frontend, backend });
                            poller.Poll(TimeSpan.FromMilliseconds(HEARTBEAT_INTERVAL * 1000));
                        }
                        else
                        {
                            //List<ZmqSocket> pollItems = new List<ZmqSocket>(new ZmqSocket[] { backend });
                            poller.Poll(TimeSpan.FromMilliseconds(HEARTBEAT_INTERVAL * 1000));
                        }

                        //Send heartbeats to idle workers if it's time
                        if (DateTime.Now >= heartbeat_at)
                        {
                            foreach (var worker in workerQueue)
                            {
                                ZMessage zmsg = new ZMessage(PPP_HEARTBEAT);
                                zmsg.Wrap(worker.address, new byte[0]);
                                zmsg.Send(backend);
                            }

                            heartbeat_at = DateTime.Now.AddMilliseconds(HEARTBEAT_INTERVAL);
                        }
                    }
                }
            }
        }