Browse Source

retry policy defined via config

pull/373/head
Igor Sychev 7 years ago
parent
commit
1b38589ff0
19 changed files with 191 additions and 54 deletions
  1. +5
    -4
      src/BuildingBlocks/EventBus/EventBusRabbitMQ/DefaultRabbitMQPersisterConnection.cs
  2. +4
    -3
      src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs
  3. +22
    -2
      src/Services/Basket/Basket.API/Startup.cs
  4. +2
    -1
      src/Services/Basket/Basket.API/appsettings.json
  5. +24
    -4
      src/Services/Catalog/Catalog.API/Startup.cs
  6. +2
    -1
      src/Services/Catalog/Catalog.API/appsettings.json
  7. +22
    -2
      src/Services/Location/Locations.API/Startup.cs
  8. +0
    -10
      src/Services/Location/Locations.API/appsettings.Development.json
  9. +2
    -1
      src/Services/Location/Locations.API/appsettings.json
  10. +23
    -2
      src/Services/Marketing/Marketing.API/Startup.cs
  11. +0
    -8
      src/Services/Marketing/Marketing.API/appsettings.Development.json
  12. +2
    -1
      src/Services/Marketing/Marketing.API/appsettings.json
  13. +22
    -2
      src/Services/Ordering/Ordering.API/Startup.cs
  14. +2
    -1
      src/Services/Ordering/Ordering.API/settings.json
  15. +22
    -2
      src/Services/Payment/Payment.API/Startup.cs
  16. +2
    -1
      src/Services/Payment/Payment.API/appsettings.json
  17. +14
    -7
      src/Web/WebMVC/Infrastructure/ResilientHttpClientFactory.cs
  18. +18
    -1
      src/Web/WebMVC/Startup.cs
  19. +3
    -1
      src/Web/WebMVC/appsettings.json

+ 5
- 4
src/BuildingBlocks/EventBus/EventBusRabbitMQ/DefaultRabbitMQPersisterConnection.cs View File

@ -15,16 +15,17 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
{
private readonly IConnectionFactory _connectionFactory;
private readonly ILogger<DefaultRabbitMQPersistentConnection> _logger;
private readonly int _retryCount;
IConnection _connection;
bool _disposed;
object sync_root = new object();
public DefaultRabbitMQPersistentConnection(IConnectionFactory connectionFactory,ILogger<DefaultRabbitMQPersistentConnection> logger)
public DefaultRabbitMQPersistentConnection(IConnectionFactory connectionFactory, ILogger<DefaultRabbitMQPersistentConnection> logger, int retryCount = 5)
{
_connectionFactory = connectionFactory ?? throw new ArgumentNullException(nameof(connectionFactory));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_retryCount = retryCount;
}
public bool IsConnected
@ -69,7 +70,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
{
var policy = RetryPolicy.Handle<SocketException>()
.Or<BrokerUnreachableException>()
.WaitAndRetry(5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) =>
.WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) =>
{
_logger.LogWarning(ex.ToString());
}
@ -88,7 +89,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
_connection.ConnectionBlocked += OnConnectionBlocked;
_logger.LogInformation($"RabbitMQ persistent connection acquired a connection {_connection.Endpoint.HostName} and is subscribed to failure events");
return true;
}
else


+ 4
- 3
src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs View File

@ -26,19 +26,20 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
private readonly IEventBusSubscriptionsManager _subsManager;
private readonly ILifetimeScope _autofac;
private readonly string AUTOFAC_SCOPE_NAME = "eshop_event_bus";
private readonly int _retryCount;
private IModel _consumerChannel;
private string _queueName;
public EventBusRabbitMQ(IRabbitMQPersistentConnection persistentConnection, ILogger<EventBusRabbitMQ> logger,
ILifetimeScope autofac, IEventBusSubscriptionsManager subsManager)
ILifetimeScope autofac, IEventBusSubscriptionsManager subsManager, int retryCount = 5)
{
_persistentConnection = persistentConnection ?? throw new ArgumentNullException(nameof(persistentConnection));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_subsManager = subsManager ?? new InMemoryEventBusSubscriptionsManager();
_consumerChannel = CreateConsumerChannel();
_autofac = autofac;
_retryCount = retryCount;
_subsManager.OnEventRemoved += SubsManager_OnEventRemoved;
}
@ -72,7 +73,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
var policy = RetryPolicy.Handle<BrokerUnreachableException>()
.Or<SocketException>()
.WaitAndRetry(5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) =>
.WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) =>
{
_logger.LogWarning(ex.ToString());
});


+ 22
- 2
src/Services/Basket/Basket.API/Startup.cs View File

@ -120,7 +120,13 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
factory.Password = Configuration["EventBusPassword"];
}
return new DefaultRabbitMQPersistentConnection(factory, logger);
var retryCount = 5;
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"]))
{
retryCount = int.Parse(Configuration["EventBusRetryCount"]);
}
return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount);
});
}
@ -247,7 +253,21 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
}
else
{
services.AddSingleton<IEventBus, EventBusRabbitMQ>();
services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp =>
{
var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>();
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
var retryCount = 5;
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"]))
{
retryCount = int.Parse(Configuration["EventBusRetryCount"]);
}
return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, retryCount);
});
}
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();


