RESTful API Gateway with gRPC

Pankaj Kumar
5 min readJul 4, 2021

--

@pixabay on pexels.com

An API Gateway or Backend for frontend (BFF) is an important design pattern for building applications based on microservices architecture. I touched on the API Gateway, aka Backend for Frontend (BFF), in the article gRPC for microservices communication. In this article, I will delve deeper into the whys of API Gateway/Backend for a Frontends design pattern. I will show examples of exposing RESTFul APIs through API Gateway with gRPC based APIs. I will also explain how to develop gRPC endpoints as a Spring Boot application.

Code Example

The working code example of this article is listed on GitHub. To run the example, clone repository, and import grpc-spring-boot as a project in your favorite IDE.

Why API Gateway?

Before we answer how and what of API Gateway, let’s understand why do we need API Gateway. Imagine, you are building an e-Commerce application using microservices. You may have microservices for Products, Orders, Offers, Inventory, etc. The microservice exposes fine-grained APIs that are consumed by the frontend application. As the granularity of the APIs provided by the microservices differs from what the frontend application needs, the frontend application has to make many calls to the different services. For example — the product details UI application can call different microservices to show product detail page as:

As the frontend application is running in the browser, these calls can introduce significant latency.

Another common problem in a microservices architecture is to solve cross-cutting concerns such as authentication, authorization, rate limiting, etc. Should we offload such concern to a gateway proxy or deploy shared or specialized service with each microservice (or as a library, which can be consumed by all services), thus increasing tight coupling between the services and also increasing deployment and maintenance complexity?

In the earlier article, I talked about the concept of public and private APIs. We know that the de facto standard of implementing public API is the REST over HTTP. What if you want to expose public APIs as REST over HTTP but implement internal APIs as gRPC?

All the above concerns can be solved by introducing API Gateway/BFF. An API Gateway or BFF is a specialized service(s) that acts as an interface between APIs provided by the backed and the consumers of the APIs. The consumer of the API can be Frontend, third-party application consuming public APIs. The API Gateway service should be deployed along with the backend service. This reduces latency due to network round trip from the browser. It also acts as an aggregator omanyle requests into a single request.

There is a subtle difference between the BFF pattern and the API Gateway pattern. BFF pattern talks about, as the name suggests, a specialized backend for the frontend. For example, you can build separate BFF services for APIs consumed by mobile applications and browser applications.

As BFF is a specialized interface service meant for UI consumption, typically, it should be written and maintained by the Frontend team. If your microservice architecture is polyglot, then think of using the same language for your BFF Service for which your UI team is comfortable, for example — Node.js BFF service for Angular UI.

Want to understand more about BFF? Read this excellent article by SoundCloud engineering.

Sometimes API Gateway pattern is also confused with commercial API management offerings such as Amazon API Gateway, Apigee, etc. API Gateway is a design pattern that you can implement in your application and offload some of the common concerns such as API management, rate limiting, etc. to these commercial offerings.

Implementing API Gateway

In this article, you will see examples of implementing API Gateway where public API is exposed as REST over HTTP and private API is exposed as gRPC. You will also see how to implement the gRPC application as Spring Boot.

Product Gateway Service

Product Gateway is a simple microservice that exposes to public REST APIs.

To expose a POST REST endpoint define @PostMapping("/products") annotation as :

Ideally, you should pass the authorization information as the authorization header parameter but for simplicity sake, we are using userID as header parameter.

The ProductGatewayController delegates call to create a new Product to the ProductService. Implementation of ProductService does the RPC blocking call to the gRPC Product Service by creating newBlockingStub as:

The gRPC connection is created by ManagedChannel as Singleton Spring bean as:

Channels are expensive to create, and the general recommendation is to use one per application, shared among the service stubs.

gRPC API

The product service exposes gRPC endpoints as:

You can import resources.proto as import "resources.proto"; that includes message definition as :

The gRPC API for creating a new product is implemented in the Product Service as:

The above code first maps API request CreateProductRequest object to the domain object Product using MapStruct and then calls ProductRepository to persist the Product. The save method returns productId which is converted into CreateProductResponse object and returned by the gRPC API.

gRPC API as a Spring application

There are a couple of ways you can turn your gRPC Server application into a Spring Boot application. Some of them are:

Both are almost similar in feature, you can compare and decide which one to use. In this article, we will use yidongnan library.

The very first thing to do is to add grpc-spring-boot-starter dependencies as:

implementation 'net.devh:grpc-server-spring-boot-starter:2.12.0.RELEASE'

and next thing to do is to annotate your gRPC Service class with @GRpcService as:

@GrpcService 
public class ProductApiService extends ProductApiServiceGrpc.ProductApiServiceImplBase {

You can start your gRPC server as a Spring Boot application as:

Testing your code

To test you can run both services locally from IDE by running the main method of the class annotated with @SpringBootApplication. To test use curl (or Postman) as:

curl --location --request POST 'http://localhost:8080/products/' \ --header 'Content-Type: application/json' \ --header 'userId: abc@xyz.com' \ --data-raw '{ "name": "Apple iPhone 12", "description": "Apple iPhone 12 Pro Max 128 GB, Pacific Blue", "price": 1700 }'

Putting it all together

The API Gateway, aka BFF, reduces chattiness between clients and services by aggregating multiple requests into a single request. We can build specialized BFF services(s) to handle different interfaces for browser and mobile applications. The API Gateway can also be used to offload cross-cutting concerns such as authentication, authorization, rate limiting to a proxy. API Gateway allows us the flexibility of exposing public APIs as REST endpoints whereas implementing private APIs in different technology, for example, gRPC.

Originally published at https://techdozo.dev.

--

--

Pankaj Kumar

Software Architect @ Schlumberger ``` Cloud | Microservices | Programming | Kubernetes | Architecture | Machine Learning | Java | Python ```