From 3c125a2590a8776272b7c7445d02688e3a6d6382 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raynald=20Messi=C3=A9?= Date: Wed, 29 May 2024 16:04:46 +0200 Subject: [PATCH] #2080 Adds parameters (in this case those of Polly V8) to fine-tune circuit-breaker behavior --- .../PollyQoSResiliencePipelineProvider.cs | 8 ++-- src/Ocelot/Configuration/QoSOptions.cs | 48 ++++++++++++++++++- test/Ocelot.AcceptanceTests/PollyQoSTests.cs | 2 +- 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/Ocelot.Provider.Polly/PollyQoSResiliencePipelineProvider.cs b/src/Ocelot.Provider.Polly/PollyQoSResiliencePipelineProvider.cs index be2df16b3..6486589d1 100644 --- a/src/Ocelot.Provider.Polly/PollyQoSResiliencePipelineProvider.cs +++ b/src/Ocelot.Provider.Polly/PollyQoSResiliencePipelineProvider.cs @@ -32,7 +32,7 @@ public ResiliencePipeline GetResiliencePipeline(DownstreamR var options = route.QosOptions; // Check if we need pipeline at all before calling GetOrAddPipeline - if (options is null || + if (options is null || options.UseQos == false || (options.ExceptionsAllowedBeforeBreaking == 0 && options.TimeoutValue is int.MaxValue)) { return null; // shortcut > no qos @@ -48,6 +48,8 @@ private void PollyResiliencePipelineWrapperFactory(ResiliencePipelineBuilder no qos + // Add TimeoutStrategy if TimeoutValue is not int.MaxValue and greater than 0 if (options.TimeoutValue != int.MaxValue && options.TimeoutValue > 0) { @@ -64,8 +66,8 @@ private void PollyResiliencePipelineWrapperFactory(ResiliencePipelineBuilder { - FailureRatio = 0.8, - SamplingDuration = TimeSpan.FromSeconds(10), + FailureRatio = options.FailureRatio, + SamplingDuration = TimeSpan.FromSeconds(options.SamplingDuration), MinimumThroughput = options.ExceptionsAllowedBeforeBreaking, BreakDuration = TimeSpan.FromMilliseconds(options.DurationOfBreak), ShouldHandle = new PredicateBuilder() diff --git a/src/Ocelot/Configuration/QoSOptions.cs b/src/Ocelot/Configuration/QoSOptions.cs index e1897bc58..b601ef91d 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. /// @@ -54,6 +84,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 597731755..dc75b3957 100644 --- a/test/Ocelot.AcceptanceTests/PollyQoSTests.cs +++ b/test/Ocelot.AcceptanceTests/PollyQoSTests.cs @@ -44,7 +44,7 @@ public override void Dispose() public void Should_not_timeout() { var port = PortFinder.GetRandomPort(); - var configuration = FileConfigurationFactory(port, new QoSOptions(10, 500, 1000, null), HttpMethods.Post); + var configuration = FileConfigurationFactory(port, new QoSOptions(10, 500,.5,5, 1000, null), HttpMethods.Post); this.Given(x => x.GivenThereIsAServiceRunningOn($"http://localhost:{port}", 200, string.Empty, 10)) .And(x => GivenThereIsAConfiguration(configuration))