Techdozo
  • Microservices
    • All
    • GraphQL
    • gRPC
    • Spring Boot
    gRPC Bidirectional Streaming with Code Example

    gRPC Bidirectional Streaming with Code Example

    gRPC Client Streaming

    gRPC Client Streaming

    Distributed transaction in microservices using Saga

    Distributed Transactions in Microservices: implementing Saga with Temporal

    Temporal Workflow Orchestration

    Workflow Orchestration with Temporal and Spring Boot

    GraphQL Directive

    GraphQL Directive

    Spring for GraphQL mutation

    Spring for GraphQL: Mutation

  • Spring Boot
    Spring Boot GraphQL service

    Getting started with Spring Boot GraphQL service

    Deploying a RESTful Spring Boot Microservice on Kubernetes

    Deploying a RESTful Spring Boot Microservice on Kubernetes

    RESTful Microservices with Spring Boot and Kubernetes

    RESTful Microservices with Spring Boot and Kubernetes

    RESTful API Gateway with gRPC

    RESTful API Gateway with gRPC

  • gRPC
    gRPC Bidirectional Streaming with Code Example

    gRPC Bidirectional Streaming with Code Example

    gRPC Client Streaming

    gRPC Client Streaming

    gRPC Interceptor: unary interceptor with code example

    gRPC Interceptor: unary interceptor with code example

    gRPC: synchronous and asynchronous Server streaming RPC

    gRPC: synchronous and asynchronous Server streaming RPC

    Photo by Ramón Salinero on Unsplash

    gRPC: synchronous and asynchronous unary RPC in Java

    Microservices inter-process communication using gRPC

    gRPC for microservices communication

  • GraphQL
    GraphQL Directive

    GraphQL Directive

    Spring for GraphQL mutation

    Spring for GraphQL: Mutation

    Spring for GraphQL: How to solve the N+1 Problem?

    Spring for GraphQL: How to solve the N+1 Problem?

    Spring GraphQL with @Controller, @SchemaMapping and @QueryMapping

    Spring for GraphQL : @SchemaMapping and @QueryMapping

    Spring Boot GraphQL service

    Getting started with Spring Boot GraphQL service

  • Kubernetes
    Deploying a RESTful Spring Boot Microservice on Kubernetes

    Deploying a RESTful Spring Boot Microservice on Kubernetes

    Components of Kubernetes Architecture

    Components of Kubernetes Architecture

    Helm Chart: quick start your app deployment on Kubernetes

    Helm Chart: quick start your app deployment on Kubernetes

    gRPC load balancing on Kubernetes (using Headless Service)

    gRPC load balancing on Kubernetes (using Headless Service)

    Getting started with Kind: quick start a multi-node local Kubernetes cluster

    Getting started with Kind: quick start a multi-node local Kubernetes cluster

    Getting started with Minikube: deploying application on local Kubernetes cluster

    Getting started with Minikube: deploying application on local Kubernetes cluster

  • Java
    Java Streams: Stream Operation with Examples

    Java Streams: Stream Operation with Examples

    Java Streams: stream creation with examples

    Java Streams: stream creation with examples

    Garbage Collection

    Super Fast Garbage Collectors in Java

    Calculus

    Functional Programming in Java

