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
- Based on Spring Framework 5, Project Reactor and Spring Boot 2.0;
- Dynamic routing, which can match any request attribute
- You can specify predicate and Filter for routes and are easy to write
- Integrated circuit breaker function of Hystrix
- Integrating spring cloud service discovery
- Request current limiting function
- Support path rewriting
Related concepts
- 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;
- 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;
- 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