Example #1
0
        public void ReconnectOnRouterBug()
        {
            {
                using (var dealer = new DealerSocket())
                {
                    dealer.Options.Identity = Encoding.ASCII.GetBytes("dealer");
                    dealer.Bind("tcp://localhost:6667");

                    using (var router = new RouterSocket())
                    {
                        router.Options.RouterMandatory = true;
                        router.Connect("tcp://localhost:6667");
                        Thread.Sleep(100);

                        router.SendMoreFrame("dealer").SendFrame("Hello");
                        var message = dealer.ReceiveFrameString();
                        Assert.That(message == "Hello");

                        router.Disconnect("tcp://localhost:6667");
                        Thread.Sleep(1000);
                        router.Connect("tcp://localhost:6667");
                        Thread.Sleep(100);

                        router.SendMoreFrame("dealer").SendFrame("Hello");
                        message = dealer.ReceiveFrameString();
                        Assert.That(message == "Hello");
                    }
                }
            }
        }
Example #2
0
        /// <summary>
        /// Shut down the service and clean up resources.
        /// </summary>
        new public void Stop()
        {
            if (IsRunning)
            {
                try
                {
                    _routerSocket.Disconnect(_facadeAddress);
                    _routerSocket.Dispose();

                    base.Stop();
                }
                finally
                {
                    IsRunning = false;
                    NetMQConfig.Cleanup();
                }
            }
        }
        private async Task BackendHandler()
        {
            while (this.IsRunning)
            {
                try
                {
                    while (this.RegisteredBackendIdentifiers.TryDequeue(out string identifier))
                    {
                    }

                    bool isListening      = false;
                    var  connectionString = this.BackendEndpoint.ToConnectionString();

                    using (var backendSocket = new RouterSocket())
                        using (this.AltBackendBuffer = new NetMQQueue <TransportMessage>())
                            using (var poller = new NetMQPoller()
                            {
                                backendSocket, this.AltBackendBuffer
                            })
                                using (var monitor = new NetMQ.Monitoring.NetMQMonitor(backendSocket, $"inproc://monitor.routerdevice.backend.{Guid.NewGuid().ToString()}", SocketEvents.Listening | SocketEvents.Disconnected | SocketEvents.Closed | SocketEvents.BindFailed))
                                {
                                    backendSocket.ReceiveReady += (sender, e) =>
                                    {
                                        try
                                        {
                                            //Console.WriteLine("Backend message received");
                                            //Console.WriteLine($"RECEIVED BACKEND ({this.BackendSocket.HasIn}) ({this.BackendSocket.HasOut})");

                                            var netmqMessage = new NetMQMessage();
                                            while (e.Socket.TryReceiveMultipartMessage(ref netmqMessage))
                                            {
                                                var message = netmqMessage.ToMessage(out var envelope);

                                                this.OnBackendReceived(message);

                                                //this.BackendBuffer.Enqueue(message);

                                                if (message.Metadata.TryPluck("Greeting", out var encodedGreeting))
                                                {
                                                    var identifier = BitConverter.ToString(envelope);

                                                    if (this.RegisteredBackends.TryAdd(identifier, new RegisteredBackend(envelope, DateTime.UtcNow)))
                                                    {
                                                        Console.WriteLine($"Backend registered [ {identifier} ]");
                                                        this.RegisteredBackendIdentifiers.Enqueue(identifier);
                                                    }
                                                    else
                                                    {
                                                        this.RegisteredBackends[identifier].RegsiteredDate = DateTime.UtcNow;
                                                    }
                                                }
                                                else
                                                {
                                                    this.AltFrontendBuffer.Enqueue(message);
                                                }
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            Console.WriteLine(ex.Message + ": " + ex.StackTrace);
                                        }
                                    };

                                    //var lastFlushed = DateTime.UtcNow;
                                    //backendSocket.SendReady += (sender, e) =>
                                    //{
                                    //    try
                                    //    {
                                    //        if (!this.FrontendBuffer.IsEmpty)
                                    //        {
                                    //            while (this.FrontendBuffer.TryDequeue(out Message message))
                                    //            {
                                    //                Console.WriteLine("Frontend forwarding");

                                    //                if (!e.Socket.TrySendMultipartMessage(TimeSpan.FromSeconds(1), message.ToNetMQMessage(true)))
                                    //                {
                                    //                    Console.WriteLine("Failed to forward to backend");

                                    //                    //var forwardedMessage = new Message(1, message.Frames, System.Text.Encoding.UTF8.GetBytes("Failed to forward to backend"), sourceEnvelope);
                                    //                    //this.FrontendSocket.SendMultipartMessage(forwardedMessage.ToNetMQMessage(true));
                                    //                }
                                    //            }

                                    //            lastFlushed = DateTime.UtcNow;
                                    //        }

                                    //        if ((DateTime.UtcNow - lastFlushed).TotalSeconds > 1)
                                    //            Task.Delay(1).Wait();
                                    //    }
                                    //    catch (Exception ex)
                                    //    {
                                    //        Console.WriteLine(ex.Message + ": " + ex.StackTrace);
                                    //    }
                                    //};
                                    this.AltBackendBuffer.ReceiveReady += (sender, e) =>
                                    {
                                        try
                                        {
                                            while (this.AltBackendBuffer.TryDequeue(out TransportMessage message, TimeSpan.Zero))
                                            {
                                                if (!message.Metadata.TryPluck($"backendEnvelope[{this.Identity}]", out var envelope))
                                                {
                                                    throw new Exception("Message backend envelope not found");
                                                }

                                                this.OnFrontendForwarded(message);

                                                if (!backendSocket.TrySendMultipartMessage(TimeSpan.FromSeconds(1), message.ToNetMQMessage(envelope)))
                                                {
                                                    Console.WriteLine("Failed to forward to backend");

                                                    //var forwardedMessage = new Message(1, message.Frames, System.Text.Encoding.UTF8.GetBytes("Failed to forward to backend"), sourceEnvelope);
                                                    //this.FrontendSocket.SendMultipartMessage(forwardedMessage.ToNetMQMessage(true));
                                                }
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            Console.WriteLine(ex.Message + ": " + ex.StackTrace);
                                        }
                                    };

                                    monitor.Listening += (sender, e) =>
                                    {
                                        Console.WriteLine($"Backend router socket listening at {connectionString}");
                                        isListening = true;
                                    };
                                    monitor.Closed += (sender, e) =>
                                    {
                                        Console.WriteLine($"Backend router socket accepted connection on {connectionString}");
                                        isListening = false;
                                    };
                                    monitor.Disconnected += (sender, e) =>
                                    {
                                        Console.WriteLine($"Backend router socket disconnected at {connectionString}");
                                    };
                                    monitor.BindFailed += (sender, e) =>
                                    {
                                        Console.WriteLine($"Backend router bind failed {connectionString}");
                                    };

                                    Console.WriteLine($"Attempting to bind backend socket to {connectionString}");
                                    monitor.StartAsync();
                                    monitor.AttachToPoller(poller);

                                    var pollerTask = new Task(poller.Run);
                                    pollerTask.ContinueWith((Task task) =>
                                    {
                                        var ex = task.Exception;

                                        Console.WriteLine(ex.Message + ": " + ex.StackTrace);
                                        isListening = false;
                                    }, TaskContinuationOptions.OnlyOnFaulted);
                                    pollerTask.Start();

                                    backendSocket.Bind(connectionString);

                                    var start = DateTime.Now;
                                    while (!isListening)
                                    {
                                        if ((DateTime.Now - start).TotalMilliseconds > 5000)
                                        {
                                            throw new Exception($"Backend socket bind timeout ({connectionString})");
                                        }

                                        await Task.Delay(1000);
                                    }

                                    while (this.IsRunning && isListening)
                                    {
                                        if (this.BackendAnnouncer != null)
                                        {
                                            //Console.WriteLine("Registering backend");
                                            await this.BackendAnnouncer.Register(this.BackendEndpoint);
                                        }

                                        await Task.Delay(1000);
                                    }

                                    poller.StopAsync();
                                    backendSocket.Disconnect(connectionString);
                                    monitor.DetachFromPoller();
                                    monitor.Stop();
                                }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message + ": " + ex.StackTrace);
                }
            }
        }
        private async Task Handler()
        {
            while (this.IsRunning)
            {
                try
                {
                    bool isListening      = false;
                    var  connectionString = this.FrontendEndpoint.ToConnectionString();

                    using (var frontendSocket = new RouterSocket())
                        using (this.FrontendBuffer = new NetMQQueue <TransportMessage>())
                            using (var poller = new NetMQPoller()
                            {
                                frontendSocket, this.FrontendBuffer
                            })
                                using (var monitor = new NetMQ.Monitoring.NetMQMonitor(frontendSocket, $"inproc://monitor.forwarderdevice.{Guid.NewGuid().ToString()}", SocketEvents.Listening | SocketEvents.Accepted | SocketEvents.Disconnected | SocketEvents.Closed))
                                {
                                    frontendSocket.ReceiveReady += (sender, e) =>
                                    {
                                        try
                                        {
                                            var netmqMessage = new NetMQMessage();
                                            while (e.Socket.TryReceiveMultipartMessage(ref netmqMessage))
                                            {
                                                var    message           = netmqMessage.ToMessage(out var envelope);
                                                string serviceIdentifier = message.Metadata.TryGetLast("serviceIdentifier", out var encodedService) ? Encoding.UTF8.GetString(encodedService) : null;

                                                try
                                                {
                                                    var cancellationSource = new CancellationTokenSource(5000);
                                                    var registeredBackend  = this.ResolveBackend(serviceIdentifier, cancellationSource.Token);
                                                    //var registeredBackend = this.InprocTransportScope.GetNextServerTransport(serviceIdentifier, cancellationSource.Token);

                                                    message.Metadata.Add($"envelope[{this.Identity}]", envelope);

                                                    //registeredBackend.ReceiveBuffer.QueueMessage(message);

                                                    registeredBackend.Send(message).ContinueWith(task =>
                                                    {
                                                        this.OnDiagnosticMessage($"Failed to forward to backend [{task.Exception.InnerException.Message}]");
                                                    }, TaskContinuationOptions.OnlyOnFaulted);
                                                }
                                                catch (OperationCanceledException)
                                                {
                                                    this.OnDiagnosticMessage($"No backends available for {serviceIdentifier}!!!");

                                                    var nmqm = MessageHelpers.CreateNetMQErrorMessage(envelope, "No backends found", message.Metadata);
                                                    e.Socket.SendMultipartMessage(nmqm);
                                                }
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            this.OnDiagnosticMessage(ex.Message + ": " + ex.StackTrace);
                                        }
                                    };

                                    this.FrontendBuffer.ReceiveReady += (sender, e) =>
                                    {
                                        try
                                        {
                                            while (this.FrontendBuffer.TryDequeue(out TransportMessage message, TimeSpan.Zero))
                                            {
                                                if (!message.Metadata.TryPluckLast($"envelope[{this.Identity}]", out var envelope))
                                                {
                                                    throw new Exception("Message envelope not found");
                                                }

                                                if (!frontendSocket.TrySendMultipartMessage(TimeSpan.FromSeconds(1), message.ToNetMQMessage(envelope)))
                                                {
                                                    this.OnDiagnosticMessage("Failed to forward to frontend");
                                                }
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            this.OnDiagnosticMessage(ex.Message + ": " + ex.StackTrace);
                                        }
                                    };

                                    monitor.Listening += (sender, e) =>
                                    {
                                        this.OnDiagnosticMessage($"Frontend router socket listening at {connectionString}");
                                        isListening = true;
                                    };
                                    monitor.Closed += (sender, e) =>
                                    {
                                        this.OnDiagnosticMessage($"Frontend router socket closed on {connectionString}");
                                        isListening = false;
                                    };
                                    monitor.Accepted += (sender, e) =>
                                    {
                                        this.OnDiagnosticMessage($"Frontend router socket connection accepted at {connectionString}");
                                    };
                                    monitor.Disconnected += (sender, e) =>
                                    {
                                        this.OnDiagnosticMessage($"Frontend router socket disconnected at {connectionString}");
                                    };

                                    this.OnDiagnosticMessage($"Attempting to bind frontend socket to {connectionString}");
                                    monitor.StartAsync();
                                    monitor.AttachToPoller(poller);

                                    var pollerTask = new Task(poller.Run);
                                    pollerTask.ContinueWith(task =>
                                    {
                                        var ex = task.Exception;

                                        this.OnDiagnosticMessage(ex.Message + ": " + ex.StackTrace);
                                        isListening = false;
                                    }, TaskContinuationOptions.OnlyOnFaulted);
                                    pollerTask.Start();

                                    frontendSocket.Bind(connectionString);

                                    var start = DateTime.Now;
                                    while (!isListening)
                                    {
                                        if ((DateTime.Now - start).TotalMilliseconds > 5000)
                                        {
                                            throw new Exception($"Frontend socket bind timeout ({connectionString})");
                                        }

                                        await Task.Delay(1000);
                                    }

                                    while (this.IsRunning && isListening)
                                    {
                                        await Task.Delay(1000);
                                    }

                                    poller.StopAsync();
                                    frontendSocket.Disconnect(connectionString);
                                    monitor.DetachFromPoller();
                                    monitor.Stop();
                                }
                }
                catch (Exception ex)
                {
                    this.OnDiagnosticMessage(ex.Message + ": " + ex.StackTrace);
                }
            }
        }
        private async Task FrontendHandler()
        {
            while (this.IsRunning)
            {
                try
                {
                    bool isListening      = false;
                    var  connectionString = this.FrontendEndpoint.ToConnectionString();

                    using (var frontendSocket = new RouterSocket())
                        using (this.AltFrontendBuffer = new NetMQQueue <TransportMessage>())
                            using (var poller = new NetMQPoller()
                            {
                                frontendSocket, this.AltFrontendBuffer
                            })
                                using (var monitor = new NetMQ.Monitoring.NetMQMonitor(frontendSocket, $"inproc://monitor.routerdevice.frontend.{Guid.NewGuid().ToString()}", SocketEvents.Listening | SocketEvents.Accepted | SocketEvents.Disconnected | SocketEvents.Closed))
                                {
                                    frontendSocket.ReceiveReady += (sender, e) =>
                                    {
                                        try
                                        {
                                            var netmqMessage = new NetMQMessage();
                                            while (e.Socket.TryReceiveMultipartMessage(ref netmqMessage))
                                            {
                                                //Console.WriteLine("Frontend message received");

                                                var message = netmqMessage.ToMessage(out var envelope);

                                                this.OnFrontendReceived(message);

                                                //this.receiveCount++;
                                                //Console.WriteLine("RECEIVED " + this.receiveCount);

                                                //var sourceEnvelope = message.Envelope;

                                                RegisteredBackend registeredBackend = null;
                                                var forwardStart = DateTime.UtcNow;
                                                while (this.IsRunning && registeredBackend == null)
                                                {
                                                    while (this.RegisteredBackendIdentifiers.TryDequeue(out string backendIdentifier))
                                                    {
                                                        registeredBackend = this.RegisteredBackends[backendIdentifier];

                                                        if ((DateTime.UtcNow - registeredBackend.RegsiteredDate).TotalMilliseconds < 2000)
                                                        {
                                                            this.RegisteredBackendIdentifiers.Enqueue(backendIdentifier);
                                                            break;
                                                        }
                                                        else
                                                        {
                                                            if (this.RegisteredBackends.TryRemove(backendIdentifier, out RegisteredBackend expiredBackend))
                                                            {
                                                                Console.WriteLine($"Backend {backendIdentifier} expired");
                                                            }
                                                        }
                                                    }

                                                    if (registeredBackend != null || (DateTime.Now - forwardStart).TotalMilliseconds > 30000)
                                                    {
                                                        break;
                                                    }

                                                    System.Threading.Thread.Sleep(100);
                                                }

                                                if (registeredBackend != null)
                                                {
                                                    //Console.WriteLine($"Forwarding to [ {BitConverter.ToString(registeredBackend.Envelope)} ]");

                                                    message.Metadata.Add($"envelope[{this.Identity}]", envelope);
                                                    message.Metadata.Add($"backendEnvelope[{this.Identity}]", registeredBackend.Envelope);

                                                    this.AltBackendBuffer.Enqueue(message);

                                                    ////this.BackendSocket.SendMultipartMessage(message.ToNetMQMessage(true));
                                                    //if (!this.BackendSocket.TrySendMultipartMessage(TimeSpan.FromSeconds(1), message.ToNetMQMessage(true)))
                                                    //{
                                                    //    Console.WriteLine("Failed to forward to backend");

                                                    //    var forwardedMessage = new Message(1, message.Frames, System.Text.Encoding.UTF8.GetBytes("Failed to forward to backend"), sourceEnvelope);
                                                    //    this.FrontendSocket.SendMultipartMessage(forwardedMessage.ToNetMQMessage(true));
                                                    //}
                                                }
                                                else
                                                {
                                                    Console.WriteLine("No backends available!!!");

                                                    var nmqm = MessageHelpers.CreateNetMQErrorMessage(envelope, "No backends found", message.Metadata);
                                                    e.Socket.SendMultipartMessage(nmqm);
                                                }
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            Console.WriteLine(ex.Message + ": " + ex.StackTrace);
                                        }
                                    };

                                    //var lastFlushed = DateTime.UtcNow;
                                    //frontendSocket.SendReady += (sender, e) =>
                                    //{
                                    //    try
                                    //    {
                                    //        if (!this.BackendBuffer.IsEmpty)
                                    //        {
                                    //            while (this.BackendBuffer.TryDequeue(out Message message))
                                    //            {
                                    //                Console.WriteLine("Backend forwarding");

                                    //                if (!e.Socket.TrySendMultipartMessage(TimeSpan.FromSeconds(1), message.ToNetMQMessage(true)))
                                    //                {
                                    //                    Console.WriteLine("Failed to forward to frontend");

                                    //                    //var forwardedMessage = new Message(1, message.Frames, System.Text.Encoding.UTF8.GetBytes("Failed to forward to backend"), sourceEnvelope);
                                    //                    //this.FrontendSocket.SendMultipartMessage(forwardedMessage.ToNetMQMessage(true));
                                    //                }
                                    //            }

                                    //            lastFlushed = DateTime.UtcNow;
                                    //        }

                                    //        if ((DateTime.UtcNow - lastFlushed).TotalSeconds > 1)
                                    //            Task.Delay(1).Wait();
                                    //    }
                                    //    catch (Exception ex)
                                    //    {
                                    //        Console.WriteLine(ex.Message + ": " + ex.StackTrace);
                                    //    }
                                    //};
                                    this.AltFrontendBuffer.ReceiveReady += (sender, e) =>
                                    {
                                        try
                                        {
                                            while (this.AltFrontendBuffer.TryDequeue(out TransportMessage message, TimeSpan.Zero))
                                            {
                                                if (!message.Metadata.TryPluck($"envelope[{this.Identity}]", out var envelope))
                                                {
                                                    throw new Exception("Message envelope not found");
                                                }

                                                this.OnBackendForwarded(message);

                                                if (!frontendSocket.TrySendMultipartMessage(TimeSpan.FromSeconds(1), message.ToNetMQMessage(envelope)))
                                                {
                                                    Console.WriteLine("Failed to forward to frontend");
                                                }
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            Console.WriteLine(ex.Message + ": " + ex.StackTrace);
                                        }
                                    };

                                    monitor.Listening += (sender, e) =>
                                    {
                                        Console.WriteLine($"Frontend router socket listening at {connectionString}");
                                        isListening = true;
                                    };
                                    monitor.Closed += (sender, e) =>
                                    {
                                        Console.WriteLine($"Frontend router socket closed on {connectionString}");
                                        isListening = false;
                                    };
                                    monitor.Accepted += (sender, e) =>
                                    {
                                        Console.WriteLine($"Frontend router socket connection accepted at {connectionString}");
                                    };
                                    monitor.Disconnected += (sender, e) =>
                                    {
                                        Console.WriteLine($"Frontend router socket disconnected at {connectionString}");
                                    };

                                    Console.WriteLine($"Attempting to bind frontend socket to {connectionString}");
                                    monitor.StartAsync();
                                    monitor.AttachToPoller(poller);

                                    var pollerTask = new Task(poller.Run);
                                    pollerTask.ContinueWith((Task task) =>
                                    {
                                        var ex = task.Exception;

                                        Console.WriteLine(ex.Message + ": " + ex.StackTrace);
                                        isListening = false;
                                    }, TaskContinuationOptions.OnlyOnFaulted);
                                    pollerTask.Start();

                                    frontendSocket.Bind(connectionString);

                                    var start = DateTime.Now;
                                    while (!isListening)
                                    {
                                        if ((DateTime.Now - start).TotalMilliseconds > 5000)
                                        {
                                            throw new Exception($"Frontend socket bind timeout ({connectionString})");
                                        }

                                        await Task.Delay(1000);
                                    }

                                    while (this.IsRunning && isListening)
                                    {
                                        if (this.FrontendAnnouncer != null)
                                        {
                                            //Console.WriteLine("Registering frontend");
                                            await this.FrontendAnnouncer.Register(this.FrontendEndpoint);
                                        }

                                        await Task.Delay(1000);
                                    }

                                    poller.StopAsync();
                                    frontendSocket.Disconnect(connectionString);
                                    monitor.DetachFromPoller();
                                    monitor.Stop();
                                }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message + ": " + ex.StackTrace);
                }
            }
        }