mirror of
https://github.com/NecroticBamboo/QRBee.git
synced 2025-12-21 12:11:53 +00:00
DEEP-26 LoadSpike shows spike end
This commit is contained in:
parent
aeb8154241
commit
58b7565597
@ -8,6 +8,8 @@ internal class Anomaly
|
|||||||
|
|
||||||
internal class GeneratorSettings
|
internal class GeneratorSettings
|
||||||
{
|
{
|
||||||
|
public string QRBeeURL { get; set; } = "http://localhost:5000/";
|
||||||
|
public int DefaultConnectionLimit { get; set; } = 100;
|
||||||
public int NumberOfClients { get; set; } = 100;
|
public int NumberOfClients { get; set; } = 100;
|
||||||
public int NumberOfMerchants { get; set; } = 10;
|
public int NumberOfMerchants { get; set; } = 10;
|
||||||
public int NumberOfThreads { get; set; } = 20;
|
public int NumberOfThreads { get; set; } = 20;
|
||||||
|
|||||||
@ -36,6 +36,8 @@ internal class LoadGenerator : IHostedService
|
|||||||
_loadSpike = loadSpike;
|
_loadSpike = loadSpike;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_settings = settings;
|
_settings = settings;
|
||||||
|
|
||||||
|
_logger.LogInformation($"Connected to QRBee on {_client.BaseUrl}");
|
||||||
}
|
}
|
||||||
public async Task StartAsync(CancellationToken cancellationToken)
|
public async Task StartAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
@ -70,12 +72,28 @@ internal class LoadGenerator : IHostedService
|
|||||||
{
|
{
|
||||||
DateTime nextReport = DateTime.MinValue;
|
DateTime nextReport = DateTime.MinValue;
|
||||||
|
|
||||||
|
var lastPaymentsGenerated = 0L;
|
||||||
|
var lastPaymentsProcessed = 0L;
|
||||||
|
var lastPaymentsConfirmed = 0L;
|
||||||
|
var lastPaymentsFailed = 0L;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (DateTime.Now > nextReport)
|
if (DateTime.Now > nextReport)
|
||||||
{
|
{
|
||||||
_logger.LogInformation($"S: {_paymentsGenerated,10:N0} R: {_paymentsProcessed,10:N0} C: {_paymentsConfirmed,10:N0} F: {_paymentsFailed,10:N0}");
|
_logger.LogInformation(
|
||||||
|
$"S: {_paymentsGenerated-lastPaymentsGenerated,10:N0} " +
|
||||||
|
$"R: {_paymentsProcessed-lastPaymentsProcessed,10:N0} " +
|
||||||
|
$"C: {_paymentsConfirmed-lastPaymentsConfirmed,10:N0} " +
|
||||||
|
$"F: {_paymentsFailed-lastPaymentsFailed,10:N0}"
|
||||||
|
);
|
||||||
|
|
||||||
nextReport = DateTime.Now + TimeSpan.FromSeconds(1);
|
nextReport = DateTime.Now + TimeSpan.FromSeconds(1);
|
||||||
|
|
||||||
|
lastPaymentsGenerated = _paymentsGenerated;
|
||||||
|
lastPaymentsProcessed = _paymentsProcessed;
|
||||||
|
lastPaymentsConfirmed = _paymentsConfirmed;
|
||||||
|
lastPaymentsFailed = _paymentsFailed;
|
||||||
}
|
}
|
||||||
await Task.Delay(1000);
|
await Task.Delay(1000);
|
||||||
}
|
}
|
||||||
@ -157,7 +175,9 @@ internal class LoadGenerator : IHostedService
|
|||||||
var newQueue = new List<Task<PaymentResponse>>();
|
var newQueue = new List<Task<PaymentResponse>>();
|
||||||
|
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
newQueue = Interlocked.Exchange(ref _responseQueue, newQueue);
|
{
|
||||||
|
(newQueue, _responseQueue) = (_responseQueue, newQueue);
|
||||||
|
}
|
||||||
|
|
||||||
if (newQueue.Count == 0)
|
if (newQueue.Count == 0)
|
||||||
{
|
{
|
||||||
@ -165,7 +185,7 @@ internal class LoadGenerator : IHostedService
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var tasks = newQueue.ToList();
|
var tasks = newQueue.Where(x => x != null).ToList();
|
||||||
|
|
||||||
while ( tasks.Any() )
|
while ( tasks.Any() )
|
||||||
{
|
{
|
||||||
@ -198,6 +218,19 @@ internal class LoadGenerator : IHostedService
|
|||||||
else
|
else
|
||||||
Interlocked.Increment(ref _paymentsFailed);
|
Interlocked.Increment(ref _paymentsFailed);
|
||||||
}
|
}
|
||||||
|
catch (TaskCanceledException )
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref _paymentsFailed);
|
||||||
|
// no message - too noisy
|
||||||
|
}
|
||||||
|
catch (HttpRequestException httpEx)
|
||||||
|
{
|
||||||
|
if ( httpEx.InnerException is IOException )
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref _paymentsFailed);
|
||||||
|
// no message - too noisy
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Interlocked.Increment(ref _paymentsFailed);
|
Interlocked.Increment(ref _paymentsFailed);
|
||||||
@ -232,7 +265,8 @@ internal class LoadGenerator : IHostedService
|
|||||||
|
|
||||||
var resp = _client.PayAsync(req);
|
var resp = _client.PayAsync(req);
|
||||||
|
|
||||||
_responseQueue.Add(resp);
|
lock (_lock)
|
||||||
|
_responseQueue.Add(resp);
|
||||||
Interlocked.Increment(ref _paymentsGenerated);
|
Interlocked.Increment(ref _paymentsGenerated);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@ -17,6 +17,7 @@ namespace QRBee.Load.Generator
|
|||||||
private TimeSpan _spikeDuration;
|
private TimeSpan _spikeDuration;
|
||||||
private TimeSpan _spikeDelay;
|
private TimeSpan _spikeDelay;
|
||||||
private double _spikeProbability;
|
private double _spikeProbability;
|
||||||
|
private bool _spikeActive;
|
||||||
|
|
||||||
private ThreadSafeRandom _rng = new();
|
private ThreadSafeRandom _rng = new();
|
||||||
private DateTime _spikeEnd = DateTime.MinValue;
|
private DateTime _spikeEnd = DateTime.MinValue;
|
||||||
@ -55,12 +56,21 @@ namespace QRBee.Load.Generator
|
|||||||
{
|
{
|
||||||
if (DateTime.Now > _spikeEnd)
|
if (DateTime.Now > _spikeEnd)
|
||||||
{
|
{
|
||||||
|
if (_spikeActive)
|
||||||
|
{
|
||||||
|
_spikeActive = false;
|
||||||
|
_logger.LogWarning($"Anomaly: Load spike ended");
|
||||||
|
}
|
||||||
|
|
||||||
var dice = _rng.NextDouble();
|
var dice = _rng.NextDouble();
|
||||||
if (dice < _spikeProbability)
|
if (dice < _spikeProbability)
|
||||||
{
|
{
|
||||||
// start load spike
|
// start load spike
|
||||||
_spikeEnd = DateTime.Now + _spikeDuration;
|
_spikeEnd = DateTime.Now + _spikeDuration;
|
||||||
|
_spikeActive = true;
|
||||||
|
|
||||||
_logger.LogWarning($"Anomaly: Load spike until {_spikeEnd} Dice={dice}");
|
_logger.LogWarning($"Anomaly: Load spike until {_spikeEnd} Dice={dice}");
|
||||||
|
|
||||||
await Task.Delay(_spikeDelay);
|
await Task.Delay(_spikeDelay);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
// See https://aka.ms/new-console-template for more information
|
using log4net;
|
||||||
using log4net;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@ -8,6 +7,7 @@ using QRBee.Droid.Services;
|
|||||||
using QRBee.Load.Generator;
|
using QRBee.Load.Generator;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
Console.WriteLine("=== QRBee artificaial load generator ===");
|
Console.WriteLine("=== QRBee artificaial load generator ===");
|
||||||
|
|
||||||
@ -24,7 +24,12 @@ builder.ConfigureServices((context, services) =>
|
|||||||
});
|
});
|
||||||
|
|
||||||
services
|
services
|
||||||
.AddHttpClient<QRBee.Core.Client.Client, QRBee.Core.Client.Client>(httpClient => new QRBee.Core.Client.Client("https://localhost:7000/", httpClient))
|
.AddHttpClient<QRBee.Core.Client.Client, QRBee.Core.Client.Client>((httpClient,x) =>
|
||||||
|
{
|
||||||
|
var settings = x.GetRequiredService<IOptions<GeneratorSettings>>();
|
||||||
|
var url = settings.Value.QRBeeURL;
|
||||||
|
return new QRBee.Core.Client.Client(url, httpClient);
|
||||||
|
})
|
||||||
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator });
|
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator });
|
||||||
;
|
;
|
||||||
services
|
services
|
||||||
@ -40,7 +45,9 @@ builder.ConfigureServices((context, services) =>
|
|||||||
;
|
;
|
||||||
});
|
});
|
||||||
|
|
||||||
ServicePointManager.DefaultConnectionLimit = 500;
|
ServicePointManager.DefaultConnectionLimit = 10;
|
||||||
|
ServicePointManager.ReusePort = true;
|
||||||
|
ServicePointManager.CheckCertificateRevocationList = false;
|
||||||
|
|
||||||
var host = builder.Build();
|
var host = builder.Build();
|
||||||
host.Run();
|
host.Run();
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"GeneratorSettings": {
|
"GeneratorSettings": {
|
||||||
|
"QRBeeURL": "http://localhost:5000/",
|
||||||
"NumberOfClients": 100,
|
"NumberOfClients": 100,
|
||||||
"NumberOfMerchants": 10,
|
"NumberOfMerchants": 10,
|
||||||
"NumberOfThreads": 10,
|
"NumberOfThreads": 10,
|
||||||
@ -22,7 +23,7 @@
|
|||||||
|
|
||||||
//0.004
|
//0.004
|
||||||
"LoadSpike": {
|
"LoadSpike": {
|
||||||
"Probability": 0.005,
|
"Probability": 0.002,
|
||||||
"Parameters": {
|
"Parameters": {
|
||||||
"Duration": "00:00:15",
|
"Duration": "00:00:15",
|
||||||
"Delay": "00:00:00.0100000"
|
"Delay": "00:00:00.0100000"
|
||||||
|
|||||||
@ -33,7 +33,7 @@
|
|||||||
<forecolor value="Blue" />
|
<forecolor value="Blue" />
|
||||||
</mapping>
|
</mapping>
|
||||||
<layout type="log4net.Layout.PatternLayout">
|
<layout type="log4net.Layout.PatternLayout">
|
||||||
<conversionPattern value="%date{HH:mm:ss,fff} [%-2thread] %-5level %-15logger{1} %message%newline" />
|
<conversionPattern value="%date{HH:mm:ss,fff} [%3thread] %-5level %-15logger{1} %message%newline" />
|
||||||
</layout>
|
</layout>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
@ -41,7 +41,7 @@
|
|||||||
<file value="log-file.txt" />
|
<file value="log-file.txt" />
|
||||||
<appendToFile value="false" />
|
<appendToFile value="false" />
|
||||||
<layout type="log4net.Layout.PatternLayout">
|
<layout type="log4net.Layout.PatternLayout">
|
||||||
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
|
<conversionPattern value="%date [%3thread] %-5level %logger [%property{NDC}] - %message%newline" />
|
||||||
</layout>
|
</layout>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ using QRBee.Api;
|
|||||||
using QRBee.Api.Services;
|
using QRBee.Api.Services;
|
||||||
using QRBee.Api.Services.Database;
|
using QRBee.Api.Services.Database;
|
||||||
using QRBee.Core.Security;
|
using QRBee.Core.Security;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
@ -56,17 +57,18 @@ builder.Services
|
|||||||
.AddSingleton<CustomMetrics>()
|
.AddSingleton<CustomMetrics>()
|
||||||
;
|
;
|
||||||
|
|
||||||
|
ServicePointManager.DefaultConnectionLimit = 10;
|
||||||
|
ServicePointManager.ReusePort = true;
|
||||||
|
ServicePointManager.CheckCertificateRevocationList = false;
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
//if (app.Environment.IsDevelopment())
|
|
||||||
{
|
|
||||||
app.UseSwagger();
|
|
||||||
app.UseSwaggerUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
app.UseOpenTelemetryPrometheusScrapingEndpoint();
|
app.UseOpenTelemetryPrometheusScrapingEndpoint();
|
||||||
app.UseHttpsRedirection();
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI();
|
||||||
|
|
||||||
|
//app.UseHttpsRedirection();
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
app.MapControllers();
|
app.MapControllers();
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,4 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
|
||||||
"iisSettings": {
|
|
||||||
"windowsAuthentication": false,
|
|
||||||
"anonymousAuthentication": true,
|
|
||||||
"iisExpress": {
|
|
||||||
"applicationUrl": "http://localhost:1103",
|
|
||||||
"sslPort": 44300
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"profiles": {
|
"profiles": {
|
||||||
"QRBeeApi": {
|
"QRBeeApi": {
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
@ -16,7 +7,7 @@
|
|||||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||||
"LOGS_ROOT": "C:\\Users\\andre\\logs"
|
"LOGS_ROOT": "C:\\Users\\andre\\logs"
|
||||||
},
|
},
|
||||||
"applicationUrl": "https://localhost:7000;http://localhost:5000",
|
"applicationUrl": "http://localhost:5000",
|
||||||
"dotnetRunMessages": true
|
"dotnetRunMessages": true
|
||||||
},
|
},
|
||||||
"Docker": {
|
"Docker": {
|
||||||
@ -25,5 +16,14 @@
|
|||||||
"publishAllPorts": true,
|
"publishAllPorts": true,
|
||||||
"useSSL": true
|
"useSSL": true
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:1103",
|
||||||
|
"sslPort": 44300
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -18,16 +18,16 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="6.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="6.1.0" />
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.15.0" />
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.18.1" />
|
||||||
<PackageReference Include="MongoDB.Driver" Version="2.15.0" />
|
<PackageReference Include="MongoDB.Driver" Version="2.20.0" />
|
||||||
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.5.1" />
|
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.6.0-alpha.1" />
|
||||||
<PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.5.0-rc.1" />
|
<PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.6.0-alpha.1" />
|
||||||
<PackageReference Include="OpenTelemetry.Instrumentation.Process" Version="0.5.0-beta.3" />
|
<PackageReference Include="OpenTelemetry.Instrumentation.Process" Version="0.5.0-beta.3" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.3.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||||
<PackageReference Include="OpenTelemetry" Version="1.5.1" />
|
<PackageReference Include="OpenTelemetry" Version="1.6.0-alpha.1" />
|
||||||
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.5.1" />
|
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.6.0-alpha.1" />
|
||||||
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.5.0-beta.1" />
|
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.5.1-beta.1" />
|
||||||
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.5.0-beta.1" />
|
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.5.1-beta.1" />
|
||||||
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.5.0" />
|
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.5.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@ -25,7 +25,7 @@
|
|||||||
<forecolor value="Blue" />
|
<forecolor value="Blue" />
|
||||||
</mapping>
|
</mapping>
|
||||||
<layout type="log4net.Layout.PatternLayout">
|
<layout type="log4net.Layout.PatternLayout">
|
||||||
<conversionPattern value="%date{HH:mm:ss,fff} [%-2thread] %-5level %-15logger{1} %message%newline" />
|
<conversionPattern value="%date{HH:mm:ss,fff} [%3thread] %-5level %-15logger{1} %message%newline" />
|
||||||
</layout>
|
</layout>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user