public void TestWriteWithDesiredSpeed() { var keyDistributor = new KeyDistributor(64); var threads = Enumerable.Range(0, 5).Select(number => { var repository = CreateBoxEventRepository((id, obj) => keyDistributor.Distribute(id.ScopeId).ToString()); var testEventWriter = new TestEventWriter(repository, OperationsSpeed.PerSecond(10000), 1000); var thread = new Thread(testEventWriter.BeginExecution); thread.Start(); return(new { Thread = thread, Writer = testEventWriter }); }).ToList(); Thread.Sleep(TimeSpan.FromSeconds(30)); threads.ForEach(x => x.Writer.StopExecution()); threads.ForEach(x => x.Thread.Join()); }
public void TestWriteAndRead64Shard() { boxIds = new[] { Guid.NewGuid().ToString(), Guid.NewGuid().ToString() }; using (var eventRepository = CreateBoxEventRepository((eventId, obj) => { var keyDistributor = new KeyDistributor(64); return(keyDistributor.Distribute(eventId.ScopeId).ToString()); }, 0)) { var expectedEvents = new List <Event>(); const int count = 30; for (var i = 0; i < count; ++i) { Console.WriteLine("Start write event {0}", i); var scopeId = GenerateScopeId(); var eventContent = GenerateEventContent(); var eventInfo = eventRepository.AddEvent(scopeId, eventContent); Assert.AreEqual(scopeId, eventInfo.Id.ScopeId); expectedEvents.Add(new Event { EventInfo = eventInfo, EventContent = eventContent, }); } var shards = new string[64].Select((x, idx) => (idx.ToString())).ToArray(); Console.WriteLine("Get events: all."); var actualEvents = eventRepository.GetEvents(null, shards).ToArray(); CheckEqualEvents(expectedEvents.ToArray(), actualEvents); for (var i = 0; i < expectedEvents.Count; ++i) { Console.WriteLine("Get events: from {0}.", i); actualEvents = eventRepository.GetEvents(expectedEvents[i].EventInfo, shards).ToArray(); CheckEqualEvents(expectedEvents.Skip(i + 1).ToArray(), actualEvents); } } }
public void TestGuidDistribution() { const int shardsCount = 10; var keyDistributor = KeyDistributor.Create(shardsCount); var array = new int[shardsCount]; const int guidsCount = 10000; var sw = Stopwatch.StartNew(); for (var i = 0; i < guidsCount; i++) { var idx = keyDistributor.Distribute(Guid.NewGuid().ToString()); if (idx < 0 || idx >= shardsCount) { Assert.That(false); } array[idx]++; } Console.WriteLine("Time=" + sw.Elapsed); var diff = array.Max() - array.Min(); Console.WriteLine("Diff = " + diff); Assert.That(diff < guidsCount / 50); }
public void TestRandomStringDistribution() { const int shardsCount = 10; var keyDistributor = KeyDistributor.Create(shardsCount); var array = new int[shardsCount]; var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Tests/EventLog/Sharding/Files/dict.txt"); var words = File.ReadAllText(path).Split('\n', '\r').Where(s => !string.IsNullOrEmpty(s)).ToArray(); var sw = Stopwatch.StartNew(); for (var i = 0; i < words.Length; i++) { var idx = keyDistributor.Distribute(words[i]); if (idx < 0 || idx >= shardsCount) { Assert.That(false); } array[idx]++; } Console.WriteLine("Time=" + sw.Elapsed); var diff = array.Max() - array.Min(); Console.WriteLine("Diff = " + diff); Assert.That(diff < words.Length / 100); }
public override void SetUp() { base.SetUp(); keyDistributor = new KeyDistributor(shardsCount); globalEventRepository = CreateBoxEventRepository(); }
private string CalculateShard(EventId eventId, object eventContent) { var keyDistributor = new KeyDistributor(ShardsCount); return(keyDistributor.Distribute(eventId.ScopeId).ToString()); }
static async Task Main(string[] args) { string basePath = (Debugger.IsAttached) ? Directory.GetCurrentDirectory() : AppDomain.CurrentDomain.BaseDirectory; var configBuilder = new ConfigurationBuilder() .SetBasePath(basePath) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: false) .AddEnvironmentVariables(); var config = configBuilder.Build(); // connect to RabbitMQ var conn = Utils.ConnectRabbitMQ(config); // token signing key byte[] tokenKey = null; // configure keys through RabbitMQ exchange await KeyDistributor.ConfigureAsync( config["RabbitMQ:Exchanges:KeyDistribution"], conn, keys => { TelemetryConfiguration.Active.InstrumentationKey = keys.AppInsightsInstrumKey; tokenKey = keys.JwtIssuerKey; }); // set app insights developer mode (remove lags when sending telemetry) TelemetryConfiguration.Active.TelemetryChannel.DeveloperMode = true; // set service name in app insights TelemetryConfiguration.Active.TelemetryInitializers.Add(new CustomTelemetryInitializer(serviceName)); // telemetry client instance var telemetry = new TelemetryClient(); // token validation parameters var tokenValidationParameters = new TokenValidationParameters { ValidateAudience = false, ValidateIssuer = false, ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(tokenKey) }; // security options for RabbitMQ service var securityOptions = new SecurityOptions( // map of request types to scope names new Dictionary <string, string>() { { nameof(Ping1), "1" }, { nameof(Ping2), "2" }, { nameof(Ping3), "3" }, { nameof(Ping4), "4" } }, tokenValidationParameters); // set host configuration var hostBuilder = new HostBuilder() .ConfigureHostConfiguration(c => c .SetBasePath(basePath) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)) .ConfigureServices((context, services) => { services.AddSingleton <TelemetryClient>(telemetry); services.AddSingleton <SecurityOptions>(securityOptions); services.AddSingleton <IConnection>(conn); services.AddHostedService <BangService>(); }); var host = hostBuilder.Build(); // send ready signal await ReadyChecker.SendReadyAsync(config["RabbitMQ:Exchanges:ReadyCheck"], conn, serviceName); // run host and wait for shutdown signal await host.StartAsync(); await Shutdowner.ShutdownAsync(config["RabbitMQ:Exchanges:Shutdown"], conn, () => host.StopAsync()); // flush telemetry telemetry?.Flush(); Task.Delay(1000).Wait(); Console.WriteLine("Bye!"); }
static async Task Main(string[] args) { string basePath = (Debugger.IsAttached) ? Directory.GetCurrentDirectory() : AppDomain.CurrentDomain.BaseDirectory; var configBuilder = new ConfigurationBuilder() .SetBasePath(basePath) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: false) .AddEnvironmentVariables(); if (Debugger.IsAttached) { configBuilder.AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: false); } var config = configBuilder.Build(); // connect to RabbitMQ var conn = Utils.ConnectRabbitMQ(config); // token signing key byte[] tokenKey = null; // app insights key string appInsKey = null; // configure keys through RabbitMQ exchange await KeyDistributor.ConfigureAsync( config["RabbitMQ:Exchanges:KeyDistribution"], conn, keys => { appInsKey = keys.AppInsightsInstrumKey; tokenKey = keys.JwtIssuerKey; }); // set app insights developer mode (remove lags when sending telemetry) TelemetryConfiguration.Active.TelemetryChannel.DeveloperMode = true; // token validation parameters var tokenValidationParameters = new TokenValidationParameters { ValidateAudience = false, ValidateIssuer = false, ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(tokenKey) }; // set host configuration var hostBuilder = new WebHostBuilder() .UseConfiguration(config) .ConfigureLogging(logging => { logging.AddConfiguration(config.GetSection("Logging")); logging.AddConsole(); }) .ConfigureServices(services => { services.AddSingleton <IConnection>(conn); services.AddSingleton <ITelemetryInitializer>(new CustomTelemetryInitializer("apigw")); services.AddApplicationInsightsTelemetry(appInsKey); services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = tokenValidationParameters; options.SaveToken = true; }); services.AddMvc(options => options.Filters.Add(new ExceptionFilter())); }) .Configure(app => { app.UseAuthentication(); app.UseMvc(); }) .UseKestrel(); var host = hostBuilder.Build(); // send ready signal await ReadyChecker.SendReadyAsync(config["RabbitMQ:Exchanges:ReadyCheck"], conn, serviceName); // run host and wait for shutdown signal await host.StartAsync(); await Shutdowner.ShutdownAsync(config["RabbitMQ:Exchanges:Shutdown"], conn, () => host.StopAsync()); // telemetry client instance var telemetry = host.Services.GetService <TelemetryClient>(); // flush telemetry telemetry?.Flush(); Task.Delay(1000).Wait(); Console.WriteLine("Bye!"); }
static async Task Main(string[] args) { string basePath = (Debugger.IsAttached) ? Directory.GetCurrentDirectory() : AppDomain.CurrentDomain.BaseDirectory; // build config var configBuilder = new ConfigurationBuilder() .SetBasePath(basePath) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: false) .AddEnvironmentVariables(); if (Debugger.IsAttached) { configBuilder.AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: false); } var config = configBuilder.Build(); // connect to RabbitMQ var conn = Utils.ConnectRabbitMQ(config); // wait peers to be ready var waitPeers = ReadyChecker.WaitPeersAsync(config["RabbitMQ:Exchanges:ReadyCheck"], conn, new List <string> { "apigw", "bang", "bar", "fib", "foo" }); // get App Insights instrumentation key from CLI Console.WriteLine("Please enter your Application Insights instrumentation key: "); var instrumKey = Console.ReadLine(); // generate key and token var tokenKey = GenKey(); // distribute keys await KeyDistributor.ConfigurePeersAsync(config["RabbitMQ:Exchanges:KeyDistribution"], conn, new Keys { AppInsightsInstrumKey = instrumKey, JwtIssuerKey = tokenKey }); // if peers are ready if (await Task.WhenAny(waitPeers, Task.Delay(15000)) == waitPeers) { // Task completed within timeout. // Consider that the task may have faulted or been canceled. // We re-await the task so that any exceptions/cancellation is rethrown. await waitPeers; bool shutdown = false; // perform demo scenarios based on user choise using (var http = new HttpClient()) { http.BaseAddress = new Uri(config["ApiGW:Url"]); while (!shutdown) { try { string url = null; switch (MainDialog()) { case '1': url = "api/demo/fooping1"; break; case '2': url = "api/demo/barping2"; break; case '3': url = "api/demo/fibping3"; break; case '4': url = "api/demo/fibping4"; break; case 'q': shutdown = true; break; } if (shutdown) { await Shutdowner.ShutdownPeersAsync(config["RabbitMQ:Exchanges:Shutdown"], conn); } else { HttpResponseMessage resp = await http.GetAsync(url); if (resp.StatusCode == HttpStatusCode.Unauthorized) { var username = LoginDialog(); var token = GenToken(tokenKey, username); http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); Console.WriteLine($"Bearer JWT for user '{username}' will be sent in the header of every request since now."); } else { resp.EnsureSuccessStatusCode(); Console.WriteLine(); Console.WriteLine("----------------------------------------"); Console.WriteLine($"HTTP GET '/{url}' completed at {DateTime.Now.ToString()}."); Console.WriteLine("----------------------------------------"); } } } catch (HttpRequestException ex) { Console.WriteLine(); Console.WriteLine("----------------------------------------"); Console.WriteLine("Message: " + ex.Message); Console.WriteLine("----------------------------------------"); } } } } else { // timeout/cancellation logic Console.WriteLine(); Console.WriteLine("Sorry, but not all services are ready for demo."); await Shutdowner.ShutdownPeersAsync(config["RabbitMQ:Exchanges:Shutdown"], conn); return; } Console.WriteLine("Bye!"); }