diff --git a/src/Ocelot.Provider.Polly/PollyQoSResiliencePipelineProvider.cs b/src/Ocelot.Provider.Polly/PollyQoSResiliencePipelineProvider.cs index a0000c62d5..88d84db414 100644 --- a/src/Ocelot.Provider.Polly/PollyQoSResiliencePipelineProvider.cs +++ b/src/Ocelot.Provider.Polly/PollyQoSResiliencePipelineProvider.cs @@ -81,8 +81,8 @@ protected virtual ResiliencePipelineBuilder ConfigureCircui var info = $"Circuit Breaker for Route: {GetRouteName(route)}: "; var strategyOptions = new CircuitBreakerStrategyOptions { - FailureRatio = 0.8, - SamplingDuration = TimeSpan.FromSeconds(10), + FailureRatio = options.FailureRatio, + SamplingDuration = TimeSpan.FromSeconds(options.SamplingDuration), MinimumThroughput = options.ExceptionsAllowedBeforeBreaking, BreakDuration = options.DurationOfBreak > QoSOptions.LowBreakDuration ? TimeSpan.FromMilliseconds(options.DurationOfBreak) diff --git a/src/Ocelot/Configuration/QoSOptions.cs b/src/Ocelot/Configuration/QoSOptions.cs index 071bfbf95b..c36ce6cf69 100644 --- a/src/Ocelot/Configuration/QoSOptions.cs +++ b/src/Ocelot/Configuration/QoSOptions.cs @@ -23,7 +23,7 @@ public QoSOptions(FileQoSOptions from) public QoSOptions( int exceptionsAllowedBeforeBreaking, int durationOfBreak, - int timeoutValue, + int timeoutValue, string key) { DurationOfBreak = durationOfBreak; @@ -32,6 +32,36 @@ public QoSOptions( TimeoutValue = timeoutValue; } + public QoSOptions( + int exceptionsAllowedBeforeBreaking, + int durationOfBreak, + double failureRatio, + int timeoutValue, + string key) + { + DurationOfBreak = durationOfBreak; + ExceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking; + Key = key; + TimeoutValue = timeoutValue; + FailureRatio = failureRatio; + } + + public QoSOptions( + int exceptionsAllowedBeforeBreaking, + int durationOfBreak, + double failureRatio, + int samplingDuration, + int timeoutValue, + string key) + { + DurationOfBreak = durationOfBreak; + ExceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking; + Key = key; + TimeoutValue = timeoutValue; + FailureRatio = failureRatio; + SamplingDuration = samplingDuration; + } + /// How long the circuit should stay open before resetting in milliseconds. /// If using Polly version 8 or above, this value must be 500 (0.5 sec) or greater. /// An value (milliseconds). @@ -50,6 +80,22 @@ public QoSOptions( /// public int ExceptionsAllowedBeforeBreaking { get; } + /// + /// The failure-success ratio that will cause the circuit to break/open. + /// + /// + /// An 0.8 means 80% failed of all sampled executions. + /// + public double FailureRatio { get; } = .8; + + /// + /// The time period over which the failure-success ratio is calculated (in seconds). + /// + /// + /// An Time period in seconds, 10 means 10 seconds. + /// + public int SamplingDuration { get; } = 10; + public string Key { get; } /// diff --git a/test/Ocelot.AcceptanceTests/PollyQoSTests.cs b/test/Ocelot.AcceptanceTests/PollyQoSTests.cs index 5a086019ad..8edd816d8c 100644 --- a/test/Ocelot.AcceptanceTests/PollyQoSTests.cs +++ b/test/Ocelot.AcceptanceTests/PollyQoSTests.cs @@ -38,7 +38,7 @@ public override void Dispose() public void Should_not_timeout() { var port = PortFinder.GetRandomPort(); - var route = GivenRoute(port, new QoSOptions(10, 500, 1000, null), HttpMethods.Post); + var route = GivenRoute(port, new QoSOptions(10, 500, .5, 5, 1000, null), HttpMethods.Post); var configuration = GivenConfiguration(route); this.Given(x => x.GivenThereIsAServiceRunningOn(port, HttpStatusCode.OK, string.Empty, 10)) @@ -186,7 +186,7 @@ public void Should_timeout_per_default_after_90_seconds() var port = PortFinder.GetRandomPort(); var route = GivenRoute(port, new QoSOptions(new FileQoSOptions()), HttpMethods.Get); var configuration = GivenConfiguration(route); - + this.Given(x => x.GivenThereIsAServiceRunningOn(port, HttpStatusCode.Created, string.Empty, 3500)) // 3.5s > 3s -> ServiceUnavailable .And(x => GivenThereIsAConfiguration(configuration)) .And(x => GivenOcelotIsRunningWithPolly())