Open gitblit opened 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.
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.
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:
Should microservices use Swagger/Open API for endpoints definitions? That's pretty much a standard nowadays, however, if we would like to achieve more complex configuration (sending commands via message broker, request transformation, etc.) then it'd make more sense to use either the current Ntrada format or something similar. Actually, the question is - should the microservice just define its endpoints or also the way how such endpoints such be visible (and handled) from the end-user perspective, for example, HTTP POST to /users
endpoint being part of users-service
should be sent via RabbitMQ
and that's what API Gateway would be responsible for doing.
Service discovery - given that we have multiple instances of the same microservice, should API Gateway care about this it all? It would be probably better to use Consul, Eureka or built-in Docker/Kubernetes service registry/discovery/DNS. The API Gateway should only take care of updating its configuration dynamically.
Authentication & authorization - each microservice would define required claims for particular endpoints, but the overall access validation should be probably performed on the API Gateway side.
Hah. All good questions. That's why this is your project, not mine. :)
[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
}
}
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. :)
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).
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.