Ocelot: Consul Service Discovery Not Working With Dynamic Routing

Created on 10 Oct 2018  路  12Comments  路  Source: ThreeMammals/Ocelot

Expected Behavior

Use Ocelot and Consul for service discovery and dynamic routing.

Actual Behavior

Without defining ReRoutes an error occurs.

Steps to Reproduce the Problem

  1. Setup Consul and register a service
  2. Setup Ocelot and provide configuration to talk to Consul with Ocelot.Provider.Consul
  3. Attempt to go to the route which should be dynamically routed.

Specifications

  • Version: 12.0.1
  • Platform: .Windows
  • Subsystem: NET Core 2.1

Error

dbug: Ocelot.Errors.Middleware.ExceptionHandlerMiddleware[0]
      requestId: 0HLHEQFFHMBL6:00000002, previousRequestId: no previous request id, message: ocelot pipeline started
dbug: Ocelot.DownstreamRouteFinder.Middleware.DownstreamRouteFinderMiddleware[0]
      requestId: 0HLHEQFFHMBL6:00000002, previousRequestId: no previous request id, message: Upstream url path is /background-forms-api/api/values
info: Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteProviderFactory[0]
      requestId: 0HLHEQFFHMBL6:00000002, previousRequestId: no previous request id, message: Selected DownstreamRouteCreator as DownstreamRouteProvider for this request
dbug: Ocelot.Errors.Middleware.ExceptionHandlerMiddleware[0]
      requestId: 0HLHEQFFHMBL6:00000002, previousRequestId: no previous request id, message: error calling middleware
fail: Ocelot.Errors.Middleware.ExceptionHandlerMiddleware[0]
      requestId: 0HLHEQFFHMBL6:00000002, previousRequestId: no previous request id, message: Exception caught in global error handler, exception message: The given key 'DownstreamRouteCreator' was not present in the dictionary., exception stack:    at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
         at Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteProviderFactory.Get(IInternalConfiguration config) in C:\projects\Ocelot\src\Ocelot\DownstreamRouteFinder\Finder\DownstreamRouteProviderFactory.cs:line 28
         at Ocelot.DownstreamRouteFinder.Middleware.DownstreamRouteFinderMiddleware.Invoke(DownstreamContext context) in C:\projects\Ocelot\src\Ocelot\DownstreamRouteFinder\Middleware\DownstreamRouteFinderMiddleware.cs:line 39
         at Ocelot.Responder.Middleware.ResponderMiddleware.Invoke(DownstreamContext context) in C:\projects\Ocelot\src\Ocelot\Responder\Middleware\ResponderMiddleware.cs:line 34
         at Ocelot.Middleware.Pipeline.MapWhenMiddleware.Invoke(DownstreamContext context) in C:\projects\Ocelot\src\Ocelot\Middleware\Pipeline\MapWhenMiddleware.cs:line 40
         at Ocelot.Errors.Middleware.ExceptionHandlerMiddleware.Invoke(DownstreamContext context) in C:\projects\Ocelot\src\Ocelot\Errors\Middleware\ExceptionHandlerMiddleware.cs:line 53 RequestId: 0HLHEQFFHMBL6:00000002, exception: System.Collections.Generic.KeyNotFoundException: The given key 'DownstreamRouteCreator' was not present in the dictionary.
         at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
         at Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteProviderFactory.Get(IInternalConfiguration config) in C:\projects\Ocelot\src\Ocelot\DownstreamRouteFinder\Finder\DownstreamRouteProviderFactory.cs:line 28
         at Ocelot.DownstreamRouteFinder.Middleware.DownstreamRouteFinderMiddleware.Invoke(DownstreamContext context) in C:\projects\Ocelot\src\Ocelot\DownstreamRouteFinder\Middleware\DownstreamRouteFinderMiddleware.cs:line 39
         at Ocelot.Responder.Middleware.ResponderMiddleware.Invoke(DownstreamContext context) in C:\projects\Ocelot\src\Ocelot\Responder\Middleware\ResponderMiddleware.cs:line 34
         at Ocelot.Middleware.Pipeline.MapWhenMiddleware.Invoke(DownstreamContext context) in C:\projects\Ocelot\src\Ocelot\Middleware\Pipeline\MapWhenMiddleware.cs:line 40
         at Ocelot.Errors.Middleware.ExceptionHandlerMiddleware.Invoke(DownstreamContext context) in C:\projects\Ocelot\src\Ocelot\Errors\Middleware\ExceptionHandlerMiddleware.cs:line 53