+ 2
- 1
src/Services/Basket/Basket.API/appsettings.json View File

@ -13,5 +13,6 @@
"SubscriptionClientName": "Basket",
"ApplicationInsights": {
"InstrumentationKey": ""
}
},
"EventBusRetryCount": 5
}

+ 24
- 4
src/Services/Catalog/Catalog.API/Startup.cs View File

@ -35,7 +35,7 @@
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public IConfiguration Configuration { get; }
public IServiceProvider ConfigureServices(IServiceCollection services)
{
@ -161,7 +161,13 @@
factory.Password = Configuration["EventBusPassword"];
}
return new DefaultRabbitMQPersistentConnection(factory, logger);
var retryCount = 5;
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"]))
{
retryCount = int.Parse(Configuration["EventBusRetryCount"]);
}
return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount);
});
}
@ -188,7 +194,7 @@
loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
app.UsePathBase(pathBase);
}
app.UseCors("CorsPolicy");
app.UseMvcWithDefaultRoute();
@ -221,7 +227,21 @@
}
else
{
services.AddSingleton<IEventBus, EventBusRabbitMQ>();
services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp =>
{
var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>();
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
var retryCount = 5;
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"]))
{
retryCount = int.Parse(Configuration["EventBusRetryCount"]);
}
return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, retryCount);
});
}
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();


+ 2
- 1
src/Services/Catalog/Catalog.API/appsettings.json View File

@ -15,5 +15,6 @@
"SubscriptionClientName": "Catalog",
"ApplicationInsights": {
"InstrumentationKey": ""
}
},
"EventBusRetryCount": 5
}

+ 22
- 2
src/Services/Location/Locations.API/Startup.cs View File

@ -87,7 +87,13 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API
factory.Password = Configuration["EventBusPassword"];
}
return new DefaultRabbitMQPersistentConnection(factory, logger);
var retryCount = 5;
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"]))
{
retryCount = int.Parse(Configuration["EventBusRetryCount"]);
}
return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount);
});
}
@ -217,7 +223,21 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API
}
else
{
services.AddSingleton<IEventBus, EventBusRabbitMQ>();
services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp =>
{
var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>();
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
var retryCount = 5;
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"]))
{
retryCount = int.Parse(Configuration["EventBusRetryCount"]);
}
return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, retryCount);
});
}
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();


+ 0
- 10
src/Services/Location/Locations.API/appsettings.Development.json View File

@ -1,10 +0,0 @@
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}

+ 2
- 1
src/Services/Location/Locations.API/appsettings.json View File

@ -14,5 +14,6 @@
"SubscriptionClientName": "Locations",
"ApplicationInsights": {
"InstrumentationKey": ""
}
},
"EventBusRetryCount": 5
}

+ 23
- 2
src/Services/Marketing/Marketing.API/Startup.cs View File

@ -122,7 +122,14 @@
{
factory.Password = Configuration["EventBusPassword"];
}
return new DefaultRabbitMQPersistentConnection(factory, logger);
var retryCount = 5;
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"]))
{
retryCount = int.Parse(Configuration["EventBusRetryCount"]);
}
return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount);
});
}
@ -242,7 +249,21 @@
}
else
{
services.AddSingleton<IEventBus, EventBusRabbitMQ>();
services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp =>
{
var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>();
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
var retryCount = 5;
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"]))
{
retryCount = int.Parse(Configuration["EventBusRetryCount"]);
}
return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, retryCount);
});
}
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();


+ 0
- 8
src/Services/Marketing/Marketing.API/appsettings.Development.json View File

@ -1,8 +0,0 @@
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning"
}
}
}

+ 2
- 1
src/Services/Marketing/Marketing.API/appsettings.json View File

@ -15,5 +15,6 @@
"AzureStorageEnabled": false,
"ApplicationInsights": {
"InstrumentationKey": ""
}
},
"EventBusRetryCount": 5
}

+ 22
- 2
src/Services/Ordering/Ordering.API/Startup.cs View File

@ -180,7 +180,13 @@
factory.Password = Configuration["EventBusPassword"];
}
return new DefaultRabbitMQPersistentConnection(factory, logger);
var retryCount = 5;
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"]))
{
retryCount = int.Parse(Configuration["EventBusRetryCount"]);
}
return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount);
});
}
@ -284,7 +290,21 @@
}
else
{
services.AddSingleton<IEventBus, EventBusRabbitMQ>();
services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp =>
{
var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>();
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
var retryCount = 5;
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"]))
{
retryCount = int.Parse(Configuration["EventBusRetryCount"]);
}
return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, retryCount);
});
}
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();


+ 2
- 1
src/Services/Ordering/Ordering.API/settings.json View File

