Getting started with Spring Cloud Gateway

abstract

SpringCloud Gateway provides API gateway support for SpringBoot applications with powerful routing and filtering functions

brief introduction

Gateway is an API gateway service built on the Spring ecosystem and is based on technologies such as Spring 5, Spring Boot 2 and Project Reactor. Gateway aims to provide a simple and effective way to route APIs and provide some powerful filter functions, such as fusing, current limiting, Retry, etc.

Spring cloud gateway has the following features

  1. Based on Spring Framework 5, Project Reactor and Spring Boot 2.0;
  2. Dynamic routing, which can match any request attribute
  3. You can specify predicate and Filter for routes and are easy to write
  4. Integrated circuit breaker function of Hystrix
  5. Integrating spring cloud service discovery
  6. Request current limiting function
  7. Support path rewriting

Related concepts

  1. Route, which is the basic module of the gateway, consists of Id, target URL, a series of assertions and filters. If the assertion is true, the matching route will be changed;
  2. Predicate refers to the Function Predicate of Java 8. The input type is ServerWebExchange in the Spring framework. This allows developers to match everything in the HTTP request, such as the request header or request parameters. Route if the request matches the assertion;
  3. Filter refers to the instance of GatewayFilter in the Spring framework. Using the filter, you can modify the request before and after it is routed.

Create api_gateway module

Create an API here_ GateWay module to demonstrate the common functions of GateWay

Add related dependencies in pom.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 routes. One is to configure routes through yml files, and the other is to configure routes through JavaBeans, as described below

Use YML configuration

Configure in application.yml:

server:
  port: 9000

service-url:
  user-service: http://localhost:8090
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8081/eureka/

spring:
  cloud:
    gateway:
      routes:
        # ID of the route
        - id: path_route
          # Route address after matching
          uri: ${service-url.user-service}/user/{id}
          predicates:
            # Assert that the path matches the route
            - Path=/user/{id}

Start the registry, gateway and business services, and test the address http://localhost:9000/user/1
Finally, it is found that the request falls on the business service http://localhost:8090/user/1

Using JavaBean configuration

Add related configuration classes and configure a RouteLocator object:

@Configuration
public class GatewayConfig {

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

}

Request: localhost:9000/user/getByUserName?userName=123
Finally fall
localhost:8090/user/getByUserName?userName=123

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 such predicates will correspond to various attributes of the HTTP request. Moreover, multiple Predicate factories can be used in combination (which is the relationship of &)
Here are some common predictions

server:
  port: 9002

service-url:
  user-service: http://localhost:8090

spring:
  cloud:
    gateway:
      routes:
        # ID of the route
        - id: route
          # Route address after matching
          uri: ${service-url.user-service}
          predicates:
            # Assertion, after time
            - After=2021-05-01T18:30:00+08:00[Asia/Shanghai]

            # Assertion, before
#            - Before=2019-12-29T18:30:00+08:00[Asia/Shanghai]

            # Assertion, within time
#            - Between=2019-12-29T18:30:00+08:00[Asia/Shanghai], 2019-12-30T18:30:00+08:00[Asia/Shanghai]

            # Cookie=username´╝îjourwon Cookie
#            - Cookie=username,jourwon

            # The X-Request-Id is followed by an integer
#            - Header=X-Request-Id, \d+

            # Request to specify host
            - Host=xx.zglx.com
            -
            # get requested
            - Method=GET

            # Matching route
            - Path=/user/{id}

            # Matching parameters
            - Query=username

            # Match request remote address
            - RemoteAddr=192.168.1.1/24


Weight Route Predicate

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

server:
  port: 9003

service-url:
  user-serviceOne: http://localhost:8090
  user-serviceTwo: http://localhost:8091

spring:
  cloud:
    gateway:
      routes:
        # ID of the route
        - id: route_one
          # Route address after matching
          uri: ${service-url.user-serviceOne}
          predicates:
            - Weight=one,8
        - id: route_two
          # Route address after matching
          uri: ${service-url.user-serviceTwo}
          predicates:
            - Weight=one,2

Use of Route Filter

server:
  port: 9004

service-url:
  user-service: http://localhost:8090
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8081/eureka/

spring:
  cloud:
    gateway:
      routes:
        # ID of the route
        - id: path_route
          # Route address after matching
          uri: ${service-url.user-service}
#          predicates:
#            - Method=GET
          # AddRequestParameter, spring cloud has many built-in routing filters
#          filters:
#              # Add parameters to the request
#              - AddRequestParameter=username, jourwon

#
#
#          predicates:
#            - Path=/user-service/**
#          filters:
#            # /Remove two bits from the path of the request starting with user service /
#             - StripPrefix=2

          predicates:
            - Method=GET
          filters:
              # /user path prefix
              - PrefixPath=/user

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.

pom file add

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
package com.example.zglx.gateway.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * @Description:
 * @Author: Zlx
 * @Date: 2021/10/16 3:52 afternoon
 */
@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;
	}
}
spring:
  cloud:
    gateway:
      routes:
        - id: hystrix_route
          uri: ${service-url.user-service}
          predicates:
            - Method=GET
          filters:
            - name: Hystrix
              args:
                name: fallbackcmd
                fallback-uri: forward:/fallback

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.

pom dependency

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

Current limiting strategy

package com.example.zglx.gateway.config;

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;

@Configuration
public class RedisRateLimiterConfig {



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

server:
  port: 9001


service-url:
  user-service: http://localhost:8090
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8081/eureka/

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

Multiple requests http://localhost:8090/user/1

Retry GatewayFilter

server:
  port: 9005

service-url:
  user-service: http://localhost:8090
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8081/eureka/

spring:
  cloud:
    gateway:
      routes:
        # ID of the route
        - id: path_route
          # Route address after matching
          uri: ${service-url.user-service}
          predicates:
            # Assert that the path matches the route
            - Method=GET
#          filters:
#            - name: Hystrix
#              args:
#                name: fallbackcmd
#                fallback-uri: forward:/fallback
          filters:
            - name: Retry
              args:
                retries: 1 #Number of retries required
                statuses: BAD_GATEWAY #The returned status code needs to be retried. The returned status code is 5XX for retry
                backoff:
                  firstBackoff: 10ms
                  maxBackoff: 50ms
                  factor: 2
                  basedOnPreviousValue: false


If the service provider is abnormal, the gateway will retry twice

Use with registry

According to the registry, dynamic routing is used

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

service-url:
  user-service: http://localhost:8090
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8081/eureka/

spring:
  cloud:
    gateway:
      # Use lb to specify routes and use load balancing
      routes:
        - id: prefixpath_route
          #lb protocol is required here to use gateway load balancing
          uri: lb://user-service
          predicates:
            - Method=GET
          filters:
            - PrefixPath=/user
      discovery:
        locator :
          #Enable the function of dynamically creating routes from the registry
          enabled: true
          #Use lowercase service name, which is uppercase by default
          lower-case-service-id: true

# journal
logging:
  level:
    org.springframework.cloud.gateway: debug

Tags: Spring Spring Cloud

Posted on Sat, 16 Oct 2021 03:45:55 -0400 by rockinaway