Photo by Dear-769888 on Unsplash
Developing a microservice-based application's external API can pose unique challenges to developers. When an application is composed of many REST-based services, it can be tempting to expose these services directly to the client. This approach should be discouraged for all but the simplest applications.
As the surface area of the external API increases, there is a corresponding increase in the number of calls the client is responsible for. In addition to the client's user interface responsibilities, it must also perform coordination between intermediate service operations, data aggregation, and filtering. These added responsibilities add to the complexity of the client and also increase the network communication load as each client must interact more frequently with the participating services.
Modifications to the service API may necessitate multiple versions be deployed and maintained until all the client development teams have migrated to the latest verion. As the client developers may be operating on different schedules, it may take a non-trivial amount of time until the older version can be phased out. Supporting multiple service versions increases the overall administration, coordination, and development effort required for the application.
With this in mind it is essential to understand that all services should not be public facing.
The API Gateway pattern introduces a facade that provides a simplified view of the application.
The simplified external API replaces the granular service APIs with a coarse-grained API to reduce the aggregate service surface area exposed to each client. The API Gateway API moves the coordiation, aggregation, and filtering out of the client and into the gateway. This simplification, reduces network load as only the processed data is returned to the client.
Additionally, the API gateway is now responsible for handling any failure and retry logic before returning to the client. The simplified client is now only responsible for handling communication failures between the client and the API Gateway.
With the API Gateway now responsible for mediating access between the client and the application's services, we decouple the client from application service changes. When a service's API changes, the API Gateway is responsible for translating those changes.
First, each API Gateway is tailored to the needs of the client. When a single API Gateway supports multiple client types, it will naturally grow in complexity. By creating a unique API Gateway for each client type, we reduce each individual API Gateway footprint. By reducing the API Gateway codebase, we make the code easier to understand and manage.
Secondly, we can assign the API Gateway development responsibilities to individual teams working independently. This approach allows the team with the best understanding of a client type's needs to develop its API Gateway. It also allows each API Gateway to develop on its own timeline.
Employing an API Gateway obviates the need for client-side Service Discovery as the Gateway takes over the responsibility for service discovery and invocation of internal services. Client responsiveness increases as the Service Discovery is performed in the high-speed network environment of a data center instead of across the slower Internet.
Granular Service APIs
The first problem we encounter is the proliferation of highly granular service APIs. Highly granular service APIs increase the complexity of the client code in several ways.As the surface area of the external API increases, there is a corresponding increase in the number of calls the client is responsible for. In addition to the client's user interface responsibilities, it must also perform coordination between intermediate service operations, data aggregation, and filtering. These added responsibilities add to the complexity of the client and also increase the network communication load as each client must interact more frequently with the participating services.
Tight Coupling
Another issue with highly granular external facing APIs is the tight coupling between the client and each exposed service. Previous articles have detailed the hazards of tight coupling and these same hazards apply between clients and services. While an API should be relatively stable, any change to the API requires a corresponding change to the client. It is also important to remember that some application clients may be developed by different teams including third-party developers working on different timelines. These teams may not have the resource to mobilize to respond quickly to changes.Modifications to the service API may necessitate multiple versions be deployed and maintained until all the client development teams have migrated to the latest verion. As the client developers may be operating on different schedules, it may take a non-trivial amount of time until the older version can be phased out. Supporting multiple service versions increases the overall administration, coordination, and development effort required for the application.
Service Discovery
In the previous article, we discussed the motivation and mechanism of the Service Discovery pattern. It is conceivable that an application client could query the Service Registry to find appropriate service endpoints and perform some form of load balancing. However, it is critical that we consider that Service Discovery performance characteristics may vary dramatically across the internet when compared to those executing within a data center due to bandwidth and network speeds. In addition to the added complexity needed to query the Service Registry, the cost of the round-trip for each service invocation will ultimately have a negative impact on client responsiveness.Security
Last but by no means least is service security. The larger the API surface area, the greater the security attack surface. By exposing every service API to a client, we render each service vulnerable to attack. Every service endpoint, container, and virtual host must be secured, increasing both security monitoring and administration.With this in mind it is essential to understand that all services should not be public facing.
A Front Door
Now that we have discussed the perils of direct client-to-microservice communication, we introduce the API Gateway Pattern to address these concerns.The API Gateway pattern introduces a facade that provides a simplified view of the application.
The simplified external API replaces the granular service APIs with a coarse-grained API to reduce the aggregate service surface area exposed to each client. The API Gateway API moves the coordiation, aggregation, and filtering out of the client and into the gateway. This simplification, reduces network load as only the processed data is returned to the client.
Additionally, the API gateway is now responsible for handling any failure and retry logic before returning to the client. The simplified client is now only responsible for handling communication failures between the client and the API Gateway.
With the API Gateway now responsible for mediating access between the client and the application's services, we decouple the client from application service changes. When a service's API changes, the API Gateway is responsible for translating those changes.
Multiple Gateways
When dealing with multiple client types, a single API gateway may prove to be inadequate. In this situation, individual API Gateways can be developed to service specific gateway types. By supporting multiple API Gateways, we realize two primary benefits:First, each API Gateway is tailored to the needs of the client. When a single API Gateway supports multiple client types, it will naturally grow in complexity. By creating a unique API Gateway for each client type, we reduce each individual API Gateway footprint. By reducing the API Gateway codebase, we make the code easier to understand and manage.
Secondly, we can assign the API Gateway development responsibilities to individual teams working independently. This approach allows the team with the best understanding of a client type's needs to develop its API Gateway. It also allows each API Gateway to develop on its own timeline.
Employing an API Gateway obviates the need for client-side Service Discovery as the Gateway takes over the responsibility for service discovery and invocation of internal services. Client responsiveness increases as the Service Discovery is performed in the high-speed network environment of a data center instead of across the slower Internet.
Twitter
Facebook
Reddit
LinkedIn
Email