Common Patterns for Microservices
Table of Contents
- Direct Client-to-Microservice Communication
- The API Gateway Pattern
- Gateway Offloading
- Backend for Frontend (BFF)
- Kuroco API Management
Microservices are a type of application architecture that break down an application into multiple service components, in contrast with a traditional monolithic architecture where all the parts are bound together, and sharing dependencies.
A microservice exposes fine-grained endpoints, which function independently of other microservices. The goal is to make each service simpler to build and maintain, reduce dependencies, and increase the speed and scalability of the microservices. As applications grow in complexity, communicating with many bundled microservices can cause issues, which are discussed below.
Direct Client-to-Microservice Communication
The most basic pattern is direct client-to-microservice architecture. In this pattern a client application makes direct requests to the microservices, as shown in the figure below:
Larger server-side applications are typically organized as a cluster, with load balancing required to manage requests from the client to the proper backend microservices. As the application grows, this can become more difficult to manage, as the number of microservice types it uses may number in the dozens.
It is therefore important for larger applications to minimize the number of requests to backend microservices, as this can increase latency and result in poor performance on the frontend UI side. Rather, responses should be bundled on the server side and served to frontend when the required data is aggregated.
The other major issue with the direct client-to-microservices pattern is handling functionality like authorization, transforming of data, and dispatching dynamic requests.
- If authorization is required for every microservice individually, this can create a lot of development overhead and repeated code, which is difficult to manage at scale.
- If microservices are using protocols not meant for Internet clients to consume directly, they must first be converted to HTTP/HTTPS, which can also require a lot of development overhead.
- Bundling API microservices to meet the specific needs of different frontends, like mobile apps versus web browsers
The API Gateway Pattern
In the above pattern, client applications would become coupled with many microservice endpoints over time. If the application were to change its structure or introduce new microservices, it would quickly become unwieldy to handle so many endpoints.
- Coupling: Although microservices are independent of each other, client applications often make direct reference to internal microservices, which can cause breaking changes if the internal microservices are refactored.
- Latency: If any of the client application’s views require many calls to multiple services, this can bog down the network and greatly increase latency. Aggregation is the most obvious solution for this.
- Security: Microservices are publicly available by default, making the attack surface larger than if internal microservices not directly used by the client apps are hidden.
- Authorization: Publicly available microservice each need to handle cross-cutting concerns such as authorization and SSL. This results in development overhead and repeated code for each microservice, which could be consolidated.
The most widely used solution for the above issues is an API Gateway.
The API Gateway pattern is about placing the needs of the client app first. It sits between the client application and the microservices, acting as a reverse proxy, routing requests from clients to services. It can also handle functionality like authentication, SSL termination, and caching.
An API Gateway can offer various features, including reverse proxy or gateway routing, to redirect or route requests to the endpoints of the internal microservices. The gateway provides a single endpoint or URL for the client applications, internally mapping the requests to a group of internal microservices. This routing feature helps to decouple the client apps from the microservices but it's also convenient when modernizing a monolithic API by sitting the API Gateway in between the monolithic API and the client apps, then you can add new APIs as new microservices while still using the legacy monolithic API until it's split into many microservices in the future.
Because of the API Gateway, the client apps won't notice if the APIs being used are implemented as internal microservices or a monolithic API and more importantly, when evolving and refactoring the monolithic API into microservices, thanks to the API Gateway routing, client apps won't be impacted with any URI change.
As part of the gateway pattern you can aggregate multiple client requests (usually HTTP requests) targeting multiple internal microservices into a single client request. This pattern is especially convenient when a client page/screen needs information from several microservices. With this approach, the client app sends a single request to the API Gateway that dispatches several requests to the internal microservices and then aggregates the results and sends everything back to the client app.
Depending on the API gateway you use, it might be able to perform this aggregation. However, in many cases it's more flexible to create aggregation microservices under the scope of the API gateway.
Depending on the features offered by your API gateway, you can offload functionality from individual microservices to the gateway, which simplifies the implementation of each microservice.
This approach works well for specialized features that can be complex to implement properly in every internal microservice, such as the following functionality:
- Authentication and authorization
- Service discovery integration
- Response caching
- Rate limiting and throttling
- Load balancing
- Logging, tracing, correlation
- Headers, query strings, and claims transformation
Backend for Frontend (BFF)
Similar to the API gateway pattern, the Backend for Frontend (BFF) pattern instead uses multiple gateways - each on dedicated to a specific frontend channel. For example, a native mobile app front and a traditional desktop browser web app would each have an API gateway they integrate, which would in turn aggregate and serve the required data in an appropriate format.
For more information on this pattern, see this article.
Kuroco API Management
Kuroco’s backend offers API gateway functionality out of the box, with built-in tracking and analytics.
Kuroco allows for logging, security, and metering of your API. These insights can help your enterprise get a better understanding of how your APIs are being used and how they are performing. They do this by letting you view near real-time analytics reports and identifying trends that might impact your business. In addition, you can view logs about request and response activity for further online and offline analysis.
You can get started today and test it out for free, or feel free to reach out to our customer support team if you have any questions!