Exemplo n.º 1
0
        static void Main(string[] args)
        {
            if (args == null || args.Length == 0)
            {
                Console.WriteLine();
                Console.WriteLine("Usage: ./{0} PPWorker [Name]", AppDomain.CurrentDomain.FriendlyName);
                Console.WriteLine();
                Console.WriteLine("    Name   Your name. Default: World");
                Console.WriteLine();
                args = new string[] { "World" };
            }
            string name = args[0];

            ZError error;

            using (var context = new ZContext())
            {
                ZSocket worker = null;

                try // using (worker)
                {
                    if (null == (worker = PPWorker_CreateZSocket(context, name, out error)))
                    {
                        if (error == ZError.ETERM)
                        {
                            return; // Interrupted
                        }
                        throw new ZException(error);
                    }

                    // If liveness hits zero, queue is considered disconnected
                    int liveness = Worker.PPP_HEARTBEAT_LIVENESS;
                    int interval = Worker.PPP_INTERVAL_INIT;

                    // Send out heartbeats at regular intervals
                    DateTime heartbeat_at = DateTime.UtcNow + Worker.PPP_HEARTBEAT_INTERVAL;

                    ZMessage incoming;
                    int      cycles = 0;
                    var      poll   = ZPollItem.CreateReceiver();
                    var      rnd    = new Random();

                    while (true)
                    {
                        if (worker.PollIn(poll, out incoming, out error, Worker.PPP_TICK))
                        {
                            // Get message
                            // - 3-part envelope + content -> request
                            // - 1-part HEARTBEAT -> heartbeat
                            using (incoming)
                            {
                                incoming.DumpZmsg("-----------from queue------------");
                                // To test the robustness of the queue implementation we
                                // simulate various typical problems, such as the worker
                                // crashing or running very slowly. We do this after a few
                                // cycles so that the architecture can get up and running
                                // first:
                                if (incoming.Count >= 3)
                                {
                                    Common.ProgramerHelper.Console_WriteZMessage("I: receiving reply", incoming);

                                    cycles++;
                                    if (cycles > 3 && rnd.Next(5) == 0)
                                    {
                                        Console.WriteLine("I: simulating a crash");
                                        return;
                                    }

                                    if (cycles > 3 && rnd.Next(3) == 0)
                                    {
                                        Console.WriteLine("I: simulating CPU overload");
                                        Thread.Sleep(100);
                                    }

                                    Thread.Sleep(1);    // Do some heavy work

                                    Console.WriteLine("I: sending reply");

                                    worker.Send(incoming);

                                    liveness = Worker.PPP_HEARTBEAT_LIVENESS;
                                }
                                // When we get a heartbeat message from the queue, it means the
                                // queue was (recently) alive, so we must reset our liveness
                                // indicator:
                                else if (incoming.Count == 1)
                                {
                                    string identity = incoming[0].ReadString();

                                    if (identity == Worker.PPP_HEARTBEAT)
                                    {
                                        Console.WriteLine("I: receiving heartbeat");
                                        liveness = Worker.PPP_HEARTBEAT_LIVENESS;
                                    }
                                    else
                                    {
                                        ProgramerHelper.Console_WriteZMessage("E: invalid message", incoming);
                                    }
                                }
                                else
                                {
                                    ProgramerHelper.Console_WriteZMessage("E: invalid message", incoming);
                                }
                            }
                            interval = Worker.PPP_INTERVAL_INIT;
                        }
                        else
                        {
                            if (error == ZError.ETERM)
                            {
                                break;  // Interrupted
                            }
                            if (error != ZError.EAGAIN)
                            {
                                throw new ZException(error);
                            }
                        }

                        if (error == ZError.EAGAIN)
                        {
                            // If the queue hasn't sent us heartbeats in a while, destroy the
                            // socket and reconnect. This is the simplest most brutal way of
                            // discarding any messages we might have sent in the meantime:
                            if (--liveness == 0)
                            {
                                Console.WriteLine("W: heartbeat failure, can't reach queue");
                                Console.WriteLine("W: reconnecting in {0} ms", interval);

                                Thread.Sleep(interval);

                                if (interval < Worker.PPP_INTERVAL_MAX)
                                {
                                    interval *= 2;
                                }
                                else
                                {
                                    Console.WriteLine("E: interrupted");
                                    break;
                                }

                                worker.Dispose();
                                if (null == (worker = PPWorker_CreateZSocket(context, name, out error)))
                                {
                                    if (error == ZError.ETERM)
                                    {
                                        break;  // Interrupted
                                    }
                                    throw new ZException(error);
                                }
                                liveness = Worker.PPP_HEARTBEAT_LIVENESS;
                            }
                        }

                        // Send heartbeat to queue if it's time
                        if (DateTime.UtcNow > heartbeat_at)
                        {
                            heartbeat_at = DateTime.UtcNow + Worker.PPP_HEARTBEAT_INTERVAL;

                            Console.WriteLine("I:   sending heartbeat");
                            using (var outgoing = new ZFrame(Worker.PPP_HEARTBEAT))
                            {
                                worker.Send(outgoing);
                            }
                        }
                    }
                }
                finally
                {
                    if (worker != null)
                    {
                        worker.Dispose();
                        worker = null;
                    }
                }
            }
        }
