Spring cloud gateway

introduce

Spring Cloud Gateway is a gateway officially developed by spring based on Spring 5.0, Spring Boot 2.0, Project Reactor and other technologies. Spring Cloud Gateway aims to provide a simple and effective unified API routing management method for microservice architecture. As a gateway in the Spring Cloud ecosystem, the goal of Spring Cloud Gateway is to replace ZUUL. It not only provides a unified routing method, but also provides the basic functions of the gateway based on the Filter chain, such as security, monitoring / embedding point, current limiting, etc.

Create API gateway module

pom. Add related dependencies to XML

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

Two different routing configurations

Gateway provides two different ways to configure routing, one is through yml file, the other is through Java Bean. Let's introduce them respectively.

Using yml configuration

  • In application Configure in YML:
server:
  port: 9201
service-url:
  user-service: http://localhost:8201
spring:
  cloud:
    gateway:
      routes:
        - id: path_route #ID of the route
          uri: ${service-url.user-service}/user/{id} #Route address after matching
          predicates: # Assert that the path matches the route
            - Path=/user/{id}
  • Start Eureka server, user service and API gateway services, and call the address to test: http://localhost:9201/user/1

  • We found that the request was routed to the path of user service: http://localhost:8201/user/1

Using Java Bean configuration

  • Add relevant configuration classes and configure a RouteLocator object:
/**
 * Created by macro on 2019/9/24.
 */
@Configuration
public class GatewayConfig {

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("path_route2", r -> r.path("/user/getByUsername")
                        .uri("http://localhost:8201/user/getByUsername"))
                .build();
    }
}

  • Restart the API gateway service and call the address test: http://localhost:9201/user/getByUsername?username=macro

  • We found that the request was routed to the path of user service: http://localhost:8201/user/getByUsername?username=macro

Use of Route Predicate

Spring Cloud Gateway takes route matching as part of the Spring WebFlux HandlerMapping infrastructure. Spring Cloud Gateway includes many built-in route predict factories. All these predictions match the different attributes of the HTTP request. Multiple route predictors can be combined. Let's introduce some common route predictors.
Note: the configurations mentioned in predict are all in application predict Modify in the YML file and start the API gateway service with this configuration.

After Route Predicate

Requests after the specified time will match the route.

spring:
  cloud:
    gateway:
      routes:
        - id: after_route
          uri: ${service-url.user-service}
          predicates:
            - After=2019-09-24T16:30:00+08:00[Asia/Shanghai]

Before Route Predicate

Requests before the specified time will match the route.

spring:
  cloud:
    gateway:
      routes:
        - id: before_route
          uri: ${service-url.user-service}
          predicates:
            - Before=2019-09-24T16:30:00+08:00[Asia/Shanghai]

Between Route Predicate

Requests within the specified time interval will match the route.

spring:
  cloud:
    gateway:
      routes:
        - id: before_route
          uri: ${service-url.user-service}
          predicates:
            - Between=2019-09-24T16:30:00+08:00[Asia/Shanghai], 2019-09-25T16:30:00+08:00[Asia/Shanghai]

Cookie Route Predicate

Requests with the specified Cookie match the route.

spring:
  cloud:
    gateway:
      routes:
        - id: cookie_route
          uri: ${service-url.user-service}
          predicates:
            - Cookie=username,macro

Using curl tool to send a request with a cookie of username=macro can match the route.

curl http://localhost:9201/user/1 --cookie "username=macro"

Header Route Predicate

The request with the specified request header matches the route.

spring:
  cloud:
    gateway:
      routes:
      - id: header_route
        uri: ${service-url.user-service}
        predicates:
        - Header=X-Request-Id, \d+

Using curl tool to send a request with request header X-Request-Id:123 can match the route.

curl http://localhost:9201/user/1 -H "X-Request-Id:123"

Host Route Predicate

Requests with the specified Host will match the route.

spring:
  cloud:
    gateway:
      routes:
        - id: host_route
          uri: ${service-url.user-service}
          predicates:
            - Host=**.macrozheng.com

Use curl tool to send a request with a header of Host:www.macrozheng.com Com requests can match the route.

curl http://localhost:9201/user/1 -H "Host:www.macrozheng.com"

Method Route Predicate

The request to send the specified method will match the route.

spring:
  cloud:
    gateway:
      routes:
      - id: method_route
        uri: ${service-url.user-service}
        predicates:
        - Method=GET

