Should a microservice take care of this or the api gateway? - microservices

I am building out a microservice architecture and kinda confused on one part. I am using Kafka as a message broker system to communicate within my services. A perfect example would be Uber's API for request estimation. It returns duration, distance, price, etc. I would assume they have a microservice for each of those, i.e. service for pricing, service for duration/distance, service for drivers, etc. My question is when hitting the endpoint /requests/estimate does the requests microservice make rest calls to the other microservices to retrieve data for the duration, distance, etc? or does the API Gateway take care of that?

I say it depends on the use case. If service A needs to know what service B knows, then it is perfectly sane for service A to make a REST call to service B. But if the combined knowledge for A and B is only needed in your gateway then the gateway can combine the results.

Both are perfectly valid ways of doing it, but I would go the Estimate microservice way to avoid putting too much logic in the API Gateway.
Maybe in the future your estimation calculation will change, and it wouldn't make much sense to me to update the gateway every time.

In practice, not all gateway APIs support multiple calls and aggregation. In the micro service architecture, there is a common pattern ("API Composition", "Composition Patterns" in particular "Aggregator Pattern"), the idea of which is that you need to make a separate service that will contain the business logic of multiple calls and aggregation.

Related

API Gateway Pattern vs Aggregator Pattern (In the context of microservices)

I am trying to wrap my head around the differences between an API gateway and the aggregator pattern for microservices.
At the moment From my understanding the aggregator pattern functions by collecting pieces of data from various microservices and returns an aggregate for processing.
Now the API gateway is the single entry point that aggregates the calls to the individual microservices. While this may sound very similar to the Aggregator Pattern, there are some distinct features. Most importantly, this new service does not store data but instead becomes responsible for API composition, request routing, and new features such as authentication
I would really like to understand if my reasoning is correct here.
Thank you in advance!
Yes, your understanding is correct. I would add a few ideas:
The API Gateway usually is entry-point of the system, while an aggregator microservice can be somewhere in the middle-layer.
The API Gateway may store partial responses from other microservices, while it waits for other ones to respond (similarly to an aggregator)
There is also a pattern which mixes them, known as a gateway aggregation pattern
Though this seems very similar having a aggregator service vs API Gateway acting as a aggergator.
Think about much bigger ecosystem, where API Gateway would genrally be 1, but we can have number of aggregator services.
Aggregator service will generally lie in middle layer and can be built using specific patterns, these can be Parallel, Chaining or Branching.
Taking example of ecommerce application, we can have below aggregators and more.
Customer Dashboard Aggrgator (Recommeneded products, past orders, current active order etc)
Cart Aggregator (Shipping Service, Inventory Service, Discount Service)
Order History Aggregator
Customer Information Aggregator (Personal Information, Address)

Mapping microservices on frontend

This is probably a bit opinion-based question, but I will try to be technical to still be relevant.
Consider having several microservices: a, b, c.
To make this available on frontend, these could be made available as:
https://host/services/a
https://host/services/b
https://host/services/c
However, the fact that the endpoints are split between differents services are kind of irrelevant for frontend and basically if we can guarantee the endpoints don't clash, it would be great to have these available directly:
a/endpoint1 -> https://host/services/endpoint1
a/endpoint2 -> https://host/services/endpoint2
b/endpoint3 -> https://host/services/endpoint3
c/endpoint4 -> https://host/services/endpoint4
To implement such mapping, one needs to list all endpoint or at least write some matching pattern within the proxy service. This is very nice for the Frontend team to work with, however it is unfortunately very easy to brake.
What are the best practices for mapping the urls of microservices? Only thing which comes to my mind are some exports of OpenApi, which could be handled by FE to get the right path. However, every service generates its own OpenApi json, so we are basically back to the original problem.
are you sure the Frontend team needs ALL the exposed endpoints? Usually, frontends talk with an API Gateway, or, as cool kids call them these days, "Backend for Frontends".
In a nutshell, it's a special service that takes care of exposing only the functionalities/endpoints needed by the frontend. It will forward calls to the relevant services or, if necessary, call multiple services and aggregate the results.
In most cases these API Gateway don't have a db, as they're retrieving all the data from other services. They might however make use of a caching layer to speedup things.
You can even have multiple API Gateway, one per Frontend (eg. desktop, mobile).