@ -16,5 +16,6 @@
"CheckUpdateTime": "30000",
"ApplicationInsights": {
"InstrumentationKey": ""
}
},
"EventBusRetryCount": 5
}

+ 22
- 2
src/Services/Payment/Payment.API/Startup.cs View File

@ -74,7 +74,13 @@ namespace Payment.API
factory.Password = Configuration["EventBusPassword"];
}
return new DefaultRabbitMQPersistentConnection(factory, logger);
var retryCount = 5;
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"]))
{
retryCount = int.Parse(Configuration["EventBusRetryCount"]);
}
return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount);
});
}
@ -123,7 +129,21 @@ namespace Payment.API
}
else
{
services.AddSingleton<IEventBus, EventBusRabbitMQ>();
services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp =>
{
var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>();
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
var retryCount = 5;
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"]))
{
retryCount = int.Parse(Configuration["EventBusRetryCount"]);
}
return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, retryCount);
});
}
services.AddTransient<OrderStatusChangedToStockConfirmedIntegrationEventHandler>();


+ 2
- 1
src/Services/Payment/Payment.API/appsettings.json View File

@ -10,5 +10,6 @@
"SubscriptionClientName": "Payment",
"ApplicationInsights": {
"InstrumentationKey": ""
}
},
"EventBusRetryCount": 5
}

+ 14
- 7
src/Web/WebMVC/Infrastructure/ResilientHttpClientFactory.cs View File

@ -9,11 +9,18 @@ namespace Microsoft.eShopOnContainers.WebMVC.Infrastructure
public class ResilientHttpClientFactory : IResilientHttpClientFactory
{
private readonly ILogger<ResilientHttpClient> _logger;
private readonly int _retryCount;
private readonly int _exceptionsAllowedBeforeBreaking;
public ResilientHttpClientFactory(ILogger<ResilientHttpClient> logger)
=>_logger = logger;
public ResilientHttpClientFactory(ILogger<ResilientHttpClient> logger, int exceptionsAllowedBeforeBreaking = 5, int retryCount = 6)
{
_logger = logger;
_exceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
_retryCount = retryCount;
}
public ResilientHttpClient CreateResilientHttpClient()
public ResilientHttpClient CreateResilientHttpClient()
=> new ResilientHttpClient((origin) => CreatePolicies(), _logger);
private Policy[] CreatePolicies()
@ -22,7 +29,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.Infrastructure
Policy.Handle<HttpRequestException>()
.WaitAndRetryAsync(
// number of retries
6,
_retryCount,
// exponential backofff
retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
// on retry
@ -36,9 +43,9 @@ namespace Microsoft.eShopOnContainers.WebMVC.Infrastructure
_logger.LogDebug(msg);
}),
Policy.Handle<HttpRequestException>()
.CircuitBreakerAsync(
.CircuitBreakerAsync(
// number of exceptions before breaking circuit
5,
_exceptionsAllowedBeforeBreaking,
// time circuit opened before retry
TimeSpan.FromMinutes(1),
(exception, duration) =>
@ -51,6 +58,6 @@ namespace Microsoft.eShopOnContainers.WebMVC.Infrastructure
// on circuit closed
_logger.LogTrace("Circuit breaker reset");
})
};
};
}
}

+ 18
- 1
src/Web/WebMVC/Startup.cs View File

@ -79,7 +79,24 @@ namespace Microsoft.eShopOnContainers.WebMVC
if (Configuration.GetValue<string>("UseResilientHttp") == bool.TrueString)
{
services.AddSingleton<IResilientHttpClientFactory, ResilientHttpClientFactory>();
services.AddSingleton<IResilientHttpClientFactory, ResilientHttpClientFactory>(sp =>
{
var logger = sp.GetRequiredService<ILogger<ResilientHttpClient>>();
var retryCount = 6;
if (!string.IsNullOrEmpty(Configuration["HttpClientRetryCount"]))
{
retryCount = int.Parse(Configuration["HttpClientRetryCount"]);
}
var exceptionsAllowedBeforeBreaking = 5;
if (!string.IsNullOrEmpty(Configuration["HttpClientExceptionsAllowedBeforeBreaking"]))
{
exceptionsAllowedBeforeBreaking = int.Parse(Configuration["HttpClientExceptionsAllowedBeforeBreaking"]);
}
return new ResilientHttpClientFactory(logger, exceptionsAllowedBeforeBreaking, retryCount);
});
services.AddSingleton<IHttpClient, ResilientHttpClient>(sp => sp.GetService<IResilientHttpClientFactory>().CreateResilientHttpClient());
}
else


+ 3
- 1
src/Web/WebMVC/appsettings.json View File

@ -21,5 +21,7 @@
},
"ApplicationInsights": {
"InstrumentationKey": ""
}
},
"HttpClientRetryCount": 6,
"HttpClientExceptionsAllowedBeforeBreaking": 5
}

Loading…
Cancel
Save