Fixed issue where qos was being created for each request so circuit breaker was never stopping traffic going to downstream service.

This commit is contained in:
TomPallister
2017-02-11 18:56:36 +00:00
parent 820673dda8
commit 286c7f8488
30 changed files with 819 additions and 184 deletions

View File

@ -15,16 +15,16 @@ namespace Ocelot.AcceptanceTests
{
public class QoSTests : IDisposable
{
private IWebHost _builder;
private IWebHost _brokenService;
private readonly Steps _steps;
private int _requestCount;
private IWebHost _workingService;
public QoSTests()
{
_steps = new Steps();
}
[Fact]
public void should_open_circuit_breaker_then_close()
{
@ -50,33 +50,90 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "Hello from Laura"))
this.Given(x => x.GivenThereIsAPossiblyBrokenServiceRunningOn("http://localhost:51879", "Hello from Laura"))
.Given(x => _steps.GivenThereIsAConfiguration(configuration))
.Given(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.Given(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Given(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.RequestTimeout))
.Given(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.ServiceUnavailable))
.Given(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Given(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.RequestTimeout))
.Given(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.ServiceUnavailable))
.Given(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Given(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.RequestTimeout))
.Given(x => x.GivenIWaitMilliSeconds(2000))
.Given(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.ServiceUnavailable))
.Given(x => x.GivenIWaitMilliseconds(3000))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.BDDfy();
}
private void GivenIWaitMilliSeconds(int ms)
[Fact]
public void open_circuit_should_not_effect_different_reRoute()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHost = "localhost",
DownstreamPort = 51879,
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
QoSOptions = new FileQoSOptions
{
ExceptionsAllowedBeforeBreaking = 1,
TimeoutValue = 500,
DurationOfBreak = 1000
}
},
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHost = "localhost",
DownstreamPort = 51880,
UpstreamPathTemplate = "working",
UpstreamHttpMethod = "Get",
}
}
};
this.Given(x => x.GivenThereIsAPossiblyBrokenServiceRunningOn("http://localhost:51879", "Hello from Laura"))
.And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51880/", 200, "Hello from Tom"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.And(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.And(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.And(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.And(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.ServiceUnavailable))
.And(x => _steps.WhenIGetUrlOnTheApiGateway("/working"))
.And(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Tom"))
.And(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.And(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.ServiceUnavailable))
.And(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.And(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.ServiceUnavailable))
.And(x => x.GivenIWaitMilliseconds(3000))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.BDDfy();
}
private void GivenIWaitMilliseconds(int ms)
{
Thread.Sleep(ms);
}
private void GivenThereIsAServiceRunningOn(string url, string responseBody)
private void GivenThereIsAPossiblyBrokenServiceRunningOn(string url, string responseBody)
{
_builder = new WebHostBuilder()
_brokenService = new WebHostBuilder()
.UseUrls(url)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
@ -95,7 +152,7 @@ namespace Ocelot.AcceptanceTests
return;
}
//request one times out and polly throws exception
//request one times out and polly throws exception, circuit opens
if (_requestCount == 1)
{
_requestCount++;
@ -104,17 +161,8 @@ namespace Ocelot.AcceptanceTests
return;
}
//request two times out and polly throws exception circuit opens
if (_requestCount == 2)
{
_requestCount++;
await Task.Delay(1000);
context.Response.StatusCode = 200;
return;
}
//after break closes we return 200 OK
if (_requestCount == 3)
if (_requestCount == 2)
{
context.Response.StatusCode = 200;
await context.Response.WriteAsync(responseBody);
@ -124,12 +172,34 @@ namespace Ocelot.AcceptanceTests
})
.Build();
_builder.Start();
_brokenService.Start();
}
private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody)
{
_workingService = new WebHostBuilder()
.UseUrls(url)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseUrls(url)
.Configure(app =>
{
app.Run(async context =>
{
context.Response.StatusCode = statusCode;
await context.Response.WriteAsync(responseBody);
});
})
.Build();
_workingService.Start();
}
public void Dispose()
{
_builder?.Dispose();
_workingService?.Dispose();
_brokenService?.Dispose();
_steps.Dispose();
}
}