The route can be matched by sending a GET request using the curl tool.

curl http://localhost:9201/user/1

Sending a POST request using curl tool cannot match the route.

curl -X POST http://localhost:9201/user/1

Path Route Predicate

The request to send the specified path will match the route.

spring:
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: ${service-url.user-service}/user/{id}
          predicates:
            - Path=/user/{id}

Using curl tool to send / user/1 path request can match this route.

curl http://localhost:9201/user/1

The / abc/1 path request sent by curl tool cannot match the route.

curl http://localhost:9201/abc/1

Query Route Predicate

Requests with specified query parameters can match the route.

spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: ${service-url.user-service}/user/getByUsername
        predicates:
        - Query=username

Using curl tool to send a request with username=macro query parameter can match the route.

curl http://localhost:9201/user/getByUsername?username=macro

Sending a request with or without query parameters using curl tool cannot match the route.

curl http://localhost:9201/user/getByUsername

RemoteAddr Route Predicate

Requests originating from the specified remote address can match the route.

spring:
  cloud:
    gateway:
      routes:
      - id: remoteaddr_route
        uri: ${service-url.user-service}
        predicates:
        - RemoteAddr=192.168.1.1/24

The route can be matched by sending a request from 192.168.1.1 using curl tool.

curl http://localhost:9201/user/1

Weight Route Predicate

Use the weight to route the corresponding requests. The following shows that 80% of the requests will be routed to localhost:8201 and 20% to localhost:8202.

spring:
  cloud:
    gateway:
      routes:
      - id: weight_high
        uri: http://localhost:8201
        predicates:
        - Weight=group1, 8
      - id: weight_low
        uri: http://localhost:8202
        predicates:
        - Weight=group1, 2

Use of Route Filter

The routing filter can be used to modify the incoming HTTP request and the returned HTTP response. The routing filter can only be used by specifying the route. Spring Cloud Gateway
There are many built-in routing filters, which are generated by the factory class of GatewayFilter. Let's introduce the usage of common routing filters.

AddRequestParameter GatewayFilter

A filter that adds parameters to the request.

spring:
  cloud:
    gateway:
      routes:
        - id: add_request_parameter_route
          uri: http://localhost:8201
          filters:
            - AddRequestParameter=username, macro
          predicates:
            - Method=GET

The above configuration will add the request parameter of username=macro to the GET request, and use the following command to test through curl tool.

curl http://localhost:9201/user/getByUsername

Equivalent to initiating the request:

curl http://localhost:8201/user/getByUsername?username=macro

StripPrefix GatewayFilter

A filter that removes a specified number of path prefixes.

spring:
  cloud:
    gateway:
      routes:
      - id: strip_prefix_route
        uri: http://localhost:8201
        predicates:
        - Path=/user-service/**
        filters:
        - StripPrefix=2

The above configuration will remove two bits from the path of the request starting with / user service /, and use the following command to test through curl tool.

curl http://localhost:9201/user-service/a/user/1

Copying the code is equivalent to initiating the request:

curl http://localhost:8201/user/1

PrefixPath GatewayFilter

Contrary to the StripPrefix filter, it is a filter that adds to the original path.

spring:
  cloud:
    gateway:
      routes:
      - id: prefix_path_route
        uri: http://localhost:8201
        predicates:
        - Method=GET
        filters:
        - PrefixPath=/user

The above configuration will add / user path prefix to all GET requests, and use the following command to test through curl tool.

curl http://localhost:9201/1

Equivalent to initiating the request:

curl http://localhost:8201/user/1

Hystrix GatewayFilter

The Hystrix filter allows you to add the circuit breaker function to the gateway routing, protect your service from cascading failures, and provide service degradation processing.

To turn on the circuit breaker function, we need to switch on the POM Add the related dependencies of Hystrix in XML:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

Then add the processing class of related service degradation:

/**
 * Created by macro on 2019/9/25.
 */
@RestController
public class FallbackController {

    @GetMapping("/fallback")
    public Object fallback() {
        Map<String,Object> result = new HashMap<>();
        result.put("data",null);
        result.put("message","Get request fallback!");
        result.put("code",500);
        return result;
    }
}

In application filter Add relevant configurations in YML. When the route fails, it will be forwarded to the controller for service degradation processing:

