Example #1
0
        private static async Task <Gossiper> StartGossiper(ushort listenPort, IPEndPoint[] seeds, ILogger logger)
        {
            var options = new GossiperOptions
            {
                SeedMembers = seeds,
            };

            var gossiper = new Gossiper(listenPort, 0x06, listenPort, options, logger);
            await gossiper.StartAsync();

            return(gossiper);
        }
Example #2
0
        public async Task TestGrpc()
        {
            const int BINDING_PORT = 28888;

            var logger = loggerFactory.CreateLogger(nameof(TestGrpc));

            var gossiperImpl = new GossiperImpl();

            gossiperImpl.OnPull += (_, e) => { logger.LogInformation("OnPull"); e.Rumors = Enumerable.Empty <Rumor>(); };
            gossiperImpl.OnPush += (_, e) => logger.LogInformation("Receive rumors: [{0}]", string.Join(", ", e.Rumors.Select(r => r.GetHashCode())));

            var server = new Server
            {
                Ports    = { new ServerPort("127.0.0.1", BINDING_PORT, ServerCredentials.Insecure) },
                Services = { Gossiper.BindService(gossiperImpl) }
            };

            server.Start();

            var client     = new Gossiper.GossiperClient(new Channel($"127.0.0.1:{BINDING_PORT}", ChannelCredentials.Insecure));
            var pullResult = client.Pull(new PullRequest(), deadline: DateTime.UtcNow.AddMilliseconds(200));

            while (await pullResult.ResponseStream.MoveNext())
            {
                logger.LogInformation("Pulled rumor {0}", pullResult.ResponseStream.Current.GetHashCode());
            }

            var pushCall = client.Push(deadline: DateTime.UtcNow.AddMilliseconds(200));
            await pushCall.RequestStream.WriteAsync(new Rumor
            {
                Counter = 1,
                Payload = new Any()
            });

            await pushCall.RequestStream.CompleteAsync();

            var pushResult = await pushCall;

            logger.LogInformation("Client push finished");

            await server.ShutdownAsync();
        }
Example #3
0
        public void Configure(ILogger <Startup> logger, IEnumerable <IMemberListener> memberListeners, IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseDefaultFiles();
            app.UseStaticFiles();
            app.UseSignalR(routes =>
            {
                routes.MapHub <MembersHub>("/membersHub");
            });

            var listenPort = ushort.Parse(_configuration["port"]);
            var options    = new GossiperOptions
            {
                SeedMembers     = GetSeedEndPoints(),
                MemberListeners = memberListeners
            };

            var gossiper = new Gossiper(listenPort, 0x01, (ushort)5000, options, logger);

            gossiper.StartAsync().ConfigureAwait(false);
        }
Example #4
0
        public async Task TestIntegration()
        {
            const int NODE_COUNT    = 20;
            const int STARTING_PORT = 18888;

            var logger = loggerFactory.CreateLogger(nameof(TestIntegration));

            logger.LogInformation("{0}({1}, {2})", nameof(TestIntegration), NODE_COUNT, STARTING_PORT);

            var options = Options.Create(new EpidemicBroadcastServiceOption
            {
                MinimalSleepIntervalMilliseconds = 10,
                RoundIntervalMilliseconds        = 1000,
                EstimatedNodeCountMin            = NODE_COUNT,
                FanInNodeCountMax  = 1,
                FanOutNodeCountMax = 2,
                PushRoundsFactor   = 1,
                PullRoundsFactor   = 1,
                DeadRoundsFactor   = 1
            });
            var stopwatchProvider = new SystemStopwatchProvider();

            var services = Enumerable.Repeat <object>(null, NODE_COUNT)
                           .Select((_, idx) => new EpidemicBroadcastService(
                                       (idx == 0 ? (ILoggerFactory)loggerFactory : NullLoggerFactory.Instance).CreateLogger <EpidemicBroadcastService>(),
                                       options,
                                       stopwatchProvider)
            {
                GossiperClientFactory = target =>
                                        new Gossiper.GossiperClient(new Channel(target, ChannelCredentials.Insecure)),
                MemberListProvider = () => Enumerable.Range(STARTING_PORT, NODE_COUNT).Select(p => $"127.0.0.1:{p}").ToArray()
            })
                           .ToArray();

            var servers = services.Select((s, i) => new Server
            {
                Ports    = { new ServerPort("127.0.0.1", STARTING_PORT + i, ServerCredentials.Insecure) },
                Services = { Gossiper.BindService(s.GossiperImpl) }
            }).ToArray();

            foreach (var s in servers)
            {
                s.Start();
            }
            services.Select <EpidemicBroadcastService, object>((s, idx) =>
            {
                s.OnRumorReceived += (_, e) => logger.LogWarning(
                    "Rumor {0} received at service {1}!",
                    e.Payload.GetHashCode(),
                    idx);
                return(null);
            });

            await Task.WhenAll(services.Select(s => s.StartAsync()));

            services[0].Broadcast(new Any());

            await Task.Delay(1000 * 10);

            await Task.WhenAll(services.Select(s => s.StopAsync()));

            await Task.WhenAll(servers.Select(s => s.ShutdownAsync()));
        }
Example #5
0
        public async Task TestObservePullService()
        {
            const int BINDING_PORT = 38888;

            var logger = loggerFactory.CreateLogger(nameof(TestObserveService));

            var options = Options.Create(new EpidemicBroadcastServiceOption
            {
                MinimalSleepIntervalMilliseconds = 10,
                RoundIntervalMilliseconds        = 100,
                EstimatedNodeCountMin            = 5,
                FanInNodeCountMax  = 1,
                FanOutNodeCountMax = 2,
                PushRoundsFactor   = 1,
                PullRoundsFactor   = 1,
                DeadRoundsFactor   = 1
            });
            var stopwatchProvider = new SystemStopwatchProvider();

            var service = new EpidemicBroadcastService(
                loggerFactory.CreateLogger <EpidemicBroadcastService>(),
                options,
                stopwatchProvider)
            {
                GossiperClientFactory = target =>
                                        new Gossiper.GossiperClient(new Channel(target, ChannelCredentials.Insecure)),
                MemberListProvider = () => Enumerable.Range(BINDING_PORT, 5).Select(p => $"127.0.0.1:{p}").ToArray()
            };

            var server = new Server
            {
                Ports    = { new ServerPort("127.0.0.1", BINDING_PORT, ServerCredentials.Insecure) },
                Services = { Gossiper.BindService(service.GossiperImpl) }
            };

            service.OnRumorReceived += (_, e) => logger.LogInformation("Rumor {0} received.", e.Payload.GetHashCode());

            server.Start();
            await service.StartAsync();

            service.Broadcast(new Any());
            await Task.Delay(500);

            var client = new Gossiper.GossiperClient(new Channel($"127.0.0.1:{BINDING_PORT}", ChannelCredentials.Insecure));

            using (var pushCall = client.Push(deadline: DateTime.UtcNow.AddMilliseconds(200)))
            {
                await pushCall.RequestStream.WriteAsync(new Rumor
                {
                    Counter = 3,
                    Payload = new Any()
                });

                await pushCall.RequestStream.CompleteAsync();

                var pushResult = await pushCall;
                logger.LogInformation("Client push finished");
            }

            await Task.Delay(110);

            using (var pullResult = client.Pull(new PullRequest(), deadline: DateTime.UtcNow.AddMilliseconds(200)))
            {
                while (await pullResult.ResponseStream.MoveNext())
                {
                    logger.LogInformation("Pulled rumor {0}", pullResult.ResponseStream.Current.GetHashCode());
                }
                logger.LogInformation("Client pull finished");
            }

            await service.StopAsync();

            await server.ShutdownAsync();

            await Task.Delay(1000);
        }
        internal static async Task Main(string[] args)
        {
            LogManager.Configuration = new XmlLoggingConfiguration("nlog.config");

            var configuration = BuildConfiguration(args);
            var services      = new ServiceCollection();

            services.AddSingleton(configuration);
            services.AddLogging(b => b.AddNLog().SetMinimumLevel(LogLevel.Trace));
            services.Configure <ClusterOptions>(configuration.GetSection("Cluster"));

            var selfNodeEndpoint = configuration.GetValue <string>("Root:EndPoint");
            var selfBindingPort  = int.Parse(selfNodeEndpoint.Split(new[] { ':' }, 2)[1]);
            var clientFactory    = new Func <string, Gossiper.GossiperClient>(target =>
            {
                var channel = new Channel(target, ChannelCredentials.Insecure);
                return(new Gossiper.GossiperClient(channel));
            });

            services.AddScoped(serviceProvider =>
            {
                var seedsEndpoint = serviceProvider.GetRequiredService <IConfiguration>()
                                    .GetValue <string>("Root:Seeds")
                                    .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                return(Node.Create(
                           selfNodeEndpoint,
                           seedsEndpoint,
                           () => serviceProvider.GetRequiredService <ILogger <Node> >()));
            });
            services.AddScoped(serviceProvider => new GossiperImpl(
                                   serviceProvider.GetRequiredService <ILogger <GossiperImpl> >(),
                                   clientFactory,
                                   serviceProvider.GetRequiredService <Node>()));
            services.AddScoped(serviceProvider => new Cluster(
                                   serviceProvider.GetRequiredService <ILogger <Cluster> >(),
                                   serviceProvider.GetRequiredService <IOptionsMonitor <ClusterOptions> >(),
                                   serviceProvider.GetRequiredService <Node>(),
                                   clientFactory));

            var container = services.BuildServiceProvider();

            var logger = container.GetRequiredService <ILogger <Program> >();
            var node   = container.GetRequiredService <Node>();

            node.NodeStateChanged += (_, e) =>
            {
                logger.LogWarning(
                    "Node {0} state changed from {1} to {2}",
                    e.EndPoint, e.PreviousNodeState, e.CurrentNodeState);
            };

            GrpcEnvironment.SetLogger(new GrpcLoggerAdapter(
                                          container.GetRequiredService <ILogger <GrpcEnvironment> >(),
                                          container.GetRequiredService <ILoggerFactory>()));

            var server = new Server
            {
                Services = { Gossiper.BindService(container.GetRequiredService <GossiperImpl>()) },
                Ports    = { new ServerPort(selfNodeEndpoint.Split(':')[0], selfBindingPort, ServerCredentials.Insecure) }
            };

            server.Start();

            var cluster = container.GetRequiredService <Cluster>();
            await cluster.StartAsync();

            logger.LogInformation("Server is running");
            Console.ReadKey();

            Task.WaitAll(
                server.ShutdownAsync(),
                cluster.StopAsync());
        }