mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 18:22:49 +08:00
Checkin for caching the template matching for significant route finder performance improvements (#728)
This commit is contained in:
parent
ac211886f1
commit
9bbb6364f2
@ -28,7 +28,7 @@ namespace Ocelot.DownstreamRouteFinder.Finder
|
|||||||
|
|
||||||
foreach (var reRoute in applicableReRoutes)
|
foreach (var reRoute in applicableReRoutes)
|
||||||
{
|
{
|
||||||
var urlMatch = _urlMatcher.Match(upstreamUrlPath, upstreamQueryString, reRoute.UpstreamTemplatePattern.Template, reRoute.UpstreamTemplatePattern.ContainsQueryString);
|
var urlMatch = _urlMatcher.Match(upstreamUrlPath, upstreamQueryString, reRoute.UpstreamTemplatePattern);
|
||||||
|
|
||||||
if (urlMatch.Data.Match)
|
if (urlMatch.Data.Match)
|
||||||
{
|
{
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
|
using Ocelot.Values;
|
||||||
|
|
||||||
namespace Ocelot.DownstreamRouteFinder.UrlMatcher
|
namespace Ocelot.DownstreamRouteFinder.UrlMatcher
|
||||||
{
|
{
|
||||||
public interface IUrlPathToUrlTemplateMatcher
|
public interface IUrlPathToUrlTemplateMatcher
|
||||||
{
|
{
|
||||||
Response<UrlMatch> Match(string upstreamUrlPath, string upstreamQueryString, string upstreamUrlPathTemplate, bool containsQueryString);
|
Response<UrlMatch> Match(string upstreamUrlPath, string upstreamQueryString, UpstreamPathTemplate pathTemplate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,21 @@
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
|
using Ocelot.Values;
|
||||||
|
|
||||||
namespace Ocelot.DownstreamRouteFinder.UrlMatcher
|
namespace Ocelot.DownstreamRouteFinder.UrlMatcher
|
||||||
{
|
{
|
||||||
public class RegExUrlMatcher : IUrlPathToUrlTemplateMatcher
|
public class RegExUrlMatcher : IUrlPathToUrlTemplateMatcher
|
||||||
{
|
{
|
||||||
public Response<UrlMatch> Match(string upstreamUrlPath, string upstreamQueryString, string upstreamUrlPathTemplate, bool containsQueryString)
|
public Response<UrlMatch> Match(string upstreamUrlPath, string upstreamQueryString, UpstreamPathTemplate pathTemplate)
|
||||||
{
|
{
|
||||||
var regex = new Regex(upstreamUrlPathTemplate);
|
if (!pathTemplate.ContainsQueryString)
|
||||||
|
|
||||||
if (!containsQueryString)
|
|
||||||
{
|
{
|
||||||
return regex.IsMatch(upstreamUrlPath)
|
return pathTemplate.Pattern.IsMatch(upstreamUrlPath)
|
||||||
? new OkResponse<UrlMatch>(new UrlMatch(true))
|
? new OkResponse<UrlMatch>(new UrlMatch(true))
|
||||||
: new OkResponse<UrlMatch>(new UrlMatch(false));
|
: new OkResponse<UrlMatch>(new UrlMatch(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
return regex.IsMatch($"{upstreamUrlPath}{upstreamQueryString}")
|
return pathTemplate.Pattern.IsMatch($"{upstreamUrlPath}{upstreamQueryString}")
|
||||||
? new OkResponse<UrlMatch>(new UrlMatch(true))
|
? new OkResponse<UrlMatch>(new UrlMatch(true))
|
||||||
: new OkResponse<UrlMatch>(new UrlMatch(false));
|
: new OkResponse<UrlMatch>(new UrlMatch(false));
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace Ocelot.Values
|
namespace Ocelot.Values
|
||||||
{
|
{
|
||||||
public class UpstreamPathTemplate
|
public class UpstreamPathTemplate
|
||||||
@ -8,6 +10,9 @@ namespace Ocelot.Values
|
|||||||
Priority = priority;
|
Priority = priority;
|
||||||
ContainsQueryString = containsQueryString;
|
ContainsQueryString = containsQueryString;
|
||||||
OriginalValue = originalValue;
|
OriginalValue = originalValue;
|
||||||
|
Pattern = template == null ?
|
||||||
|
new Regex("$^", RegexOptions.Compiled | RegexOptions.Singleline) :
|
||||||
|
new Regex(template, RegexOptions.Compiled | RegexOptions.Singleline);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Template { get; }
|
public string Template { get; }
|
||||||
@ -17,5 +22,7 @@ namespace Ocelot.Values
|
|||||||
public bool ContainsQueryString { get; }
|
public bool ContainsQueryString { get; }
|
||||||
|
|
||||||
public string OriginalValue { get; }
|
public string OriginalValue { get; }
|
||||||
|
|
||||||
|
public Regex Pattern { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ using BenchmarkDotNet.Configs;
|
|||||||
using BenchmarkDotNet.Diagnosers;
|
using BenchmarkDotNet.Diagnosers;
|
||||||
using BenchmarkDotNet.Validators;
|
using BenchmarkDotNet.Validators;
|
||||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||||
|
using Ocelot.Values;
|
||||||
|
|
||||||
namespace Ocelot.Benchmarks
|
namespace Ocelot.Benchmarks
|
||||||
{
|
{
|
||||||
@ -12,8 +13,8 @@ namespace Ocelot.Benchmarks
|
|||||||
public class UrlPathToUrlPathTemplateMatcherBenchmarks : ManualConfig
|
public class UrlPathToUrlPathTemplateMatcherBenchmarks : ManualConfig
|
||||||
{
|
{
|
||||||
private RegExUrlMatcher _urlPathMatcher;
|
private RegExUrlMatcher _urlPathMatcher;
|
||||||
|
private UpstreamPathTemplate _pathTemplate;
|
||||||
private string _downstreamUrlPath;
|
private string _downstreamUrlPath;
|
||||||
private string _downstreamUrlPathTemplate;
|
|
||||||
private string _upstreamQuery;
|
private string _upstreamQuery;
|
||||||
|
|
||||||
public UrlPathToUrlPathTemplateMatcherBenchmarks()
|
public UrlPathToUrlPathTemplateMatcherBenchmarks()
|
||||||
@ -27,14 +28,14 @@ namespace Ocelot.Benchmarks
|
|||||||
public void SetUp()
|
public void SetUp()
|
||||||
{
|
{
|
||||||
_urlPathMatcher = new RegExUrlMatcher();
|
_urlPathMatcher = new RegExUrlMatcher();
|
||||||
|
_pathTemplate = new UpstreamPathTemplate("api/product/products/{productId}/variants/", 0, false, null);
|
||||||
_downstreamUrlPath = "api/product/products/1/variants/?soldout=false";
|
_downstreamUrlPath = "api/product/products/1/variants/?soldout=false";
|
||||||
_downstreamUrlPathTemplate = "api/product/products/{productId}/variants/";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Benchmark(Baseline = true)]
|
[Benchmark(Baseline = true)]
|
||||||
public void Baseline()
|
public void Baseline()
|
||||||
{
|
{
|
||||||
_urlPathMatcher.Match(_downstreamUrlPath, _upstreamQuery, _downstreamUrlPathTemplate, false);
|
_urlPathMatcher.Match(_downstreamUrlPath, _upstreamQuery, _pathTemplate);
|
||||||
}
|
}
|
||||||
|
|
||||||
// * Summary *
|
// * Summary *
|
||||||
|
@ -624,7 +624,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
|
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
|
||||||
.And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
|
.And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
|
||||||
.When(x => x.WhenICallTheFinder())
|
.When(x => x.WhenICallTheFinder())
|
||||||
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly(1))
|
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly(1, 0))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -677,7 +677,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "test"))
|
.WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "test"))
|
||||||
.Build()
|
.Build()
|
||||||
)))
|
)))
|
||||||
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly(2))
|
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly(1, 0))
|
||||||
|
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly(1, 1))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -706,32 +707,32 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
private void ThenTheUrlMatcherIsCalledCorrectly()
|
private void ThenTheUrlMatcherIsCalledCorrectly()
|
||||||
{
|
{
|
||||||
_mockMatcher
|
_mockMatcher
|
||||||
.Verify(x => x.Match(_upstreamUrlPath, _upstreamQuery, _reRoutesConfig[0].UpstreamTemplatePattern.Template, _reRoutesConfig[0].UpstreamTemplatePattern.ContainsQueryString), Times.Once);
|
.Verify(x => x.Match(_upstreamUrlPath, _upstreamQuery, _reRoutesConfig[0].UpstreamTemplatePattern), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheUrlMatcherIsCalledCorrectly(int times)
|
private void ThenTheUrlMatcherIsCalledCorrectly(int times, int index = 0)
|
||||||
{
|
{
|
||||||
_mockMatcher
|
_mockMatcher
|
||||||
.Verify(x => x.Match(_upstreamUrlPath, _upstreamQuery, _reRoutesConfig[0].UpstreamTemplatePattern.OriginalValue, _reRoutesConfig[0].UpstreamTemplatePattern.ContainsQueryString), Times.Exactly(times));
|
.Verify(x => x.Match(_upstreamUrlPath, _upstreamQuery, _reRoutesConfig[index].UpstreamTemplatePattern), Times.Exactly(times));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheUrlMatcherIsCalledCorrectly(string expectedUpstreamUrlPath)
|
private void ThenTheUrlMatcherIsCalledCorrectly(string expectedUpstreamUrlPath)
|
||||||
{
|
{
|
||||||
_mockMatcher
|
_mockMatcher
|
||||||
.Verify(x => x.Match(expectedUpstreamUrlPath, _upstreamQuery, _reRoutesConfig[0].UpstreamTemplatePattern.OriginalValue, _reRoutesConfig[0].UpstreamTemplatePattern.ContainsQueryString), Times.Once);
|
.Verify(x => x.Match(expectedUpstreamUrlPath, _upstreamQuery, _reRoutesConfig[0].UpstreamTemplatePattern), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheUrlMatcherIsNotCalled()
|
private void ThenTheUrlMatcherIsNotCalled()
|
||||||
{
|
{
|
||||||
_mockMatcher
|
_mockMatcher
|
||||||
.Verify(x => x.Match(_upstreamUrlPath, _upstreamQuery, _reRoutesConfig[0].UpstreamTemplatePattern.OriginalValue, _reRoutesConfig[0].UpstreamTemplatePattern.ContainsQueryString), Times.Never);
|
.Verify(x => x.Match(_upstreamUrlPath, _upstreamQuery, _reRoutesConfig[0].UpstreamTemplatePattern), Times.Never);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheUrlMatcherReturns(Response<UrlMatch> match)
|
private void GivenTheUrlMatcherReturns(Response<UrlMatch> match)
|
||||||
{
|
{
|
||||||
_match = match;
|
_match = match;
|
||||||
_mockMatcher
|
_mockMatcher
|
||||||
.Setup(x => x.Match(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>()))
|
.Setup(x => x.Match(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<UpstreamPathTemplate>()))
|
||||||
.Returns(_match);
|
.Returns(_match);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
|
using Ocelot.Values;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
@ -270,7 +271,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
|
|||||||
|
|
||||||
private void WhenIMatchThePaths()
|
private void WhenIMatchThePaths()
|
||||||
{
|
{
|
||||||
_result = _urlMatcher.Match(_path, _queryString, _downstreamPathTemplate, _containsQueryString);
|
_result = _urlMatcher.Match(_path, _queryString, new UpstreamPathTemplate(_downstreamPathTemplate, 0, _containsQueryString, _downstreamPathTemplate));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheResultIsTrue()
|
private void ThenTheResultIsTrue()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user