Microservice Aggregator Service BFF

Let say I have 22 microservices. I developed with docker on local.
Client wants to get product model data which contains 3 different service data and aggregate them.
Should I use aggregator gateway api or SPA get separately from each service. Does Aggregator service couple services ?
These Microservices patterns always come with Trade-offs. Here you need to consider more than just a coupling issue when you are going with Aggregator pattern (Backend for Frontend).
The following are some of the points you need to think about before going with this pattern.
The Latency problem. If you want this implementation to make it better without any latency problem, then your services and aggregator should be in the same location or the same data center. Avoid third party calls from aggregators.
This can introduce a single point of failure. Make sure that you've designed in such a way that the service is highly available.
Implement a resilient design and timeout since this aggregator is calling other services and getting data. If one or more service calls take too long, it should timeout and return a partial set of data. Consider how your application will handle this scenario
Monitoring of your aggregator and it's child service calls. Implement distributed tracing using correlation IDs to track each call.
Ensure the aggregator has the adequate performance to handle the load and can be scaled to meet your anticipated growth.
These are the best practices that I can suggest, You are the best person who can decide based on your system requirements and these points.
There are some compelling advantages to using a BfF service as an orchestration layer that aggregates calls to various backend data services.
It will reduce the complexity in the data access areas of your SPA.
It can also reduce load times.
Over time, your frontend devs will be less likely to get blocked on the backend devs assuming that the BfF is maintained by the frontend devs.
Take a look at this article on Consistency, Coupling, and Complexity at the Edge that goes into more detail on this and proposes some best practices such as GraphQL vs REST.

Why API Gateway is recommended for Microservices?

