Spring Cloud Gateway Example


In a previous tutorial we had implemented API Gateway using Netflix Zuul Component. However Zuul is a blocking API. A blocking gateway api makes use of as many threads as the number of incoming requests. So this approach is more resource intensive. If no threads are available to process incoming request then the request has to wait in queue.
In this tutorial we will be implementing API Gateway using Spring Cloud Gateway. Spring Cloud Gateway is a non blocking API. When using non blocking API, a thread is always available to process the incoming request. These request are then processed asynchronously in the background and once completed the response is returned. So no incoming request never gets blocked when using Spring Cloud Gateway.
We will first look at what is API gateway and why are they needed. Then we will be exploring the Spring Cloud Gateway Architecture and implement an API Gateway using it.

Video

This tutorial is explained in the below Youtube Video.


What is an API Gateway? Why do we need it?

An API Gateway acts as a single entry point for a collection of microservices. Any external client cannot access the microservices directly but can access them only through the application gateway
In a real world scenario an external client can be any one of the three-
  • Mobile Application
  • Desktop Application
  • External Services or third party Apps

spring cloud gateway tutorial

The advantages of this approach are as follows-
  • This improves the security of the microservices as we limit the access of external calls to all our services.
  • The cross cutting concerns like authentication, monitoring/metrics, and resiliency will be needed to be implemented only in the API Gateway as all our calls will be routed through it.
  • The client does not know about the internal architecture of our microservices system. Client will not be able to determine the location of the microservice instances.
  • Simplifies client interaction as he will need to access only a single service for all the requirements.

Spring Cloud Gateway Architecture

Spring Cloud Gateway is API Gateway implementation by Spring Cloud team on top of Spring reactive ecosystem. It consists of the following building blocks-
  • Route: Route the basic building block of the gateway. It consists of
    • ID
    • destination URI
    • Collection of predicates and a collection of filters
  • A route is matched if aggregate predicate is true.
  • Predicate: This is similar to Java 8 Function Predicate. Using this functionality we can match HTTP request, such as headers , url, cookies or parameters.
  • Filter: These are instances Spring Framework GatewayFilter. Using this we can modify the request or response as per the requirement. We will be looking at filters in detail in the next tutorial - Spring Cloud Tutorial - Spring Cloud Gateway Filters Example

spring cloud gateway architecture
When the client makes a request to the Spring Cloud Gateway, the Gateway Handler Mapping first checks if the request matches a route. This matching is done using the predicates. If it matches the predicate then the request is sent to the filters.


Implementing Spring Cloud Gateway

Using Spring Cloud Gateway we can create routes in either of the two ways -
  • Use java based configuration to programmatically create routes
  • Use property based configuration(i.e application.properties or application.yml) to create routes.
In this tutorial we will be implementing Spring Cloud Gateway using both configurations.
We will be implementing Spring Cloud Gateway application which routes request to two other microservices depending on the url pattern.
spring cloud gateway

Implement First Microservice

The Maven project will be as follows-
spring cloud first microservice

The pom.xml will be as follows:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.javainuse</groupId>
<artifactId>first-service</artifactId>
<version>0.0.1-SNAPSHOT</version>

<properties>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

</project>
Define the application.yml as follows-
spring:
application:
name: first-service
server:
port: 8081
Create a Controller class that exposes the GET REST service as follows-
package com.javainuse.controller;

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/employee")

public class FirstController {

@GetMapping("/message")
public String test() {
return "Hello JavaInUse Called in First Service";
}
}

Create the bootstrap class with the @SpringBootApplication annotation
package com.javainuse;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class FirstApplication {

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

}

Implement Second Microservice

The Maven project will be as follows-
spring cloud second microservice
The pom.xml will be as follows-
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.javainuse</groupId>
<artifactId>second-service</artifactId>
<version>0.0.1-SNAPSHOT</version>

<properties>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

</project>
Define the application.properties as follows-
spring:
application:
name: second-service
server:
port: 8082
Create a Controller class that exposes the GET REST service as follows-
package com.javainuse.controller;

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/consumer")

public class SecondController {

@GetMapping("/message")
public String test() {
return "Hello JavaInUse Called in Second Service";
}

}
Create the bootstrap class with the @SpringBootApplication annotation
package com.javainuse;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SecondApplication {

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

Implement Spring Cloud Gateway using property based config

The Maven project will be as follows-
spring cloud gateway microservice

The pom.xml will be as follows-
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.javainuse</groupId>
<artifactId>cloud-gateway-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gateway-service</name>

<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR2</spring-cloud.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

</dependencies>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>
Define the application.yml as follows-
server:
port: 8080

spring:
cloud:
gateway:
routes:
- id: employeeModule
uri: http://localhost:8081/
predicates:
- Path=/employee/**
- id: consumerModule
uri: http://localhost:8082/
predicates:
- Path=/consumer/**

Create the bootstrap class with the @SpringBootApplication annotation
package com.javainuse;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class APIGatewayApplication {

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

}

Start the three microservices we have developed-
  • Go to url - localhost:8080/employee/message
    spring cloud gateway API tutorial
  • Go to url - localhost:8080/consumer/message
    spring cloud gateway example

Implement Spring Cloud Gateway using Java based config

The Maven project will be as follows-
spring cloud gateway config microservice

The pom.xml will be as follows-
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.javainuse</groupId>
<artifactId>cloud-gateway-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gateway-service</name>

<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR2</spring-cloud.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

</dependencies>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>
Define the application.yml as follows-
server:
port: 8080
Create the configuration class where we define the route configurations. Gateway Handler resolves route configurations by using RouteLocator Bean.
package com.javainuse.config;

import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringCloudConfig {

@Bean
public RouteLocator gatewayRoutes(RouteLocatorBuilder builder) {
return builder.routes()
.route(r -> r.path("/employee/**")
.uri("http://localhost:8081/")
.id("employeeModule"))

.route(r -> r.path("/consumer/**")
.uri("http://localhost:8082/")
.id("consumerModule"))

.build();
}

}
Create the bootstrap class with the @SpringBootApplication annotation
package com.javainuse;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class APIGatewayApplication {

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

}

Start the three microservices we have developed-
  • Go to url - localhost:8080/employee/message
    spring cloud gateway API tutorial
  • Go to url - localhost:8080/consumer/message
    spring cloud gateway example



Post a Comment

Mới hơn Cũ hơn