snatch-dev / Ntrada

Ntrada - API Gateway built with .NET Core
MIT License
133 stars 21 forks source link

Convey configuration strategy #13

Open gitblit opened 4 years ago

gitblit commented 4 years ago

I watched your Convey walkthrough last weekend. Very interesting! I like how you are stitching together all these components into an semi-opinionated, cohesive, scalable story. I am particularly interested in how Entrada fits into Convey.

Have you considered: instead of (or in addition to) declaring a complete configuration in YML, having Convey microservices register with an Entrada instance at runtime/startup? Maybe you decorate/annotate handlers for Entrada registration.

It's not a fully formed thought in my head but I'm trying to think of ways this could be a little more dynamic.

spetz commented 4 years ago

Hey, Thank you for the kind words, really happy to hear that :).

Just to clarify, Ntrada is a different project than Convey. It's an API Gateway that can be run seamlessly e.g. via Docker as well as used as a custom library if you're willing to extend it with your own C# code. Basically, you could use Convey packages along with Ntrada (e.g. tracing, persistence, monitoring etc.), but that's pretty much it.

If I understand you correctly, you're asking whether it would be possible to create a Convey extension (let's call it Ntrada integration), so that the API Gateway itself wouldn't be configured via YML or any other type file, but based on the microservices in your solution, it would configure itself dynamically (something like Fabio does via Consul tags).

I think it's a really great idea and actually there would be no need to use Convey at all. It could be a standalone Nuget package that is able to register within Ntrada on its own (via Web API or so), or even better, it could be sidecar/proxy (something like Envoy), that could be run next to your microservice (written in any language) and it'd register the service instances into the API Gateway.

Let me know if that's what you were thinking of.

gitblit commented 4 years ago

Ntrada is a different project than Convey

Understood.

it would configure itself dynamically

Yes, that's the idea. Make the gateway dynamically responsive to the services it actually proxies rather than being declarative where configuration must be double-maintained.

The sidecar design is interesting, I can see what problems it solves but I'm not totally convinced to use it myself. It feels like yet another layer of DevOps complexity. The sidecar pattern is what Microsoft is promoting with their recently announced Dapr project.

spetz commented 4 years ago

That makes a lot of sense, and whether it'd be a sidecar (Dapr is interesting, yet didn't have time to play with it yet) or a simple HTTP request it pretty much boils down to the same Web API call.

There are still (at least) a few questions:

gitblit commented 4 years ago

Hah. All good questions. That's why this is your project, not mine. :)

  1. The microservice already defines how it can communicate. The Entrada config is a replication of that (possibly a subset if you are building both restful apis and message bus capability). The microservice could specify it's preferred Entrada delegation mechanism probably with a default for the microservice with optional discrete overrides per handler?
    [Entrada(Bus = true, Endpoint = true)] // terrible example, I'm sure you can do better
    public class GetAccountHandler : IQueryHandler<GetAccount, AccountDto>
    {
        public Task<AccountDto> HandleAsync(GetAccount query)
        {
            //put the handling code here
        }
    }
  2. Service/instance discovery. Totally agree. Gateway does not need to be concerned with load balancing. Maybe the microservice/instance registration sends the service name which matches the Consul service name?
  3. Auth is always tricky. That would be a definite concern. Maybe the microservice can indicate a policy name that is defined in Entrada when it registers it's capabilities.

Another one would be what happens if you are rolling out an update to your microservices which changes the capabilities? (adds an endpoint, handler, etc).

Like I wrote initially, not fully formed. :)

spetz commented 4 years ago

Yes, I think that services need to specify their endpoints and the request handling mechanism, so either by using attribute (like in your sample) or configuration via file (to make it a universal solution, not just for C# apps).

Service discovery - both the API and microservices need to beware of the common infrastructure, so whether it's Consul, orchestration engine with built-in DNS or something else, all of the requests have to be forwarded using the same mechanism and Gateway should only care about the service name.

Auth - as you said, either define a set of global claims in the Gateway/Identity Server or allow for arbitrary claims, as long as it works with the JWT.

Speaking of rolling updates, I think it would be possible to provide a special tag (besides the service name, something like version or so), that would be added both to Gateway and e.g. Consul, and based on the new version of given microservice, the load balancer could redirect the traffic properly (Fabio, Traefik or anything else).