Exemplo n.º 2
0
        static void Main(string[] args)
        {
            using (var context = new ZContext())
                using (var backend = new ZSocket(context, ZSocketType.ROUTER))
                    using (var frontend = new ZSocket(context, ZSocketType.ROUTER))
                    {
                        backend.Bind("tcp://*:5556");
                        frontend.Bind("tcp://*:5555");

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

                        // Send out heartbeats at regular intervals
                        DateTime heartbeat_at = DateTime.UtcNow + Worker.PPP_HEARTBEAT_INTERVAL;

                        // Create a Receiver ZPollItem (ZMQ_POLLIN)
                        var poll = ZPollItem.CreateReceiver();

                        ZError   error;
                        ZMessage incoming;

                        while (true)
                        {
                            // Handle worker activity on backend
                            if (backend.PollIn(poll, out incoming, out error, Worker.PPP_TICK))
                            {
                                using (incoming)
                                {
                                    incoming.DumpZmsg("--------from worker---------");

                                    // Any sign of life from worker means it's ready
                                    ZFrame identity = incoming.Unwrap();
                                    var    worker   = new Worker(identity);
                                    workers.Ready(worker);

                                    // Validate control message, or return reply to client
                                    if (incoming.Count == 1)
                                    {
                                        string message = incoming[0].ReadString();
                                        if (message == Worker.PPP_READY)
                                        {
                                            Console.WriteLine("I:        worker ready ({0})", worker.IdentityString);
                                        }
                                        else if (message == Worker.PPP_HEARTBEAT)
                                        {
                                            Console.WriteLine("I: receiving heartbeat ({0})", worker.IdentityString);
                                        }
                                        else
                                        {
                                            ProgramerHelper.Console_WriteZMessage("E: invalid message from worker", incoming);
                                        }
                                    }
                                    else
                                    {
                                        if (ProgramerHelper.Verbose)
                                        {
                                            ProgramerHelper.Console_WriteZMessage("I: [backend sending to frontend] ({0})", incoming, worker.IdentityString);
                                        }

                                        frontend.Send(incoming);
                                    }
                                }
                            }
                            else
                            {
                                if (error == ZError.ETERM)
                                {
                                    break; // Interrupted
                                }
                                if (error != ZError.EAGAIN)
                                {
                                    throw new ZException(error);
                                }
                            }

                            // Handle client activity on frontend
                            if (workers.Count > 0)
                            {
                                // Poll frontend only if we have available workers
                                if (frontend.PollIn(poll, out incoming, out error, Worker.PPP_TICK))
                                {
                                    // Now get next client request, route to next worker
                                    using (incoming)
                                    {
                                        ZFrame workerIdentity = workers.Next();
                                        incoming.Prepend(workerIdentity);

                                        if (ProgramerHelper.Verbose)
                                        {
                                            ProgramerHelper.Console_WriteZMessage("I: [frontend sending to backend] ({0})", incoming, workerIdentity.ReadString());
                                        }

                                        backend.Send(incoming);
                                    }
                                }
                                else
                                {
                                    if (error == ZError.ETERM)
                                    {
                                        break; // Interrupted
                                    }
                                    if (error != ZError.EAGAIN)
                                    {
                                        throw new ZException(error);
                                    }
                                }
                            }

                            // We handle heartbeating after any socket activity. First, we send
                            // heartbeats to any idle workers if it's time. Then, we purge any
                            // dead workers:
                            if (DateTime.UtcNow > heartbeat_at)
                            {
                                heartbeat_at = DateTime.UtcNow + Worker.PPP_HEARTBEAT_INTERVAL;

                                foreach (Worker worker in workers)
                                {
                                    using (var outgoing = new ZMessage())
                                    {
                                        outgoing.Add(ZFrame.CopyFrom(worker.Identity));
                                        outgoing.Add(new ZFrame(Worker.PPP_HEARTBEAT));

                                        Console.WriteLine("I:   sending heartbeat ({0})", worker.IdentityString);
                                        backend.Send(outgoing);
                                    }
                                }
                            }

                            workers.Purge();
                        }

                        // When we're done, clean up properly
                        foreach (Worker worker in workers)
                        {
                            worker.Dispose();
                        }
                    }
        }