ThreeMammals / Ocelot

.NET API Gateway
https://www.nuget.org/packages/Ocelot
MIT License
8.4k stars 1.64k forks source link

Feature Request: Dynamic Service Registration via Reverse Connection #1271

Closed Danielku15 closed 5 months ago

Danielku15 commented 4 years ago

Expected Behavior / New Feature

It would be great if Ocelot would support a mechanism where microservices in the system, could connect "outbound" to a service running Ocelot. As part of this outbound connect the microservice would register the routes it is offering and Ocelot would start handling this route. If multiple services register the same route, Ocelot would load balance the calls between them.

The important aspect of this feature is that the Microservice would pre-establish a pool of connections to Ocelot which will then be used to handle the calls. Idea behind this is to achieve special LAN/DMZ separation of the services where no manual firewall configuration is needed where ports are opened from the DMZ into the LAN.

See this architectural chart: image

Actual Behavior / Motivation for New Feature

Please note that this feature request might be quite specific to what we're doing in our software but I guess it is a topic general enough to be potentially adressed by Ocelot.

First of all this feature brings the benefit that Ocelot would be able to dynamically expose service (as standalone service) depending on their availability in the network. This allows you do scale dynamically but also publish new services in your architecture without the need of changing anything on Ocelot.

The second aspect is security and the related costs maintaining it. Opening ports in the firewall towards your private network is always risky. If your backend is dynamic, (e.g. via spawning new VMs or containers), it needs again administrative effort to change the firewall accordingly. Some of our customers have very restricted network policies and opening ports is from the DMZ to LAN is not easily possible.

Steps to Reproduce the Problem / How to implement the New Feature

Our old proxy service was a specific development to our APIs we are exposing. Basically a dynamically generated WCF proxy for our contract but we want to switch to an HTTP based reverse proxy system. We started with a custom development with this approach when we started on some new HTTP based APIs.

In the backend services we have an ASP.net core service which is having a custom IServer implementation. This IServer implementation is connecting outbound to the proxy service via WebSockets. The gateway service detects the special service connect and starts communicating via a special WebSocket messages to exchange some metadata. For Ocelot the route configurations would be exchanged. Maybe also some metadata like the number of data connections could be agreed on this channel. This client part could be either ASP.net core specific but also it could be integrated to other services as long as there is some callback for the application to handle the request.

On the gateway side, the special control and data connections would need to be handled. Once a service registers the gateway would accept some data connections from this service. As soon a client calls an API, the gateway would use one of these available connections to handle the request. In our case we also handled this via a WebSocket based protocol that exchanges HTTP headers and data in a streaming fashion. In best case connections can be re-used.

Another approach could be a message-bus system. There would be one Ocelot Host on the DMZ side, and a Ocelot Client on the LAN side. The Host would just forward all HTTP requests to this service bus, and each microservice would listen to HTTP requests relevant for it.

image

Or last but not least a setup like this would also be an alternative: The microservices would only register themselves on a gateway in the LAN. This registration is just for initial setup and heartbeating if services are still around. This LAN gateway can connect then directly to the individual services to execute requests. But the 2 gateways would be connected via some outbound connection pool. Benefit on this solutions is that the service registration is an own special feature within Ocelot and does not require any client application adjustment. You just need an additional service in your overall architecture.

image

From what I saw the host part could be done via https://ocelot.readthedocs.io/en/latest/features/delegatinghandlers.html which use a connection from the pool to forward the and handle the requests. The service registration would be a new special endpoint services would call. This would be an extension to the service discovery https://ocelot.readthedocs.io/en/latest/features/servicediscovery.html#service-discovery

The client part would be a likely a compeltely new module like an AddOcelotGatewayServer(o=> o.GatewayAddress = "https://gateway/"; o.ServiceAuthenticationKey = "Secret to allow service registration" ) which registers an IServer for handling requests.

I'm eager to get some feedback on this feature request and which solution to this problem you guys prefer.

Specifications

Not relevant.

ArchitectCat commented 3 years ago

outbound connect the microservice would register the routes it is offering and Ocelot would start handling this route. If multiple services register the same route, Ocelot would load balance the calls between them Maybe I'm reading this wrong but this is literally describes the definition of a service discovery, which Ocelot already supports out of the box. Sounds like all you trying to achieve is to have a custom service discovery provider that handles node/service registrations via network zone availability.

raman-m commented 8 months ago

@Danielku15 Not bad description! 👍 💪
So, are you ready to develop this feature? Are your fingertips resting on the keyboard? 😄