dbug: Ocelot.Errors.Middleware.ExceptionHandlerMiddleware[0]
      requestId: 0HLHEQFFHMBL6:00000002, previousRequestId: no previous request id, message: ocelot pipeline finished

Configuration

Ocelot

The configuration is pulled from appsettings.json:

{
  "ReRoutes": [],
  "Aggregates": [],
  "GlobalConfiguration": {
    "RequestIdKey": null,
    "ServiceDiscoveryProvider": {
      "ConfigurationKey": "Ocelot",
      "Host": "localhost",
      "Port": 8500,
      "Type": "Consul"
    },
    "RateLimitOptions": {
      "ClientIdHeader": "ClientId",
      "QuotaExceededMessage": null,
      "RateLimitCounterPrefix": "ocelot",
      "DisableRateLimitHeaders": false,
      "HttpStatusCode": 429
    },
    "QoSOptions": {
      "ExceptionsAllowedBeforeBreaking": 0,
      "DurationOfBreak": 0,
      "TimeoutValue": 0
    },
    "LoadBalancerOptions": {
      "Type": "LeastConnection"
    },
    "DownstreamScheme": "http",
    "HttpHandlerOptions": {
      "AllowAutoRedirect": false,
      "UseCookieContainer": false,
      "UseTracing": false
    }
  }
}

Consul

The service self-registers with Consul on startup.

{
    "ID": "098a60b3-9e77-d3e1-ccb7-56580afadb74",
    "Node": "54060bfe6310",
    "Address": "127.0.0.1",
    "Datacenter": "dc1",
    "TaggedAddresses": {
        "lan": "127.0.0.1",
        "wan": "127.0.0.1"
    },
    "NodeMeta": {
        "consul-network-segment": ""
    },
    "ServiceKind": "",
    "ServiceID": "background-forms-api-v1-final-01-192.168.1.203-5000",
    "ServiceName": "background-forms-api",
    "ServiceTags": [
        "Forms"
    ],
    "ServiceAddress": "192.168.1.203",
    "ServiceWeights": {
        "Passing": 1,
        "Warning": 1
    },
    "ServiceMeta": {
        "BoolTest": "\"True\"",
        "DecimalTest": "\"12.3\"",
        "Scopes": "[\"oidc\",\"name\",\"email\",\"gender\",\"birthdate\",\"zoneinfo\",\"locale\",\"phone_number\",\"address\"]",
        "StringTest": "\"Hello\""
    },
    "ServicePort": 5000,
    "ServiceEnableTagOverride": false,
    "ServiceProxyDestination": "",
    "ServiceConnect": {
        "Native": false,
        "Proxy": null
    },
    "CreateIndex": 396,
    "ModifyIndex": 580
}

Description

I've setup a basic API gateway in .NET Core 2.1 using Ocelot. The goal is to have the API gateway configure its routing based on the information inside of a service registry.

To meet this I've setup Consul and have services self-register as they come on-line. Ocelot should then be able to use Consul to determine the routes for downstream services.

When I attempt to do this per the configuration I get the above error. If I change my configuration to manually put the route information into ReRoutes Ocelot will detect the host and port information from Consul and redirect the request.

I tried to trace what is going on during the configuration of Ocelot. To me it seems that the ConsulProviderFactory.Get is never executed in the case where the ReRoutes array is empty.

bug help wanted merged

Most helpful comment

When will it be updated to the nuget repository?

All 12 comments

@mikejr83 thanks for your PR! I will merge it ASAP.

I have the same problem, please kindly release the new version as soon as possible

Dude, I can't wait for your version

LOL. I've been just building it and replacing the binary in the NuGet path. It was driving me bonkers on this PoC I'm working on.

@mikejr83 Thank you for your hard work

When will it be updated to the nuget repository?

Guys any plan to release new Nuget Package ? I need urgently use dynamic routes and this is blocking me!
Or release as beta this one :)
Thanks a lot!

me too. @thiagoloureiro

me too

Is there a new version? Have the same problem :(

The same problem锛孖 have to downgrade from 12.0.1 version to 12.0.0

available in version 13.0.0 on nuget

Was this page helpful?
0 / 5 - 0 ratings