spring:
  cloud:
    gateway:
      routes:
        - id: hystrix_route
          uri: http://localhost:8201
          predicates:
            - Method=GET
          filters:
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/fallback
  • Close the user service and call the address to test: http://localhost:9201/user/1 , it is found that the processing information of service degradation has been returned.

RequestRateLimiter GatewayFilter

The RequestRateLimiter filter can be used to limit the flow. The RateLimiter implementation is used to determine whether to allow the current request to continue. If the request is too large, the HTTP 429- too many request status will be returned by default.

In POM Add related dependencies to XML:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>

Add the configuration class of current limiting policy. There are two strategies: one is to limit the current according to the username in the request parameter, and the other is to limit the current according to the access IP;

/**
 * Created by macro on 2019/9/25.
 */
@Configuration
public class RedisRateLimiterConfig {
    @Bean
    KeyResolver userKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("username"));
    }

    @Bean
    public KeyResolver ipKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
    }
}

We use Redis to limit the flow, so we need to add the configuration of Redis and RequestRateLimiter. All GET requests are limited by IP;

server:
  port: 9201
spring:
  redis:
    host: localhost
    password: 123456
    port: 6379
  cloud:
    gateway:
      routes:
        - id: requestratelimiter_route
          uri: http://localhost:8201
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 1 #Number of requests allowed to be processed per second
                redis-rate-limiter.burstCapacity: 2 #Maximum number of requests processed per second
                key-resolver: "#{@ipKeyResolver}" #Current limiting policy, Bean corresponding to the policy
          predicates:
            - Method=GET
logging:
  level:
    org.springframework.cloud.gateway: debug

Retry GatewayFilter

The filter that retries the routing request can determine whether to retry according to the HTTP status code returned by the routing request.

To modify a profile:

spring:
  cloud:
    gateway:
      routes:
      - id: retry_route
        uri: http://localhost:8201
        predicates:
        - Method=GET
        filters:
        - name: Retry
          args:
            retries: 1 #Number of retries required
            statuses: BAD_GATEWAY #Which status code needs to be returned for retry? The status code returned is 5XX for retry
            backoff:
              firstBackoff: 10ms
              maxBackoff: 50ms
              factor: 2
              basedOnPreviousValue: false

When the call returns 500, it will retry and access the test address: http://localhost:9201/user/111

It can be found that the user service console reported an error twice, indicating a retry.

2019-10-27 14:08:53.435 ERROR 2280 --- [nio-8201-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause

java.lang.NullPointerException: null
	at com.macro.cloud.controller.UserController.getUser(UserController.java:34) ~[classes/:na]

Use with registry

Last time we talked about using Zuul as a gateway in combination with the registry. By default, Zuul will create a dynamic route with the service name as the path according to the service list registered in the registry. Gateway also realizes this function. Let's demonstrate how the gateway uses the default dynamic routing and filter in combination with the registry.

Use dynamic routing

In POM Add related dependencies to XML:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

Add application Eureka YML profile:

server:
  port: 9201
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #Enable the function of dynamically creating routes from the registry
          lower-case-service-id: true #Use lowercase service name, which is uppercase by default
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8001/eureka/
logging:
  level:
    org.springframework.cloud.gateway: debug

Use application Eureka YML configuration file starts API gateway service and accesses http://localhost:9201/user-service/user/1, which can be routed to the user service http://localhost:8201/user/1 Office.

Use filter

When using the filter in combination with the registry, we should note that the uri protocol is lb, so that the load balancing function of the Gateway can be enabled.

Modify application Eureka YML file, using PrefixPath filter, will add / user path and route for all GET request paths;

server:
  port: 9201
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: prefixpath_route
          uri: lb://User service # requires lb protocol
          predicates:
            - Method=GET
          filters:
            - PrefixPath=/user
      discovery:
        locator:
          enabled: true
eureka:
  client:
    service-url: 
      defaultZone: http://localhost:8001/eureka/
logging:
  level:
    org.springframework.cloud.gateway: debug

Use application Eureka YML configuration file starts API gateway service and accesses http://localhost:9201/1 , which can be routed to the user service http://localhost:8201/user/1 Office.

Modules used

springcloud-learning
- eureka server - eureka registry
User service - the service that provides the CRUD interface of the user object
└ - API Gateway - Test Service of gateway

Tags: Java gateway

Posted by Sander on Fri, 15 Apr 2022 15:42:02 +0930