No Result
View All Result
  • Login
  • Microservices
    • All
    • GraphQL
    • gRPC
    • Spring Boot
    gRPC Bidirectional Streaming with Code Example

    gRPC Bidirectional Streaming with Code Example

    gRPC Client Streaming

    gRPC Client Streaming

    Distributed transaction in microservices using Saga

    Distributed Transactions in Microservices: implementing Saga with Temporal

    Temporal Workflow Orchestration

    Workflow Orchestration with Temporal and Spring Boot

    GraphQL Directive

    GraphQL Directive

    Spring for GraphQL mutation

    Spring for GraphQL: Mutation

  • Spring Boot
    Spring Boot GraphQL service

    Getting started with Spring Boot GraphQL service

    Deploying a RESTful Spring Boot Microservice on Kubernetes

    Deploying a RESTful Spring Boot Microservice on Kubernetes

    RESTful Microservices with Spring Boot and Kubernetes

    RESTful Microservices with Spring Boot and Kubernetes

    RESTful API Gateway with gRPC

    RESTful API Gateway with gRPC

  • gRPC
    gRPC Bidirectional Streaming with Code Example

    gRPC Bidirectional Streaming with Code Example

    gRPC Client Streaming

    gRPC Client Streaming

    gRPC Interceptor: unary interceptor with code example

    gRPC Interceptor: unary interceptor with code example

    gRPC: synchronous and asynchronous Server streaming RPC

    gRPC: synchronous and asynchronous Server streaming RPC

    Photo by Ramón Salinero on Unsplash

    gRPC: synchronous and asynchronous unary RPC in Java

    Microservices inter-process communication using gRPC

    gRPC for microservices communication

  • GraphQL
    GraphQL Directive

    GraphQL Directive

    Spring for GraphQL mutation

    Spring for GraphQL: Mutation

    Spring for GraphQL: How to solve the N+1 Problem?

    Spring for GraphQL: How to solve the N+1 Problem?

    Spring GraphQL with @Controller, @SchemaMapping and @QueryMapping

    Spring for GraphQL : @SchemaMapping and @QueryMapping

    Spring Boot GraphQL service

    Getting started with Spring Boot GraphQL service

  • Kubernetes
    Deploying a RESTful Spring Boot Microservice on Kubernetes

    Deploying a RESTful Spring Boot Microservice on Kubernetes

    Components of Kubernetes Architecture

    Components of Kubernetes Architecture

    Helm Chart: quick start your app deployment on Kubernetes

    Helm Chart: quick start your app deployment on Kubernetes

    gRPC load balancing on Kubernetes (using Headless Service)

    gRPC load balancing on Kubernetes (using Headless Service)

    Getting started with Kind: quick start a multi-node local Kubernetes cluster

    Getting started with Kind: quick start a multi-node local Kubernetes cluster

    Getting started with Minikube: deploying application on local Kubernetes cluster

    Getting started with Minikube: deploying application on local Kubernetes cluster

  • Java
    Java Streams: Stream Operation with Examples

    Java Streams: Stream Operation with Examples

    Java Streams: stream creation with examples

    Java Streams: stream creation with examples

    Garbage Collection

    Super Fast Garbage Collectors in Java

    Calculus

    Functional Programming in Java

No Result
View All Result
Techdozo
No Result
View All Result
Home Microservices gRPC

RESTful API Gateway with gRPC

Pankaj by Pankaj
May 23, 2021
in gRPC, Microservices, Spring Boot
Reading Time: 11 mins read
0
A A
0
RESTful API Gateway with gRPC
0
SHARES
4.7k
VIEWS
Share on FacebookShare on TwitterShare on Linkedin

If you are designing an application as microservices architecture, then you must have heard the term API Gateway, aka Backend for Frontend (BFF). It is an important design pattern for building applications based on microservices architecture. A very common architecture pattern is to use gRPC for internal microservices communication and expose public RESTful APIs by API Gateway.

In this article, I will delve deeper into the whys of API Gateway (BFF) 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 as Gradle project.

To build the project and generate client and server stubs, run the command gradlew clean build. You can start the gRPC server in IDE by running the main method of ProductApplication. The gRPC server runs on localhost:8001.

You can run API Gateway microservice, product-gateway, as Spring Boot application by running ProductGatewayApplication in IDE.

Why API Gateway?

One important aspect of API design is determining the right size of an API in terms of its features and functionality. A microservice, typically, exposes fine-grained APIs instead of coarse-grained API. The fine-grained APIs introduces some problem for UI workflow.

The problem of fine-grained APIs

Imagine, you are building an e-Commerce application using microservices. You may have microservices for Products, Orders, Offers, Inventory, etc. 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 may have to call different microservices to show product detail page as:

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

Cross-cutting concerns

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 a shared or specialized service with each microservice (or as a library, which can be consumed by all services)? There is no doubt that this approach increases the tight coupling between the microservices and also increases deployment and maintenance complexity

In the article gRPC for microservices communication, 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.

What is API Gateway?

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 of many requests into a single request.

