public static void TaskWork2(IDictionary <string, string> dict, string[] args) { // // Task worker - design 2 // Adds pub-sub flow to receive and respond to kill signal // // Author: metadings // // Socket to receive messages on, // Socket to send messages to and // Socket for control input using (var context = ZContext.Create()) using (var receiver = ZSocket.Create(context, ZSocketType.PULL)) using (var sender = ZSocket.Create(context, ZSocketType.PUSH)) using (var controller = ZSocket.Create(context, ZSocketType.SUB)) { receiver.Connect("tcp://127.0.0.1:5557"); sender.Connect("tcp://127.0.0.1:5558"); controller.Connect("tcp://127.0.0.1:5559"); controller.SubscribeAll(); var poll = ZPollItem.CreateReceiver(); ZError error; ZMessage message; while (true) { // Process messages from either socket if (receiver.PollIn(poll, out message, out error, TimeSpan.FromMilliseconds(64))) { int workload = message[0].ReadInt32(); Console.WriteLine("{0}.", workload); // Show progress Thread.Sleep(workload); // Do the work sender.Send(new byte[0], 0, 0); // Send results to sink } // Any waiting controller command acts as 'KILL' if (controller.PollIn(poll, out message, out error, TimeSpan.FromMilliseconds(64))) { break; // Exit loop } } } }
public void PollMany_Single_Timeout() { using (var context = new ZContext()) { using (var socket = new ZSocket(context, ZSocketType.PAIR)) { var sockets = new[] { socket }; var pollItems = new[] { ZPollItem.CreateReceiver() }; ZMessage[] messages = null; ZError error; Assert.IsFalse(sockets.Poll(pollItems, ZPoll.In, ref messages, out error, TimeSpan.Zero)); CollectionAssert.AreEqual(new ZMessage[] { null }, messages); Assert.AreEqual(ZError.EAGAIN, error); } } }
/// <summary> /// 代理2 /// </summary> /// <param name="context"></param> public static void RRBroker(ZContext context) { using (var ctx = new ZContext()) using (var frontend = new ZSocket(ctx, ZSocketType.ROUTER)) using (var backend = new ZSocket(ctx, ZSocketType.DEALER)) { frontend.Bind("tcp://*:5570"); backend.Bind("inproc://backend"); Thread.Sleep(2000); //backend.SendFrame(new ZFrame("hahah")); var poll = ZPollItem.CreateReceiver(); while (true) { if (frontend.PollIn(poll, out var message, out var error, TimeSpan.FromMilliseconds(64))) { backend.Send(message); }
// private static readonly int sizeof_MonitorEventData = Marshal.SizeOf(typeof(ZMonitorEventData)); /// <summary> /// Begins monitoring for state changes, raising the appropriate events as they arrive. /// </summary> /// <remarks>NOTE: This is a blocking method and should be run from another thread.</remarks> protected override void Run() { _socket.Connect(_endpoint); ZError error; ZMessage incoming; var poller = ZPollItem.CreateReceiver(); while (!Cancellor.IsCancellationRequested) { if (!_socket.PollIn(poller, out incoming, out error, PollingInterval)) { if (error == ZError.EAGAIN) { Thread.Sleep(1); continue; } throw new ZException(error); } var eventValue = new ZMonitorEventData(); using (incoming) { if (incoming.Count > 0) { eventValue.Event = (ZMonitorEvents)incoming[0].ReadInt16(); eventValue.EventValue = incoming[0].ReadInt32(); } if (incoming.Count > 1) { eventValue.Address = incoming[1].ReadString(); } } OnMonitor(eventValue); } if (!_socket.Disconnect(_endpoint, out error)) { } // ignore errors }
public void PollOutSingle_Ready() { using (var context = new ZContext()) { using (var socket1 = new ZSocket(context, ZSocketType.PAIR)) { socket1.Bind(DefaultEndpoint); using (var socket2 = new ZSocket(context, ZSocketType.PAIR)) { socket2.Connect(DefaultEndpoint); ZError error; Assert.IsTrue(socket1.PollOut(ZPollItem.CreateSender(), new ZMessage(new[] { new ZFrame(32) }), out error, TimeSpan.Zero)); Assert.IsNull(error); var message = socket2.ReceiveMessage(); Assert.AreEqual(new ZMessage(new[] { new ZFrame(32) }), message); } } } }
public void PollInSingle_CancelByContextClose() { Task task; ZError error = null; using (var context = new ZContext()) { var socket = new ZSocket(context, ZSocketType.PAIR); task = Task.Run(() => { using (socket) { ZMessage message; socket.PollIn(ZPollItem.CreateReceiver(), out message, out error); } }); } Assert.IsTrue(task.Wait(1000)); Assert.AreEqual(ZError.ETERM, error); }
public JupyterMessage Execute(string code) { FlushMessages(); CurrentState = KernelState.busy; SendShell( JupyterMessage.Header.MsgType.execute_request, new JupyterMessage.ExecuteRequestContent { code = code, silent = false, store_history = true, user_expressions = null, allow_stdin = true, stop_on_error = false }, null); var poll = ZPollItem.CreateReceiver(); ZMessage incoming; ZError error; while (CurrentState != KernelState.idle) { if (StdInSocket.PollIn(poll, out incoming, out error, TimeSpan.FromMilliseconds(100))) { ProcessMessage(incoming, error); } if (IoPubSocket.PollIn(poll, out incoming, out error, TimeSpan.FromMilliseconds(100))) { ProcessMessage(incoming, error); } } var replyMessage = ShellSocket.ReceiveMessage(); return(ParseMessage(replyMessage)); }
/// <summary> /// 接收完关闭模式 /// </summary> /// <param name="args"></param> public static void TaskWork2(string[] args) { using (var context = new ZContext()) using (var receiver = new ZSocket(context, ZSocketType.PULL)) using (var sender = new ZSocket(context, ZSocketType.PUSH)) using (var controller = new ZSocket(context, ZSocketType.SUB)) { receiver.Connect("tcp://127.0.0.1:5557"); sender.Connect("tcp://127.0.0.1:5558"); controller.Connect("tcp://127.0.0.1:5559"); controller.SubscribeAll(); var poll = ZPollItem.CreateReceiver(); ZError error; ZMessage message; while (true) { // Process messages from either socket if (receiver.PollIn(poll, out message, out error, TimeSpan.FromMilliseconds(64))) { int workload = message[0].ReadInt32(); Console.WriteLine("{0}.", workload); // Show progress Thread.Sleep(workload); // Do the work sender.Send(new byte[0], 0, 0); // Send results to sink } // Any waiting controller command acts as 'KILL' if (controller.PollIn(poll, out message, out error, TimeSpan.FromMilliseconds(64))) { break; // Exit loop } } } }
public void PollInMany_CancelByContextClose() { Task task; ZError error = null; using (var context = new ZContext()) { var socket = new ZSocket(context, ZSocketType.PAIR); task = Task.Run(() => { using (socket) { var sockets = new[] { socket }; var pollItems = new[] { ZPollItem.CreateReceiver() }; ZMessage[] messages; sockets.PollIn(pollItems, out messages, out error, TimeSpan.Zero); } }); } Assert.IsTrue(task.Wait(1000)); Assert.AreEqual(ZError.ETERM, error); }
/// <summary> /// We need two queues, one for requests from local clients and one for requests from cloud /// clients.One option would be to pull messages off the local and cloud frontends and /// pump these onto their respective queues.But this is kind of pointless, because ØMQ /// sockets are queues already. So let’s use the ØMQ socket buffers as queues. /// /// We use broker identities to route messages between brokers. /// </summary> /// <param name="args"></param> static void Main(string[] args) { var options = new Options(); var parser = new CommandLineParser(new CommandLineParserSettings(Console.Error)); if (!parser.ParseArguments(args, options)) { Environment.Exit(1); } using (var context = new ZContext()) using (ZSocket cloudFrontend = new ZSocket(context, ZSocketType.ROUTER), cloudBackend = new ZSocket(context, ZSocketType.ROUTER)) using (ZSocket localFrontend = new ZSocket(context, ZSocketType.ROUTER), localBackend = new ZSocket(context, ZSocketType.ROUTER)) using (ZSocket stateFrontend = new ZSocket(context, ZSocketType.SUB), stateBackend = new ZSocket(context, ZSocketType.PUB)) using (ZSocket monitorSocket = new ZSocket(context, ZSocketType.PULL)) { var self = options.LocalFrontEndPoint; // Prepare local frontend and backend Console.WriteLine("localFrontend binding {0}", options.LocalFrontEndPoint); localFrontend.Bind(options.LocalFrontEndPoint); Console.WriteLine("localBackend binding {0}", options.LocalBackendPoint); localBackend.Bind(options.LocalBackendPoint); // Bind cloud frontend to endpoint. used to communicate with other broker in cluster cloudFrontend.IdentityString = self; Console.WriteLine("cloudFrontend binding {0}", options.CloudFrontendPoint); cloudFrontend.Bind(options.CloudFrontendPoint); // Connect cloud backend to all peers cloudBackend.IdentityString = self; foreach (var cloudBackendPoint in options.CloudBackendPoints) { Console.WriteLine("I: connecting to cloud frontend at {0}", cloudBackendPoint); cloudBackend.Connect(cloudBackendPoint); } // Bind state backend to endpoint Console.WriteLine("stateBackend binding {0}", options.StateBackendPoint); stateBackend.Bind(options.StateBackendPoint); // Connect state frontend to all peers foreach (var stateFrontendPoint in options.StateFrontendPoints) { Console.WriteLine("I: connecting to state backend at {0}", stateFrontendPoint); stateFrontend.Connect(stateFrontendPoint); } // Prepare monitor socket Console.WriteLine("monitorSocket binding {0}", options.MonitorPoint); monitorSocket.Bind(options.MonitorPoint); // Get user to tell us when we can start... Console.WriteLine("Press ENTER when all brokers are started..."); Console.ReadLine(); // Queue of available workers int local_worker_capacity = 0; int cloud_worker_capacity = 0; var localworkerList = new List <string>(); // .split main loop // The main loop has two parts. First, we poll workers and our two service // sockets (statefe and monitor), in any case. If we have no ready workers, // then there's no point in looking at incoming requests. These can remain // on their internal 0MQ queues: ZError error; ZMessage incoming; TimeSpan?waitTimeSpan; var poll = ZPollItem.CreateReceiver(); while (true) { // Track if capacity changes during this iteration int previous = local_worker_capacity; // If we have no workers, wait indefinitely waitTimeSpan = localworkerList.Count > 0 ? (TimeSpan?)TimeSpan.FromMilliseconds(1000) : null; Console.WriteLine("workers count:{0}, waitTime:{1}", localworkerList.Count, waitTimeSpan); ZMessage msgFromWorker, msgFromCloudBacked; // Poll localBackend if (localBackend.PollIn(poll, out msgFromWorker, out error, waitTimeSpan)) { msgFromWorker.DumpZmsg("--------------------------"); // Handle reply from local worker string identity = msgFromWorker[0].ReadString(); localworkerList.Add(identity); // If it's READY, don't route the message any further string hello = msgFromWorker[2].ReadString(); if (hello == "READY") { using (msgFromWorker) { local_worker_capacity++; Console.WriteLine("Local worker is READY, don't route the ready message"); } msgFromWorker = null; } } else if (error == ZError.EAGAIN && cloudBackend.PollIn(poll, out msgFromCloudBacked, out error, waitTimeSpan)) { //Handle reply from peer broker // We don't use peer broker identity for anything using (msgFromCloudBacked) { string identity = msgFromCloudBacked[0].ReadString(); // string ok = incoming[2].ReadString(); } msgFromCloudBacked = null; } else { if (error == ZError.ETERM) { return; // Interrupted } if (error != ZError.EAGAIN) { throw new ZException(error); } } // Route worker reply to cloud if it's addressed to a broker if (msgFromWorker != null) { Console.WriteLine("Route reply to cloud if it's addressed to a broker"); // Route reply to cloud if it's addressed to a broker string identity = msgFromWorker[0].ReadString(); Console.WriteLine("identity:{0}", identity); foreach (var cloudBackendPoint in options.CloudBackendPoints) { if (identity == cloudBackendPoint) { using (msgFromWorker) cloudFrontend.Send(msgFromWorker); msgFromWorker = null; break; } } } // Route reply to client if we still need to if (msgFromWorker != null) { Console.WriteLine("Send the worker msg to client"); localFrontend.Send(msgFromWorker); } // .split handle state messages // If we have input messages on our statefe or monitor sockets, we // can process these immediately: //using (var stateMsg = stateFrontend.ReceiveMessage()) //{ // var peer = stateMsg[0].ReadString(Encoding.UTF8); // var status = stateMsg[1].ReadInt32(); // cloud_worker_capacity = status; //} //using (var monitorMsg = monitorSocket.ReceiveMessage()) //{ // Console.WriteLine(monitorMsg[0].ReadString(Encoding.UTF8)); //} // .split route client requests // Now route as many clients requests as we can handle. If we have // local capacity, we poll both localfe and cloudfe. If we have cloud // capacity only, we poll just localfe. We route any request locally // if we can, else we route to the cloud. ZMessage localFrontMsg = null; ZMessage cloudFrontMsg = null; while (local_worker_capacity + cloud_worker_capacity > 0) { if (localFrontend.PollIn(poll, out localFrontMsg, out error, new TimeSpan(10 * 1000))) { if (local_worker_capacity > 0) { //zframe_t* frame = (zframe_t*)zlist_pop(workers); //zmsg_wrap(msg, frame); //zmsg_send(&msg, localbe); var worker = localworkerList[0]; localworkerList.RemoveAt(0); //send to client msg to worker, there is no identify localBackend.Send(new ZFrame(worker)); local_worker_capacity--; } } if (local_worker_capacity <= 0) { if (cloudFrontend.PollIn(poll, out cloudFrontMsg, out error, new TimeSpan(10 * 1000))) { // Route to random broker peer var tempRamdom = new Random(options.CloudBackendPoints.Count - 1); var cbIndex = tempRamdom.Next(); cloudBackend.Send(new ZFrame(options.CloudBackendPoints[cbIndex])); //int peer = randof(argc - 2) + 2; //zmsg_pushmem(msg, argv[peer], strlen(argv[peer])); //zmsg_send(&msg, cloudbe); } } if (localFrontMsg == null && cloudFrontMsg == null) { // No work, go back to primary break; } } // .split broadcast capacity // We broadcast capacity messages to other peers; to reduce chatter, // we do this only if our capacity changed. if (local_worker_capacity != previous) { // We stick our own identity onto the envelope var statemsg = new ZMessage(); statemsg.Add(new ZFrame(self)); statemsg.Add(new ZFrame(local_worker_capacity)); // Broadcast new capacity stateBackend.Send(statemsg); } } //end of while true } }
// The main task begins by setting-up its frontend and backend sockets // and then starting its client and worker tasks: public static void Peering2(string[] args) { // First argument is this broker's name // Other arguments are our peers' names // if (args == null || args.Length < 3) { if (args != null && args.Length == 1) { args = new string[] { args[0], "Me", "You" }; } else { Console.WriteLine("Usage: {0} Peering2 Hello Me You", AppDomain.CurrentDomain.FriendlyName); Console.WriteLine(" {0} Peering2 Message You Me", AppDomain.CurrentDomain.FriendlyName); return; } } string message = args[0]; string name = args[1]; Console.WriteLine("I: preparing broker as {0}", name); using (var context = new ZContext()) using (var cloudFrontend = new ZSocket(context, ZSocketType.ROUTER)) using (var cloudBackend = new ZSocket(context, ZSocketType.ROUTER)) using (var localFrontend = new ZSocket(context, ZSocketType.ROUTER)) using (var localBackend = new ZSocket(context, ZSocketType.ROUTER)) { // Bind cloud frontend to endpoint cloudFrontend.IdentityString = name; cloudFrontend.Bind("tcp://127.0.0.1:" + Peering2_GetPort(name) + 0); // Connect cloud backend to all peers cloudBackend.IdentityString = name; for (int i = 2; i < args.Length; ++i) { string peer = args[i]; Console.WriteLine("I: connecting to cloud frontend at {0}", peer); cloudBackend.Connect("tcp://127.0.0.1:" + Peering2_GetPort(peer) + 0); } // Prepare local frontend and backend localFrontend.Bind("tcp://127.0.0.1:" + Peering2_GetPort(name) + 1); localBackend.Bind("tcp://127.0.0.1:" + Peering2_GetPort(name) + 2); // Get user to tell us when we can start... Console.WriteLine("Press ENTER when all brokers are started..."); Console.ReadKey(true); // Start local workers for (int i = 0; i < Peering2_Workers; ++i) { int j = i; new Thread(() => Peering2_WorkerTask(context, j, name)).Start(); } // Start local clients for (int i = 0; i < Peering2_Clients; ++i) { int j = i; new Thread(() => Peering2_ClientTask(context, j, name, message)).Start(); } // Here, we handle the request-reply flow. We're using load-balancing // to poll workers at all times, and clients only when there are one // or more workers available. // Least recently used queue of available workers var workers = new List <string>(); ZError error; ZMessage incoming; TimeSpan?wait; var poll = ZPollItem.CreateReceiver(); while (true) { // If we have no workers, wait indefinitely wait = workers.Count > 0 ? (TimeSpan?)TimeSpan.FromMilliseconds(1000) : null; // Poll localBackend if (localBackend.PollIn(poll, out incoming, out error, wait)) { // Handle reply from local worker string identity = incoming[0].ReadString(); workers.Add(identity); // If it's READY, don't route the message any further string hello = incoming[2].ReadString(); if (hello == "READY") { incoming.Dispose(); incoming = null; } } else if (error == ZError.EAGAIN && cloudBackend.PollIn(poll, out incoming, out error, wait)) { // We don't use peer broker identity for anything // string identity = incoming[0].ReadString(); // string ok = incoming[2].ReadString(); } else { if (error == ZError.ETERM) { return; // Interrupted } if (error != ZError.EAGAIN) { throw new ZException(error); } } if (incoming != null) { // Route reply to cloud if it's addressed to a broker string identity = incoming[0].ReadString(); for (int i = 2; i < args.Length; ++i) { if (identity == args[i]) { using (incoming) cloudFrontend.Send(incoming); incoming = null; break; } } } // Route reply to client if we still need to if (incoming != null) { using (incoming) localFrontend.Send(incoming); incoming = null; } // Now we route as many client requests as we have worker capacity // for. We may reroute requests from our local frontend, but not from // // the cloud frontend. We reroute randomly now, just to test things // out. In the next version, we'll do this properly by calculating // cloud capacity:// var rnd = new Random(); while (workers.Count > 0) { int reroutable = 0; // We'll do peer brokers first, to prevent starvation if (localFrontend.PollIn(poll, out incoming, out error, TimeSpan.FromMilliseconds(64))) { reroutable = 0; } else if (error == ZError.EAGAIN && cloudFrontend.PollIn(poll, out incoming, out error, TimeSpan.FromMilliseconds(64))) { reroutable = 1; } else { if (error == ZError.ETERM) { return; // Interrupted } if (error == ZError.EAGAIN) { break; // No work, go back to backends } throw new ZException(error); } using (incoming) { // If reroutable, send to cloud 25% of the time // Here we'd normally use cloud status information // if (reroutable == 1 && rnd.Next(4) == 0) { // Route to random broker peer int peer = rnd.Next(args.Length - 2) + 2; incoming.ReplaceAt(0, new ZFrame(args[peer])); /* using (var outgoing = new ZMessage()) * { * outgoing.Add(new ZFrame(args[peer])); * outgoing.Add(new ZFrame()); * outgoing.Add(incoming[2]); * * cloudBackend.Send(outgoing); * } /**/ cloudBackend.Send(incoming); } else { // Route to local broker peer string peer = workers[0]; workers.RemoveAt(0); incoming.ReplaceAt(0, new ZFrame(peer)); /* using (var outgoing = new ZMessage()) * { * outgoing.Add(new ZFrame(peer)); * outgoing.Add(new ZFrame()); * outgoing.Add(incoming[2]); * * localBackend.Send(outgoing); * } /**/ localBackend.Send(incoming); } } } } } }
public static void LBBroker(IDictionary <string, string> dict, string[] args) { // This is the main task. It starts the clients and workers, and then // routes requests between the two layers. Workers signal READY when // they start; after that we treat them as ready when they reply with // a response back to a client. The load-balancing data structure is // just a queue of next available workers. // Prepare our context and sockets using (var context = new ZContext()) using (var frontend = new ZSocket(context, ZSocketType.ROUTER)) using (var backend = new ZSocket(context, ZSocketType.ROUTER)) { // Bind frontend.Bind("inproc://frontend"); // Bind backend.Bind("inproc://backend"); int clients = 0; for (; clients < LBBroker_Clients; ++clients) { int j = clients; new Thread(() => LBBroker_Client(context, j)).Start(); } for (int i = 0; i < LBBroker_Workers; ++i) { int j = i; new Thread(() => LBBroker_Worker(context, j)).Start(); } // Here is the main loop for the least-recently-used queue. It has two // sockets; a frontend for clients and a backend for workers. It polls // the backend in all cases, and polls the frontend only when there are // one or more workers ready. This is a neat way to use 0MQ's own queues // to hold messages we're not ready to process yet. When we get a client // reply, we pop the next available worker and send the request to it, // including the originating client identity. When a worker replies, we // requeue that worker and forward the reply to the original client // using the reply envelope. // Queue of available workers var worker_queue = new List <string>(); ZMessage incoming; ZError error; var poll = ZPollItem.CreateReceiver(); while (true) { if (backend.PollIn(poll, out incoming, out error, TimeSpan.FromMilliseconds(64))) { // Handle worker activity on backend // incoming[0] is worker_id string worker_id = incoming[0].ReadString(); // Queue worker identity for load-balancing worker_queue.Add(worker_id); // incoming[1] is empty // incoming[2] is READY or else client_id string client_id = incoming[2].ReadString(); if (client_id != "READY") { // incoming[3] is empty // incoming[4] is reply string reply = incoming[4].ReadString(); using (var outgoing = new ZMessage()) { outgoing.Add(new ZFrame(client_id)); outgoing.Add(new ZFrame()); outgoing.Add(new ZFrame(reply)); // Send frontend.Send(outgoing); } if (--clients == 0) { // break the while (true) when all clients said Hello break; } } } if (worker_queue.Count > 0) { // Poll frontend only if we have available workers if (frontend.PollIn(poll, out incoming, out error, TimeSpan.FromMilliseconds(64))) { // Here is how we handle a client request // incoming[0] is client_id string client_id = incoming[0].ReadString(); // incoming[1] is empty // incoming[2] is request string requestText = incoming[2].ReadString(); using (var outgoing = new ZMessage()) { outgoing.Add(new ZFrame(worker_queue[0])); outgoing.Add(new ZFrame()); outgoing.Add(new ZFrame(client_id)); outgoing.Add(new ZFrame()); outgoing.Add(new ZFrame(requestText)); // Send backend.Send(outgoing); } // Dequeue the next worker identity worker_queue.RemoveAt(0); } } } } }
public static void LPClient(IDictionary <string, string> dict, string[] args) { if (args == null || args.Length < 1) { Console.WriteLine(); Console.WriteLine("Usage: ./{0} LPClient [Name]", AppDomain.CurrentDomain.FriendlyName); Console.WriteLine(); Console.WriteLine(" Name Your name. Default: People"); Console.WriteLine(); args = new string[] { "People" }; } string name = args[0]; using (var context = new ZContext()) { ZSocket requester = null; try { // using (requester) ZError error; if (null == (requester = LPClient_CreateZSocket(context, name, out error))) { if (error == ZError.ETERM) { return; // Interrupted } throw new ZException(error); } int sequence = 0; int retries_left = LPClient_RequestRetries; var poll = ZPollItem.CreateReceiver(); while (retries_left > 0) { // We send a request, then we work to get a reply using (var outgoing = ZFrame.Create(4)) { outgoing.Write(++sequence); if (!requester.Send(outgoing, out error)) { if (error == ZError.ETERM) { return; // Interrupted } throw new ZException(error); } } ZMessage incoming; while (true) { // Here we process a server reply and exit our loop // if the reply is valid. // If we didn't a reply, we close the client socket // and resend the request. We try a number of times // before finally abandoning: // Poll socket for a reply, with timeout if (requester.PollIn(poll, out incoming, out error, LPClient_RequestTimeout)) { using (incoming) { // We got a reply from the server int incoming_sequence = incoming[0].ReadInt32(); if (sequence == incoming_sequence) { Console.WriteLine("I: server replied OK ({0})", incoming_sequence); retries_left = LPClient_RequestRetries; break; } else { Console_WriteZMessage(incoming, "E: malformed reply from server"); } } } else { if (error == ZError.EAGAIN) { if (--retries_left == 0) { Console.WriteLine("E: server seems to be offline, abandoning"); break; } Console.WriteLine("W: no response from server, retrying..."); // Old socket is confused; close it and open a new one requester.Dispose(); if (null == (requester = LPClient_CreateZSocket(context, name, out error))) { if (error == ZError.ETERM) { return; // Interrupted } throw new ZException(error); } Console.WriteLine("I: reconnected"); // Send request again, on new socket using (var outgoing = ZFrame.Create(4)) { outgoing.Write(sequence); if (!requester.Send(outgoing, out error)) { if (error == ZError.ETERM) { return; // Interrupted } throw new ZException(error); } } continue; } if (error == ZError.ETERM) { return; // Interrupted } throw new ZException(error); } } } } finally { if (requester != null) { requester.Dispose(); requester = null; } } } }
public static void Server(ZContext context, String identity, string BrokerAddressforServer, ZSocketType socketType, string AddrForSub) { using (var server = new ZSocket(context, socketType)) { server.Connect(BrokerAddressforServer); server.Identity = Encoding.UTF8.GetBytes(identity); string text = "Confirmed Echo"; ZPollItem poll = ZPollItem.CreateReceiver(); ZError error; ZMessage request2; try { if (socketType == ZSocketType.REP) { using (ZMessage request = server.ReceiveMessage()) { string uid = request[0].ReadString(); string receiverIdentity = request[1].ReadString(); Console.WriteLine("{0} <- {1} : [{2} {3}]", identity, receiverIdentity, uid, "REQ"); Send(server, Encoding.UTF8.GetBytes(identity), text, uid); } } else if (socketType == ZSocketType.PULL) { while (true) { if (server.PollIn(poll, out request2, out error, TimeSpan.FromMilliseconds(1000))) { string uid = request2[1].ReadString(); string receivedIdentity = request2[2].ReadString(); Console.WriteLine("{0} <- {1} : [{2}]", identity, receivedIdentity, uid); } else { ErrorChecker(error); } } } else if (socketType == ZSocketType.SUB) { if (identity == "Server") { server.Subscribe("B"); } if (identity == "Server2") { server.Subscribe("Topic"); } if (identity == "Server3") { server.SubscribeAll(); } while (true) { using (ZMessage request = server.ReceiveMessage()) { string topic = request[0].ReadString(); string uid = request[1].ReadString(); string receivedIdentity = request[2].ReadString(); Console.WriteLine("{0} <- {1} : [{2} {3}]", identity, receivedIdentity, uid, topic); } } } } catch (ZException) { context = new ZContext(); } } }
protected override async Task ExecuteAsync(CancellationToken ct) { var endpoints = clusterConfig.Pools.Select(x => x.Extra.SafeExtensionDataAs <BitcoinPoolConfigExtra>()?.BtStream ?? x.Extra.SafeExtensionDataAs <CryptonotePoolConfigExtra>()?.BtStream) .Where(x => x != null) .DistinctBy(x => $"{x.Url}:{x.SharedEncryptionKey}") .ToArray(); if (!endpoints.Any()) { return; } await Task.Run(() => { var timeout = TimeSpan.FromMilliseconds(1000); var reconnectTimeout = TimeSpan.FromSeconds(300); var relays = endpoints .DistinctBy(x => $"{x.Url}:{x.SharedEncryptionKey}") .ToArray(); logger.Info(() => "Online"); while (!ct.IsCancellationRequested) { // track last message received per endpoint var lastMessageReceived = relays.Select(_ => clock.Now).ToArray(); try { // setup sockets var sockets = relays.Select(SetupSubSocket).ToArray(); using (new CompositeDisposable(sockets)) { var pollItems = sockets.Select(_ => ZPollItem.CreateReceiver()).ToArray(); while (!ct.IsCancellationRequested) { if (sockets.PollIn(pollItems, out var messages, out var error, timeout)) { for (var i = 0; i < messages.Length; i++) { var msg = messages[i]; if (msg != null) { lastMessageReceived[i] = clock.Now; using (msg) { ProcessMessage(msg); } } else if (clock.Now - lastMessageReceived[i] > reconnectTimeout) { // re-create socket sockets[i].Dispose(); sockets[i] = SetupSubSocket(relays[i]); // reset clock lastMessageReceived[i] = clock.Now; logger.Info(() => $"Receive timeout of {reconnectTimeout.TotalSeconds} seconds exceeded. Re-connecting to {relays[i].Url} ..."); } } if (error != null) { logger.Error(() => $"{nameof(ShareReceiver)}: {error.Name} [{error.Name}] during receive"); } } } } } catch (Exception ex) { logger.Error(() => $"{nameof(ShareReceiver)}: {ex}"); if (!ct.IsCancellationRequested) { Thread.Sleep(1000); } } } logger.Info(() => "Offline"); }, ct); }
// // Broker peering simulation (part 1) // Prototypes the state flow // // Author: metadings // public static void Peering1(string[] args) { // First argument is this broker's name // Other arguments are our peers' names // if (args == null || args.Length < 2) { Console.WriteLine(); Console.WriteLine("Usage: {0} Peering1 World Receiver0", AppDomain.CurrentDomain.FriendlyName); Console.WriteLine(" {0} Peering1 Receiver0 World", AppDomain.CurrentDomain.FriendlyName); Console.WriteLine(); return; } string self = args[0]; Console.WriteLine("I: preparing broker as {0}", self); using (var context = new ZContext()) using (var backend = new ZSocket(context, ZSocketType.PUB)) using (var frontend = new ZSocket(context, ZSocketType.SUB)) { // Bind backend to endpoint backend.Bind("tcp://127.0.0.1:" + Peering1_GetPort(self)); // Connect frontend to all peers frontend.SubscribeAll(); for (int i = 1; i < args.Length; ++i) { string peer = args[i]; Console.WriteLine("I: connecting to state backend at {0}", peer); frontend.Connect("tcp://127.0.0.1:" + Peering1_GetPort(peer)); } // The main loop sends out status messages to peers, and collects // status messages back from peers. The zmq_poll timeout defines // our own heartbeat: ZError error; ZMessage incoming; var poll = ZPollItem.CreateReceiver(); var rnd = new Random(); while (true) { // Poll for activity, or 1 second timeout if (!frontend.PollIn(poll, out incoming, out error, TimeSpan.FromSeconds(1))) { if (error == ZError.EAGAIN) { using (var output = new ZMessage()) { output.Add(new ZFrame(self)); var outputNumber = ZFrame.Create(4); outputNumber.Write(rnd.Next(10)); output.Add(outputNumber); backend.Send(output); } continue; } if (error == ZError.ETERM) { return; } throw new ZException(error); } using (incoming) { string peer_name = incoming[0].ReadString(); int available = incoming[1].ReadInt32(); Console.WriteLine("{0} - {1} workers free", peer_name, available); } } } }
static void AsyncSrv_Client(ZContext context, int i) { // // Asynchronous client-to-server (DEALER to ROUTER) // // While this example runs in a single process, that is to make // it easier to start and stop the example. Each task has its own // context and conceptually acts as a separate process. // // Authors: Pieter Hintjens, Uli Riehm // // 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. using (var client = ZSocket.Create(context, ZSocketType.DEALER)) { // Set identity to make tracing easier client.Identity = Encoding.UTF8.GetBytes("CLIENT" + i); // Connect client.Connect("tcp://localhost:5570"); ZError error; ZMessage incoming; var poll = ZPollItem.CreateReceiver(); int requests = 0; while (true) { // Tick once per second, pulling in arriving messages for (int centitick = 0; centitick < 100; ++centitick) { if (!client.PollIn(poll, out incoming, out error, TimeSpan.FromMilliseconds(10))) { if (error == ZError.EAGAIN) { error = ZError.None; continue; } if (error == ZError.ETERM) { return; // Interrupted } throw new ZException(error); } using (incoming) { string messageText = incoming[0].ReadString(); Console.WriteLine("[CLIENT{0}] {1}", i, messageText); } } using (var outgoing = new ZMessage()) { outgoing.Add(new ZFrame(client.Identity)); outgoing.Add(new ZFrame("request " + (++requests))); if (!client.Send(outgoing, out error)) { if (error == ZError.ETERM) { return; // Interrupted } throw new ZException(error); } } } } }
public static void Agent(ZContext context, ZSocket backend, CancellationTokenSource cancellor, object[] args) { // Finally, here's the agent task itself, which polls its two sockets // and processes incoming messages: using (var agent = new Agent(context, backend)) { var p = ZPollItem.CreateReceiver(); while (!cancellor.IsCancellationRequested) { ZMessage msg; ZError error; // Poll the control message if (agent.Pipe.PollIn(p, out msg, out error, TimeSpan.FromMilliseconds(64))) { using (msg) { agent.ControlMessage(msg); } } else { if (error == ZError.ETERM) { break; // Interrupted } if (error != ZError.EAGAIN) { throw new ZException(error); } } // Poll the router message if (agent.Router.PollIn(p, out msg, out error, TimeSpan.FromMilliseconds(64))) { using (msg) { agent.RouterMessage(msg); } } else { if (error == ZError.ETERM) { break; // Interrupted } if (error != ZError.EAGAIN) { throw new ZException(error); } } if (agent.Request != null) { // If we're processing a request, dispatch to next server if (DateTime.UtcNow >= agent.Expires) { // Request expired, kill it using (var outgoing = new ZFrame("FAILED")) { agent.Pipe.Send(outgoing); } agent.Request.Dispose(); agent.Request = null; } else { // Find server to talk to, remove any expired ones foreach (Server server in agent.Actives.ToList()) { if (DateTime.UtcNow >= server.Expires) { agent.Actives.Remove(server); server.Alive = false; } else { // Copy the Request, Push the Endpoint and send on Router using (var request = agent.Request.Duplicate()) { request.Prepend(new ZFrame(server.Endpoint)); agent.Router.Send(request); break; } } } } } // Disconnect and delete any expired servers // Send heartbeats to idle servers if needed foreach (Server server in agent.Servers) { server.Ping(agent.Router); } } } }
public static void PPWorker(IDictionary <string, string> dict, 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) { // 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) { Console_WriteZMessage(incoming, "I: receiving reply"); 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 { Console_WriteZMessage(incoming, "E: invalid message"); } } else { Console_WriteZMessage(incoming, "E: invalid message"); } } 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; } } } }
public virtual async Task <TResponse> SendAsync <TRequest, TResponse>(string name, Packet <TRequest> packet, IpAddress ip, int port, Func <TResponse, TResponse> successFunction = null, Func <object, TResponse> failureFunction = null, Func <object, TResponse> timeoutFunction = null) { // Validation if (packet == null) { throw new ArgumentException("packet", string.Format(Messages.ObjectNull, "packet")); } if (ip == null) { throw new ArgumentException("ip", string.Format(Messages.ObjectNull, "ip")); } if (port < 1024) { throw new ArgumentException("port", Messages.PortNoInRange); } if (successFunction == null) { successFunction = OnSuccess; } if (failureFunction == null) { failureFunction = OnFailure <TResponse>; } if (timeoutFunction == null) { timeoutFunction = OnTimeout <TResponse>; } using (var context = new ZContext()) { ZSocket requester = null; try { var createSocketResult = await GetRequestZSocketAsync(context, name, ip, port); if (createSocketResult.Error != ZError.None) { return(failureFunction.Invoke(createSocketResult.Error)); } requester = createSocketResult.Socket; int retries_left = RequestRetries; var poll = ZPollItem.CreateReceiver(); while (retries_left > 0) { var json = JsonConvert.SerializeObject(packet); var frame = new ZFrame(json); if (!requester.Send(frame, out ZError error)) { if (error != ZError.None) { return(failureFunction.Invoke(error)); } } while (true) { if (requester.PollIn(poll, out ZMessage incomingMessage, out error, RequestTimeout)) { using (incomingMessage) { var responseJson = incomingMessage[0].ReadString(); var responsePacket = JsonConvert.DeserializeObject <Packet <TResponse> >(responseJson); retries_left = RequestRetries; return(successFunction.Invoke(responsePacket.Payload)); } } else { if (error == ZError.EAGAIN) { if (--retries_left == 0) { Console.WriteLine($"Worker did not respond: {ip}:{port}."); break; } ; // Old socket is confused; close it and open a new one requester.Dispose(); createSocketResult = await GetRequestZSocketAsync(context, name, ip, port); if (createSocketResult.Error != ZError.None) { return(failureFunction.Invoke(createSocketResult.Error)); } requester = createSocketResult.Socket; var retryFrame = new ZFrame(json); if (!requester.Send(retryFrame, out error)) { if (error != ZError.None) { return(failureFunction.Invoke(error)); } } continue; } if (error != ZError.None) { return(failureFunction(error)); } } } }
// .split send request and wait for reply // Here is the {{send}} method. It sends a request to the broker and gets // a reply even if it has to retry several times. It takes ownership of // the request message, and destroys it when sent. It returns the reply // message, or NULL if there was no reply after multiple attempts: public ZMessage Send(string service, ZMessage request, CancellationTokenSource cancellor) { if (request == null) { throw new InvalidOperationException(); } // Prefix request with protocol frames // Frame 1: "MDPCxy" (six bytes, MDP/Client x.y) // Frame 2: Service name (printable string) request.Prepend(new ZFrame(service)); request.Prepend(new ZFrame(MdpCommon.MDPC_CLIENT)); if (Verbose) { request.DumpZmsg("I: send request to '{0}' service:", service); } int retriesLeft = Retries; while (retriesLeft > 0 && !cancellor.IsCancellationRequested) { if (cancellor.IsCancellationRequested || (Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Escape)) { _context.Shutdown(); } // Copy the Request and send on Client ZMessage msgreq = request.Duplicate(); ZError error; if (!Client.Send(msgreq, out error)) { if (Equals(error, ZError.ETERM)) { cancellor.Cancel(); break; // Interrupted } } var p = ZPollItem.CreateReceiver(); ZMessage msg; // .split body of send // On any blocking call, {{libzmq}} will return -1 if there was // an error; we could in theory check for different error codes, // but in practice it's OK to assume it was {{EINTR}} (Ctrl-C): // Poll the client Message if (Client.PollIn(p, out msg, out error, Timeout)) { // If we got a reply, process it if (Verbose) { msg.DumpZmsg("I: received reply"); } if (msg.Count < 3) { throw new InvalidOperationException(); } using (ZFrame header = msg.Pop()) if (!header.ToString().Equals(MdpCommon.MDPC_CLIENT)) { throw new InvalidOperationException(); } using (ZFrame replyService = msg.Pop()) if (!replyService.ToString().Equals(service)) { throw new InvalidOperationException(); } request.Dispose(); return(msg); } else if (Equals(error, ZError.ETERM)) { cancellor.Cancel(); break; // Interrupted } else if (Equals(error, ZError.EAGAIN)) { if (--retriesLeft > 0) { if (Verbose) { "W: no reply, reconnecting...".DumpString(); } ConnectToBroker(); } else { if (Verbose) { "W: permanent error, abandoning".DumpString(); } break; // Give up } } } if (cancellor.IsCancellationRequested) { "W: interrupt received, killing client...\n".DumpString(); } request.Dispose(); return(null); }
public static void LVCache(string[] args) { // // Last value cache // Uses XPUB subscription messages to re-send data // // Author: metadings // using (var context = new ZContext()) using (var frontend = new ZSocket(context, ZSocketType.SUB)) using (var backend = new ZSocket(context, ZSocketType.XPUB)) { // Subscribe to every single topic from publisher frontend.Connect("tcp://*:5557"); frontend.SubscribeAll(); backend.Bind("tcp://*:5558"); // Store last instance of each topic in a cache var cache = new HashSet <LVCacheItem>(); // We route topic updates from frontend to backend, and // we handle subscriptions by sending whatever we cached, // if anything: var p = ZPollItem.CreateReceiver(); ZMessage msg; ZError error; while (true) { // Any new topic data we cache and then forward if (frontend.PollIn(p, out msg, out error, TimeSpan.FromMilliseconds(1))) { using (msg) { string topic = msg[0].ReadString(); string current = msg[1].ReadString(); LVCacheItem previous = cache.FirstOrDefault(item => topic == item.Topic); if (previous != null) { cache.Remove(previous); } cache.Add(new LVCacheItem { Topic = topic, Current = current }); backend.Send(msg); } } else { if (error == ZError.ETERM) { break; // Interrupted } if (error != ZError.EAGAIN) { throw new ZException(error); } } // When we get a new subscription, we pull data from the cache: if (backend.PollIn(p, out msg, out error, TimeSpan.FromMilliseconds(1))) { using (msg) { // Event is one byte 0=unsub or 1=sub, followed by topic byte subscribe = msg[0].ReadAsByte(); if (subscribe == 0x01) { string topic = msg[0].ReadString(); LVCacheItem previous = cache.FirstOrDefault(item => topic == item.Topic); if (previous != null) { Console.WriteLine("Sending cached topic {0}", topic); backend.SendMore(new ZFrame(previous.Topic)); backend.Send(new ZFrame(previous.Current)); } else { Console.WriteLine("Failed to send cached topic {0}!", topic); } } } } else { if (error == ZError.ETERM) { break; // Interrupted } if (error != ZError.EAGAIN) { throw new ZException(error); } } } } }
public static void RRBroker(IDictionary <string, string> dict, string[] args) { // // Simple request-reply broker // // Author: metadings // // Prepare our context and sockets using (var context = new ZContext()) using (var frontend = new ZSocket(context, ZSocketType.ROUTER)) using (var backend = new ZSocket(context, ZSocketType.DEALER)) { frontend.Bind("tcp://*:5559"); backend.Bind("tcp://*:5560"); // Initialize poll set var poll = ZPollItem.CreateReceiver(); // Switch messages between sockets ZError error; ZMessage message; while (true) { if (frontend.PollIn(poll, out message, out error, TimeSpan.FromMilliseconds(64))) { using (message) { // Process all parts of the message Console_WriteZMessage(2, message, "frontend"); backend.Send(message); } } else { if (error == ZError.ETERM) { return; // Interrupted } if (error != ZError.EAGAIN) { throw new ZException(error); } } if (backend.PollIn(poll, out message, out error, TimeSpan.FromMilliseconds(64))) { // Process all parts of the message Console_WriteZMessage(2, message, " backend"); frontend.Send(message); } else { if (error == ZError.ETERM) { return; // Interrupted } if (error != ZError.EAGAIN) { throw new ZException(error); } } } } }
private void MainLoop() { ZError error; ZMessage incoming; var poll = ZPollItem.CreateReceiver(); while (true) { //await Task.Delay(1); //yield return null; if (_backendSocket.PollIn(poll, out incoming, out error, TimeSpan.FromMilliseconds(1))) { using (incoming) { // Handle worker activity on backend // incoming[0] is worker_id string workerName = incoming[0].ReadString(); // Queue worker identity for load-balancing workerQueue.Add(workerName); // incoming[1] is empty // incoming[2] is READY or else client_id var client_id = incoming[2]; var clientIdString = client_id.ToString(); if (client_id.ToString() == "READY") { Logger.Warn("I: ({0}) worker ready!!!", workerName); } else { // incoming[3] is empty // incoming[4] is reply // string reply = incoming[4].ReadString(); // int reply = incoming[4].ReadInt32(); Logger.Trace("I: ({0}) work complete", workerName); using (var outgoing = new ZMessage()) { outgoing.Add(client_id); outgoing.Add(new ZFrame()); outgoing.Add(incoming[4]); // Send _responseSocket.Send(outgoing); } } } } else { if (error == ZError.ETERM) { return; } //yield break; if (error != ZError.EAGAIN) { throw new ZException(error); } } if (workerQueue.Count > 0) { // Poll frontend only if we have available workers if (_responseSocket.PollIn(poll, out incoming, out error, TimeSpan.FromMilliseconds(1))) { using (incoming) { // Here is how we handle a client request // Dequeue the next worker identity string workerId = workerQueue[0]; workerQueue.RemoveAt(0); // incoming[0] is client_id var client_id = incoming[0]; var clientIdStr = client_id.ToString(); // incoming[1] is empty // incoming[2] is request // string request = incoming[2].ReadString(); var requestData = incoming[2]; Logger.Trace("I: ({0}) working on ({1}) {2}", workerId, client_id, requestData); using (var outgoing = new ZMessage()) { outgoing.Add(new ZFrame(workerId)); outgoing.Add(new ZFrame()); outgoing.Add(client_id); outgoing.Add(new ZFrame()); outgoing.Add(requestData); // Send _backendSocket.Send(outgoing); } } } else { if (error == ZError.ETERM) { return; } //yield break; if (error != ZError.EAGAIN) { throw new ZException(error); } } } else { //Logger.Warn("no idle worker...."); //AddWorker(); // 不够worker,创建一个 } } }
public static void PPQueue(IDictionary <string, string> dict, string[] args) { using (var context = ZContext.Create()) using (var backend = ZSocket.Create(context, ZSocketType.ROUTER)) using (var frontend = ZSocket.Create(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) { // 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 { Console_WriteZMessage(incoming, "E: invalid message from worker"); } } else { Console_WriteZMessage(incoming, "I: [backend sending to frontend] ({0})", 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); Console_WriteZMessage(incoming, "I: [frontend sending to backend] ({0})", workerIdentity.ReadString()); // Console.WriteLine("I: route to next worker [frontend send to backend] ({0})", 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(); } } }
// Main function. It is capable of invoking new workers, adding and removing clients and transfering requests and replies between them public void Broker() { ZMessage incoming; ZError error; var poll = ZPollItem.CreateReceiver(); while (!_stopLoops) { if (workers_socket.PollIn(poll, out incoming, out error, TimeSpan.FromMilliseconds(64))) { string worker_id = incoming[0].ReadString(); workers.Add(worker_id); string client_id = incoming[2].ReadString(); if (client_id != "READY") { using (var outgoing = new ZMessage()) { var response = Serializer.Deserialize <Response>(incoming[4]); var res = response as ClaimRes; if (res.Ok) { //Console.WriteLine(res.Ok.ToString() + " " + res.Position[0].ToString() + " " + res.Position[1].ToString() + " " + res.UserId.ToString()); playfield[res.Position[0] - 1, res.Position[1] - 1] = res.UserId; } outgoing.Add(incoming[2]); outgoing.Add(new ZFrame()); outgoing.Add(incoming[4]); users_socket.Send(outgoing); requests++; } } } if (workers.Count > 0) { while (toRemove > 0) { toRemove--; var request = new StartReq() { desire = true }; using (var message = new ZMessage()) using (var responseStream = new MemoryStream()) { message.Add(new ZFrame(workers[0])); message.Add(new ZFrame()); message.Add(new ZFrame()); message.Add(new ZFrame()); Serializer.Serialize(responseStream, request); message.Add(new ZFrame(responseStream.ToArray())); workers_socket.Send(message); } while (workers.Count == 0) { Thread.Sleep(10); } } if (users_socket.PollIn(poll, out incoming, out error, TimeSpan.FromMilliseconds(64))) { using (var receivedFrame = incoming[2]) { var request = Serializer.Deserialize <Request>(receivedFrame); //Console.WriteLine(request.RequesType); switch (request.RequesType) { case RequesType.ClaimReq: { using (var outgoing = new ZMessage()) { outgoing.Add(new ZFrame(workers[0])); outgoing.Add(new ZFrame()); outgoing.Add(incoming[0]); outgoing.Add(new ZFrame()); outgoing.Add(incoming[2]); workers_socket.Send(outgoing); } workers.RemoveAt(0); break; } case RequesType.StartReq: { var sr = request as StartReq; //Console.WriteLine(request.RequesType); var response = new StartRes(); response.size = size; if (sr.desire) { if (users.Contains(request.UserId)) { response.Ok = false; } else { response.Ok = true; response.Position = new List <int> { _random.Next(0, size), _random.Next(0, size) }; users.Add(request.UserId); playfield[response.Position[0], response.Position[1]] = request.UserId; requests++; if ((users.Count == 2) || (users.Count / 10 > workerCount)) { Process.Start(workersList[workerCount % workersList.Count], size.ToString() + " " + (++workerCount).ToString() + " " + myAdress); Console.WriteLine("New worker added, id: " + workerCount); } Console.WriteLine("New user added, id: {0}, symbol: {0}", request.UserId); } } else { users.Remove(request.UserId); if (users.Count == 1 || ((users.Count) % 10 == 0 && users.Count > 0)) { toRemove++; } Console.WriteLine("User removed, id: {0}, symbol: {0}", request.UserId); response.Ok = true; for (int i = 0; i < size; ++i) { for (int j = 0; j < size; ++j) { if (playfield[i, j] == request.UserId) { playfield[i, j] = 0; } } } } using (var responseStream = new MemoryStream()) using (var outgoing = new ZMessage()) { Serializer.Serialize(responseStream, response); outgoing.Add(incoming[0]); outgoing.Add(new ZFrame()); outgoing.Add(new ZFrame(responseStream.ToArray())); users_socket.Send(outgoing); } break; } } } } } } }
private void StartMessageReceiver(ZmqPubSubEndpointConfig[] endpoints) { Task.Run(() => { Thread.CurrentThread.Name = "BtStreamReceiver Socket Poller"; var timeout = TimeSpan.FromMilliseconds(1000); var reconnectTimeout = TimeSpan.FromSeconds(300); var relays = endpoints .DistinctBy(x => $"{x.Url}:{x.SharedEncryptionKey}") .ToArray(); while (!cts.IsCancellationRequested) { // track last message received per endpoint var lastMessageReceived = relays.Select(_ => clock.UtcNow).ToArray(); try { // setup sockets var sockets = relays.Select(SetupSubSocket).ToArray(); using (new CompositeDisposable(sockets)) { var pollItems = sockets.Select(_ => ZPollItem.CreateReceiver()).ToArray(); while (!cts.IsCancellationRequested) { if (sockets.PollIn(pollItems, out var messages, out var error, timeout)) { for (var i = 0; i < messages.Length; i++) { var msg = messages[i]; if (msg != null) { lastMessageReceived[i] = clock.UtcNow; using (msg) { ProcessMessage(msg); } } else if (clock.UtcNow - lastMessageReceived[i] > reconnectTimeout) { // re-create socket sockets[i].Dispose(); sockets[i] = SetupSubSocket(relays[i]); // reset clock lastMessageReceived[i] = clock.UtcNow; logger.Info(() => $"Receive timeout of {reconnectTimeout.TotalSeconds} seconds exceeded. Re-connecting to {relays[i].Url} ..."); } } if (error != null) { logger.Error(() => $"{nameof(ShareReceiver)}: {error.Name} [{error.Name}] during receive"); } } } } } catch (Exception ex) { logger.Error(() => $"{nameof(ShareReceiver)}: {ex}"); if (!cts.IsCancellationRequested) { Thread.Sleep(1000); } } } }, cts.Token); }
public ZMessage Request(ZMessage request) { // This method does the hard work. It sends a request to all // connected servers in parallel (for this to work, all connections // must be successful and completed by this time). It then waits // for a single successful reply, and returns that to the caller. // Any other replies are just dropped: ZMessage reply = null; using (request) { // Prefix request with sequence number and empty envelope this.sequence++; request.Prepend(new ZFrame(this.sequence)); request.Prepend(new ZFrame()); // Blast the request to all connected servers for (int server = 0; server < this.servers; ++server) { using (var outgoing = request.Duplicate()) { this.socket.Send(outgoing); } } // Wait for a matching reply to arrive from anywhere // Since we can poll several times, calculate each one ZError error; DateTime endtime = DateTime.UtcNow + GLOBAL_TIMEOUT; var poll = ZPollItem.CreateReceiver(); while (endtime > DateTime.UtcNow) { if (this.socket.PollIn(poll, out reply, out error, endtime - DateTime.UtcNow)) { // Reply is [empty][sequence][OK] if (reply.Count < 3) { throw new InvalidOperationException(); } reply.RemoveAt(0); using (ZFrame sequenceFrame = reply.RemoveAt(0, false)) { int sequence = sequenceFrame.ReadInt32(); if (sequence == this.sequence) { break; // Reply is ok } } reply.Dispose(); } else { if (error == ZError.ETERM) { break; // Interrupted } if (error != ZError.EAGAIN) { throw new ZException(error); } } } } return(reply); }
private ZFrame SendMess(ZFrame frame) { replay = null; ZError error; ZMessage msg = null; using (var requesterMorph = new ZSocket(ZSocketType.REQ)) //using (var requesterDB = new ZSocket(ZSocketType.REQ)) { // Connect requesterMorph.Connect("tcp://127.0.0.1:5559"); //requesterDB.Connect("tcp://127.0.0.1:5560"); var poll = ZPollItem.CreateReceiver(); // Send switch (this.servType) { case ServType.svMorph: requesterMorph.Send(frame); break; case ServType.svSUBD: //requesterDB.Send(frame); break; } // Process messages from both sockets if (requesterMorph.PollIn(poll, out msg, out error, TimeSpan.FromMilliseconds(5000))) //if (requesterMorph.PollIn(poll, out msg, out error)) { // Process task replay = msg[0]; } else { if (error == ZError.ETERM) { return(replay); // Interrupted } if (error != ZError.EAGAIN) { throw new ZException(error); } } /*if (requesterDB.PollIn(poll, out msg, out error, TimeSpan.FromMilliseconds(10000))) * { * // Process task * replay = msg[0]; * } * else * { * if (error == ZError.ETERM) * return replay; // Interrupted * if (error != ZError.EAGAIN) * throw new ZException(error); * }*/ /*/ Receive * using (ZFrame reply = requesterMorph.ReceiveFrame()) * { * reply.Position = 0; * var bufrep = reply.Read(); * //PrintRep(bufrep); * replay = GetRep(bufrep); * }*/ } return(replay); }
static void Main(string[] args) { // // Simple Pirate broker // This is identical to load-balancing pattern, with no reliability // mechanisms. It depends on the client for recovery. Runs forever. // // Author: metadings // using (var context = new ZContext()) using (var frontend = new ZSocket(context, ZSocketType.ROUTER)) using (var backend = new ZSocket(context, ZSocketType.ROUTER)) { frontend.Bind("tcp://*:5555"); backend.Bind("tcp://*:5556"); // Queue of available workers var worker_queue = new List <string>(); ZError error; ZMessage incoming; var poll = ZPollItem.CreateReceiver(); while (true) { if (backend.PollIn(poll, out incoming, out error, TimeSpan.FromMilliseconds(64))) { using (incoming) { incoming.DumpZmsg("-----from worker------"); /* * [2016-09-11T20:13:38:3787670 +08:00] - -----from worker------ * [2016-09-11T20:13:38:3797682 +08:00] - D: [008]:Worker-1 * [2016-09-11T20:13:38:3807673 +08:00] - D: [000]: * [2016-09-11T20:13:38:3807673 +08:00] - D: [004]:MIKE * [2016-09-11T20:13:38:3817685 +08:00] - D: [000]: * [2016-09-11T20:13:38:3817685 +08:00] - D: [004]:02000000 */ // Handle worker activity on backend // incoming[0] is worker_id string worker_id = incoming[0].ReadString(); // Queue worker identity for load-balancing worker_queue.Add(worker_id); // incoming[1] is empty // incoming[2] is READY or else client_id string client_id = incoming[2].ReadString(); if (client_id == "READY") { Console.WriteLine("I: ({0}) worker ready", worker_id); } else { // incoming[3] is empty // incoming[4] is reply // string reply = incoming[4].ReadString(); // int reply = incoming[4].ReadInt32(); Console.WriteLine("I: ({0}) work complete", worker_id); using (var outgoing = new ZMessage()) { // repackaging message outgoing.Add(new ZFrame(client_id)); outgoing.Add(new ZFrame()); outgoing.Add(incoming[4]); // Send to client frontend.Send(outgoing); } } } } else { if (error == ZError.ETERM) { return; } if (error != ZError.EAGAIN) { throw new ZException(error); } } if (worker_queue.Count > 0) { // Poll frontend only if we have available workers if (frontend.PollIn(poll, out incoming, out error, TimeSpan.FromMilliseconds(64))) { using (incoming) { // Here is how we handle a client request // Dequeue the next worker identity string worker_id = worker_queue[0]; worker_queue.RemoveAt(0); incoming.DumpZmsg("-------from client---------"); // incoming[0] is client_id string client_id = incoming[0].ReadString(); // incoming[1] is empty // incoming[2] is request // string request = incoming[2].ReadString(); int request = incoming[2].ReadInt32(); Console.WriteLine("I: ({0}) working on ({1}) {2}", worker_id, client_id, request); using (var outgoing = new ZMessage()) { outgoing.Add(new ZFrame(worker_id)); outgoing.Add(new ZFrame()); outgoing.Add(new ZFrame(client_id)); outgoing.Add(new ZFrame()); outgoing.Add(incoming[2]); // Send backend.Send(outgoing); } } } else { if (error == ZError.ETERM) { return; } if (error != ZError.EAGAIN) { throw new ZException(error); } } } } } }