For microservices, the common design pattern used is API-Gateway. I am a bit confused about its implementation and implications. My questions/concerns are as follows:
Why other patterns for microservices are not generally discussed? If they are, then did I miss them out?
If we deploy a gateway server, isn't it a bottleneck?
Isn't the gateway server vulnerable to crashes/failures due to excessive requests at a single point? I believe that the load would be enormous at this point (and keeping in mind that Netflix is doing something like this). Correct me if I am wrong in understanding.
Stream/download/upload data (like files, videos, images) will also be passing through the gateway server with other middleware services?
Why can't we use the proxy pattern instead of Gateway?
From my understanding, in an ideal environment, a gateway server would be entertaining the requests from clients and responding back after the Microservices has performed the due task.
Additionally, I was looking at Spring Cloud Gateway. It seems to be something that I am looking for in a gateway server but the routing functionality of it confuses me if it's just a routing (redirect) service and the microservice would be directly responsible for the response to the client.
The gateway pattern is used to provide a single interface to a bunch of different microservices. If you have multiple microservices providing data for your API, you don't want to expose all of these to your clients. Much better for them to have just a single point of entry, without having to think about which service to poll for which data. It's also nice to be able to centralise common processing such as authentication. Like any design pattern, it can be applied very nicely to some solutions and doesn't work well for others.
If throughput becomes an issue, the gateway is very scalable. You can just add more gateways and load balance them
There are some subtle differences between proxy pattern and API gateway pattern. I recommend this article for a pretty straightforward explanation
https://blog.akana.com/api-proxy-or-gateway/
In the area of microservices the API-Gateway is a proven Pattern. It has several advantages e.g:
It encapsulate several edge functionalities (like authentication, authorization, routing, monitoring, ...)
It hides all your microservices and controls the access to them (I don't think, you want that your clients should be able to access your microservices directly).
It may encapsulate the communication protocols requested by your microservices (sometimes the service may have a mixture of protocols internally which even are only allowed within a firewall).
An API-Gateway may also provide "API composition" (orchestrating the calls to several services an merge their results to one). It s not recommended, to implement a such composition in a microservice.
and so on
Implementing all these feature in a proxy is not trivial. There is a couple of API-Gateways which provide all these functionalities and more like the Netflix-Zuul, Spring-Gateway or the Akana Gateway.
Furthermore, in order to avoid your API-Gateway from being a bottleneck you may :
Scale your API-Gateway and load balance it (as mentioned above by Arran_Duff)
Your API-Gateway should not provide a single one-size-fits-all API for all your clients. Doing so you will, in the case of huge request amount (or large files to down/up load) for sure encounter the problems you mentioned in questions 3 and 4. Therefore in order to mitigate a such situation your Gateway e.g may provide each client with a client specific API (a API-Gateway instance serves only a certain client type or business area..). This is exactly what Netflix has done to resolve this problem (see https://medium.com/netflix-techblog/embracing-the-differences-inside-the-netflix-api-redesign-15fd8b3dc49d)
1.Why other patterns for microservices are not generally discussed? If they are, then did I miss them out?
There are many microservice pattern under different categories such as database , service etc .This is a very good article https://microservices.io/patterns/index.html
2.If we deploy a gateway server, isn't it a bottleneck?
Yes to some extent .Q3's answers image will answer this.
3.Isn't the gateway server vulnerable to crashes/failures due to excessive requests at a single point? I believe that the load would be enormous at this point (and keeping in mind that Netflix is doing something like this). Correct me if I am wrong in understanding.
4.Stream/download/upload data (like files, videos, images) will also be passing through the gateway server with other middleware services?
Why can't we use the proxy pattern instead of Gateway?
The use case for an API Proxy versus an API Gateway depends on what kinds of capabilities you require and where you are in the API Lifecycle. If you already have an existing API that doesn’t require the advanced capabilities that an API Gateway can offer than an API Proxy would be a recommended route.
You can save valuable engineering bandwidth because proxies are much easier to maintain and you won’t suffer any negligible performance loss. If you need specific capabilities that a proxy doesn’t offer you could also develop an in-house layer to accommodate your use case. If you are earlier in the API lifecycle or need the extra features that an API Gateway can provide, then investing in one would pay dividends.

Micro services using Service fabric where to place controllers

I have a micro-service project with multiple services in .NET Core. When it comes to placing the controllers, there are 2 approaches:
Place the controllers in respective Micro Services, with Startup.cs in each micro-service.
Place all controllers in a separate project and have them call the individual services.
I think the 1st approach will involve less coding effort but the 2nd one separates controllers from actual services using interfaces etc.
Is there a difference in terms of how they are created and managed in Fabric using both approaches.
This is very broad topic and can raise points for discussion because it all depends on preferences, experiences and tech stacks. I will add my two cents, but do not consider it as a rule, just my view for both approaches.
First approach (APIs for each service isolated from each other):
the services will expose their public APIs themselves and you will need to put a service discovery approach in place to enable clients to call each microservice, a simple one is using the reverse proxy to forward the calls using the service name.
Each service and it's APIs scales independently
This approach is better to deploy individual updates without taking down other microservices.
This approach tends to have more code repetition to handle authorization, authentication, and other common aspects, from there you will end up doing shared libraries using on all services.
This approach increase the points of failures, it is good because failures will affect less services, if one API is failing, other services won't be impacted (if the failure does not affect the machine like memory leak or high CPU usage).
The second approach (Single API to forward the calls to right services):
You have a single endpoint and the service discovery will happen in the API, all work will be handled by each services.
The API must scale for everyone even though one service consumes much more resources than others. just the service will scale independently.
This approach, to add or modify api endpoints, you will likely update the API and the service, taking down the API will affect other services.
This approach reduces the code duplication and you can centralize many common aspects like Authorization, request throttling and so on.
This approach has less points of failures, if one microservices goes down, and a good amount of calls depend on this service, the API will handle more connection and pending requests, this will affect other services and performance. If it goes down, every services will be unavailable. Compared to the first approach, the first approach will offloaded the resilience to the proxy or to the client.
In summary,
both approaches will have a similar effort, the difference is that the effort will be split into different areas, you should evaluate both and consider which one to maintain. Don't consider just code in the comparison, because code has very little impact on the overall solution when compared with other aspects like release, monitoring, logging, security, performance.
In our current project we have a public facing API. We have several individual microservice projects for each domain. Being individual allows us to scale according to the resources each microservice use. For example we have an imaging service that consumes a lot of resources, so scaling this is easier. You also have the chance to deploy them individually and if any service fails it doesn't break the whole application.
In front of all the microservices we have an API Gateway that handles all the authentication, throttles, versioning, health checks, metrics, logging etc. We have interfaces for each microservice, and keep the Request and Response models seperately for each context. There is no business logic on this layer, and you also have the chance to aggregate responses where several services need to be called.
If you would like to ask anything about this structure please feel free to ask.

Resources