(Aggregating different 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.

(Different BFF for browser and mobile 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, if your application frontend is in Angular then use Node.js as a BFF service.

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

API management vs API Gateway

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

The product-gateway is an API Gateway microservice that exposes to public RESTful APIs.

  • Create a new product: POST /products
  • Get product: GET /products/{productId}

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


@PostMapping("/products")
 public ResponseEntity<ProductResponse> createProduct(
     @RequestHeader(value = "userId") String userId, @RequestBody Product product) {
   product.setUserId(userId);
   var productId = productService.createNewProduct(product);
   var productResponse = new ProductResponse(productId);
   return new ResponseEntity<>(productResponse, HttpStatus.CREATED);
 }

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

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


public String createNewProduct(Product product) {
  var createProductRequest =
       CreateProductRequest.newBuilder()
           .setPrice(product.getPrice())
           .setName(product.getName())
           .setDescription(product.getDescription())
           .setUserId(product.getUserId())
           .build();
  var productApiServiceBlockingStub = ProductServiceGrpc.newBlockingStub(managedChannel);
  var response = productApiServiceBlockingStub.createProduct(createProductRequest);
  var productId = response.getProductId();
  return productId;
}

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


@Bean
public ManagedChannel managedChannel() {
  return ManagedChannelBuilder.forAddress(
          applicationProperties().getHost(), applicationProperties().getPort())
      .usePlaintext()
      .build();
}

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 APIs as:


syntax = "proto3";
package dev.techdozo.product;
import "resources.proto";

option java_package = "dev.techdozo.product.resource";
option java_multiple_files = true;

service ProductService {
  rpc CreateProduct(CreateProductRequest) returns (CreateProductResponse);
}

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


syntax = "proto3";
package dev.techdozo.product;

message CreateProductRequest {
  string name = 1;
  string description = 2;
  double price = 3;
  string userId = 4;
}

message CreateProductResponse {
  string productId = 1;
}

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


public void createProduct(
    CreateProductRequest request, StreamObserver<CreateProductResponse> responseObserver) {

  var product = ProductMapper.MAPPER.map(request);
  var productId = productRepository.save(product);

  var createProductResponse = CreateProductResponse.newBuilder().setProductId(productId).build();

  responseObserver.onNext(createProductResponse);
  responseObserver.onCompleted();
}

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 microservice as a Spring Boot application

There are many benefits of making gRPC microservice as Spring Boot application if you are using Spring Boot as a technology stack. For instance, you can use the dependency injection provided by a Spring Boot application.

There are a couple of approaches to make a gRPC microservices as a Spring Boot application. Some of them are:

  • LogNet/grpc-spring-boot-starter
  • yidongnan/grpc-spring-boot-starter

Both are almost similar in feature, and 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:


@SpringBootApplication
public class ProductApplication {
  public static void main(String[] args) {
    SpringApplication.run(ProductApplication.class, args);
  }
}

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. You 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 RESTful APIs whereas keeping private APIs as gRPC.

Tags: grpcjavaspring
Previous Post

Deploying and accessing a microservices application in Kubernetes

Next Post

Getting Error Handling right in gRPC

Pankaj

Pankaj

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

Related Posts

gRPC Bidirectional Streaming with Code Example
gRPC

gRPC Bidirectional Streaming with Code Example

February 17, 2023
gRPC Client Streaming
gRPC

gRPC Client Streaming

January 20, 2023
Distributed transaction in microservices using Saga
Microservices

Distributed Transactions in Microservices: implementing Saga with Temporal

November 8, 2022
Temporal Workflow Orchestration
Microservices

Workflow Orchestration with Temporal and Spring Boot

October 29, 2022

Discussion about this post

Recent Articles

gRPC Bidirectional Streaming with Code Example

gRPC Bidirectional Streaming with Code Example

February 17, 2023
gRPC Client Streaming

gRPC Client Streaming

January 20, 2023
Distributed transaction in microservices using Saga

Distributed Transactions in Microservices: implementing Saga with Temporal

November 8, 2022
Temporal Workflow Orchestration

Workflow Orchestration with Temporal and Spring Boot

October 29, 2022
  • Trending
  • Comments
  • Latest
Deploying a RESTful Spring Boot Microservice on Kubernetes

Deploying a RESTful Spring Boot Microservice on Kubernetes

August 18, 2021
Temporal Workflow Orchestration

Workflow Orchestration with Temporal and Spring Boot

October 29, 2022
gRPC Interceptor: unary interceptor with code example

gRPC Interceptor: unary interceptor with code example

April 30, 2022
Microservices inter-process communication using gRPC

gRPC for microservices communication

August 29, 2021
Calculus

Functional Programming in Java

0
Java Streams: stream creation with examples

Java Streams: stream creation with examples

0
Garbage Collection

Super Fast Garbage Collectors in Java

0
Java Streams: Stream Operation with Examples

Java Streams: Stream Operation with Examples

0
gRPC Bidirectional Streaming with Code Example

gRPC Bidirectional Streaming with Code Example

February 17, 2023
gRPC Client Streaming

gRPC Client Streaming

January 20, 2023
Distributed transaction in microservices using Saga

Distributed Transactions in Microservices: implementing Saga with Temporal

November 8, 2022
Temporal Workflow Orchestration

Workflow Orchestration with Temporal and Spring Boot

October 29, 2022
Facebook Twitter Pinterest

TECHDOZO

Simplifying modern tech stack!

Browse by Category

  • Bitesize
  • GraphQL
  • gRPC
  • Java
  • Kubernetes
  • Microservices
  • Spring Boot

Recent Articles

gRPC Bidirectional Streaming with Code Example

gRPC Bidirectional Streaming with Code Example

February 17, 2023
gRPC Client Streaming

gRPC Client Streaming

January 20, 2023

© 2023 Techdozo.

No Result
View All Result
  • Home
  • gRPC
  • Kubernetes
  • Microservices
  • GraphQL

© 2023 Techdozo.

Welcome Back!

Sign In with Google
OR

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In