Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Route key is not unique when using Host header for service discovery #1496

Closed
sliekens opened this issue Jul 22, 2021 · 5 comments · Fixed by #1944
Closed

Route key is not unique when using Host header for service discovery #1496

sliekens opened this issue Jul 22, 2021 · 5 comments · Fixed by #1944
Assignees
Labels
bug Identified as a potential bug Jan'24 January 2024 release Load Balancer Ocelot feature: Load Balancer merged Issue has been merged to dev and is waiting for the next release proposal Proposal for a new functionality in Ocelot Service Discovery Ocelot feature: Service Discovery
Milestone

Comments

@sliekens
Copy link
Contributor

sliekens commented Jul 22, 2021

Expected Behavior

The RouteKey format should include a route's ServiceName when you use service discovery: "UpstreamPathTemplate|UpstreamHttpMethod|ServiceName".

Actual Behavior

The default format is "UpstreamPathTemplate|UpstreamHttpMethod|DownstreamHostAndPorts". The last section resolves to an empty string when you use service discovery: "/some-path|GET|".

This leads to conflicts when multiple routes have the same upstream method and path template, but are discriminated by an UpstreamHost.

Steps to Reproduce the Problem

  1. Create two routes with identical UpstreamPathTemplate and UpstreamHttpMethod
  2. Give each route a unique UpstreamHost
  3. Do not configure the DownstreamHostAndPorts, instead configure a ServiceName and a ServiceDiscoveryProvider.
{
  "GlobalConfiguration": {
    "ServiceDiscoveryProvider": {
      "Scheme": "https",
      "Host": "localhost",
      "Port": 8500,
      "Type": "Consul"
    }
  },
  "Routes": [
    {
      "UpstreamHost": "api.contoso.de",
      "ServiceName": "BackofficeGermany",
      "UpstreamPathTemplate": "/some-path",
      "UpstreamHttpMethod": [ "Get" ],
      "DownstreamPathTemplate": "/some/path",
      "DownstreamScheme": "https"
    },
    {
      "UpstreamHost": "api.contoso.fr",
      "ServiceName": "BackofficeFrance",
      "UpstreamPathTemplate": "/some-path",
      "UpstreamHttpMethod": [ "Get" ],
      "DownstreamPathTemplate": "/some/path",
      "DownstreamScheme": "https"
    }
  ]
}

Now when you send two requests, once for each route:

GET /some-path HTTP/1.1
Host: api.contoso.de


GET /some-path HTTP/1.1
Host: api.contoso.fr


The first request initiates service discovery, which resolves the host and port for BackofficeGermany. The resolved configuration is stored in the ILoadBalancerHouse with the key "/some-path|GET|" .

The second request has the same route key so the ILoadBalancerHouse entirely skips the service discovery step. Instead it reuses the configuration for BackofficeGermany, which is wrong.

Specifications

  • Version: 16.0.1
  • Platform: netcoreapp3.1
  • Subsystem: ??
@raman-m
Copy link
Member

raman-m commented Jan 21, 2024

@sliekens
Hi Steven!
I don't get you!...
Seems you request new feature in service discovery feature...
Let me ask our Consul, @ggnaegi, the expert in Service Discovery feature.

@raman-m raman-m added question Initially seen a question could become a new feature or bug or closed ;) proposal Proposal for a new functionality in Ocelot waiting Waiting for answer to question or feedback from issue raiser Service Discovery Ocelot feature: Service Discovery labels Jan 21, 2024
@sliekens
Copy link
Contributor Author

It's not a feature request, it's a problem with service discovery caching. The wrong route is reused from cache. A false cache hit, basically, because the route key does not include the service name.

@raman-m
Copy link
Member

raman-m commented Jan 22, 2024

Actual Behavior

The default format is UpstreamPathTemplate|UpstreamHttpMethod|DownstreamHostAndPorts. The last section resolves to an empty string when you use service discovery: /some-path|GET|.
This leads to conflicts when multiple routes have the same upstream method and path template, but are discriminated by an UpstreamHost.

@sliekens 🆗 Got it now!
We will look into the code...
Why not create a PR by you? 😉

I guess we need this key construction template: ServiceName|UpstreamPathTemplate|UpstreamHttpMethod
So, service name should have higher priority over path and method.

Also, UpstreamHost could be a last suffix in caching key... What do you think?
Finally, the complete pattern will be ServiceName|UpstreamPathTemplate|UpstreamHttpMethod|UpstreamHost

@sliekens
Copy link
Contributor Author

Yep, that looks correct to me.

sliekens added a commit to sliekens/Ocelot that referenced this issue Jan 27, 2024
The old key format did not contain enough information to disambiguate routes based on an UpstreamHost. This was especially problematic when a ServiceName was used in conjuction with Service Discovery, instead of DownstreamHostAndPorts configuration.

Resolves ThreeMammals#1496
@sliekens
Copy link
Contributor Author

@raman-m I created a PR, the final pattern is a bit different, but it shouldn't matter. The route key is treated as an opaque string once it's created.

@raman-m raman-m added bug Identified as a potential bug accepted Bug or feature would be accepted as a PR or is being worked on and removed question Initially seen a question could become a new feature or bug or closed ;) waiting Waiting for answer to question or feedback from issue raiser labels Jan 27, 2024
@raman-m raman-m added this to the January'24 milestone Jan 27, 2024
@raman-m raman-m added Jan'24 January 2024 release Load Balancer Ocelot feature: Load Balancer labels Jan 27, 2024
raman-m pushed a commit to sliekens/Ocelot that referenced this issue Feb 16, 2024
The old key format did not contain enough information to disambiguate routes based on an UpstreamHost. This was especially problematic when a ServiceName was used in conjuction with Service Discovery, instead of DownstreamHostAndPorts configuration.

Resolves ThreeMammals#1496
raman-m pushed a commit to sliekens/Ocelot that referenced this issue Feb 27, 2024
The old key format did not contain enough information to disambiguate routes based on an UpstreamHost. This was especially problematic when a ServiceName was used in conjuction with Service Discovery, instead of DownstreamHostAndPorts configuration.

Resolves ThreeMammals#1496
@raman-m raman-m added merged Issue has been merged to dev and is waiting for the next release and removed accepted Bug or feature would be accepted as a PR or is being worked on labels Feb 29, 2024
@raman-m raman-m mentioned this issue Mar 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Identified as a potential bug Jan'24 January 2024 release Load Balancer Ocelot feature: Load Balancer merged Issue has been merged to dev and is waiting for the next release proposal Proposal for a new functionality in Ocelot Service Discovery Ocelot feature: Service Discovery
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants