Then our application consists of a set of microservices it would be a wrong decision to implement interactions between clients and services directly as drawn on diagram below
it is not so good idea to share all microservices with world. Clients should knows about microservices. Also, in this approach we should implement user authentication method for all services, we can't have platform authentication in hidden platform layer. All clients should support changes occurring from services and it can cause an additional work to update clients (mobile for example, not so easy to update).
The main problem:
How do the clients of a Microservices-based application access the individual services? taken from here
API Gateway is it a service between UI and backend (or set of backend services) which provides ability for UI to work with the system in some kind of abstraction layer under backend services.
API Gateway provide a lot of benefits for the system, for operations, for monitoring and keeping the system in green status.
API Gateway works as a reverse proxy between clients and the backend microservices architecture.
Good points related to API Gateway:
Problems with the API Gateway:
In additional to the list above, here is some of the problems with details which can be solved by API Gateway pattern:
Transforming the responses. API Gateway can transform responses and keep only those data that is required for client.
Performance optimization for slow clients. Filtering, sorting or other expensive operations can be delegated to API Gateway service.
Interact with backend services, hide authentication mechanis and tokens for it. Also, with API Gateway it is easy to implement and decouple different authentication methods for clients and backend services.
Cross-Origin Resource Sharing (CORS). Not all services allows this. And not all existing services was desined to work with browser. Sometimes it is can take a lot of time or impossible to connect from browser to services directly.
Preventing system overload by using a speed limit the API Gateway can keep the services in working condition.
The main defferent between API Gateway and Load Balancer:
Load Balancer - it is component to distribute requests in set of servers with one service
API Gateway - it is component to route requests to different services by different conditions
BFF defines a separate API gateway for each kind of client and tightly coupled to a specific user experience.
The BFF pattern is an architectural paradigm, a variant of the API gateway pattern and it comprises of multiple back-ends that are designed to meet the demands of specific front-end applications, such as desktop, browser, and native-mobile applications, IOT devices etc. quote source
Sometimes BFF pattern is called as "specific case of API Gateway" or "separate API Gateway for each client type". In other words, if we have only one client type (web for example) we will use API Gateway, but if we have different types of clients (different protocols, etc...) we will use BFF (separate API Gateway) for each client type.
BFF pattern it is simple dedicated backend for each client type (web, desktop, mobile, ...). Each client will send requests only to its own backend.
Here we have special backend for each interface (web, mobile, desktop, tool, etc...). In the BFF component we can optimize API, performance or other aspects of interaction with the client.
BFF pattern is useful when you want to avoid customizing a single backend for multiple interfaces. If we have requirement to optimize or change protocol with a specific client we can keep other clients as is.
BFF component for web can host UI as static assets and browsers will load SPA UI from BFF server and send requests to this server.
BFF pattern it is way to organize API for different types of clients. This is a easyest way because BFF eliminates all the differences in individual backends.
In Spring word we have very interesting Spring conponent Spring Cloud Gateway to implement both API Gateway and BFF patters.
From documentation
This project provides an API Gateway built on top of the Spring Ecosystem, including: Spring 5, Spring Boot 2 and Project Reactor. Spring Cloud Gateway aims to provide a simple, yet effective way to route to APIs and provide cross cutting concerns to them such as: security, monitoring/metrics, and resiliency.
It is very powerful and flexible tool which will cover all your needs.
Can be implemented in code as well as in configuration:
in code
@Configuration
class PlantAPIGatewayConfig {
@Bean
RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("plant-props-routing ", route ->
route.path("/api/v1/plant/**")
.and()
.method(HttpMethod.GET)
.filters(filter -> filter.stripPrefix(1))
.uri("https://plant-storage.dom"))
.build();
}
}
// Transformation in this example drops prefix from url path. "/api" for this example.
or completly in configuration
-- application.yml
spring:
cloud:
gateway:
routes:
- id: read_only_processor_route
uri: https://plant-storage.dom
predicates:
- Method=GET
- Path=/api/v1/plant/property/{propId},/api/v1/plant/image/{imId}
Benefits:
Most of the Spring features are available to use with Spring Cloud Gateway:
Disadvantages:
This approach can be used with both API Gateway and BFF. But, better for BFF pattern, because for API Gateway it is less flexible then Spring Cloud Gateway. In case BFF, it is great choose, because all code are in one style, in one technology stack. Or if you have only one client type (browser) and you want to delegate API Gateway component to UI team you can use NestJS too.
In NestJS, code such as the domain model or some services can be shared between Angular UI and NestJS backend.
For backend developers NestJS won't be something completely new. Spring Boot and NestJS
http-proxy-middleware can be used with NestJS to organize proxy module in gateway. This middleware provides ability to transform requests and responses, implement authentication and error handling.
NestJS framework seems very similar to Angular code and it provide same expirience for UI developers to write code for Angular UI and NestJS backend.
NestJS example. It is really seems like Angular code.
// domain
export interface IPlant {
name: string;
}
// controller
import { Controller, Get } from '@nestjs/common';
import { IPlant } from './interfaces/plant.interface';
@Controller('plants')
export class PlantController {
constructor(private plantService: PlantService) {}
@Get()
findAll(): IPant[] {
return this.plantService.findAll();
}
}
// service
import { Injectable } from '@nestjs/common';
import { IPlant } from './interfaces/plant.interface';
@Injectable()
export class PlantService {
findAll(): IPant[] {
return [
{ name: "Betula pendula" }
];
}
}
I'm not a big expert on GraphQL, here I just want to summorize some common knowledge about this apporach.
API Gateway pattern can be inplemented with GraphQL + Spring and supports by one of the backend teams. For BFF, GraphQL can be implemented in NodeJS with NestJS or with other framework.
Each cloud has API Gateway service.
In case of API Gateway and BFF, monorepo allows us to avoid code duplication between frontend and backend. All API components are developed as shared components in monorepo and each BFF service can include required API components.
Interesting technology stack examples to organize code charing approaches below.
Interesting solution can be implemented based on .NET
In this technology stack we have one language (C#) and shared code between
Docs:
Pattern: API Gateway / Backends for Frontends (microservices.io)
The API gateway pattern versus the Direct client-to-microservice communication (.NET architecture)
Choosing the Right API Gateway Pattern for Effective API Delivery (nginx.com)