Simple to get started, copy directly, you can build microservices (Hoxton.SR8) 2020.8.28 released, SpringCloud build articles are being sorted out, don’t miss out on dry goods
-
SpringCloud microservices can also be used by novices (Hoxton.SR8) (2) Ribbon|Service Consumers
-
SpringCloud microservices Xiaobai can also take (Hoxton.SR8) (3) Feign|Service Consumers
-
SpringCloud microservices Xiaobai can also take (Hoxton.SR8) (4) Hystrix|Circuit Breaker
-
SpringCloud Microservice Xiaobai can also take (Hoxton.SR8) (6) Zuul|Service Gateway
-
SpringCloud microservice Xiaobai can also take (Hoxton.SR8) (7) Gateway|Service Gateway
-
SpringCloud white micro-services can take (Hoxton.SR8) (eight) Sleuth | Link Tracking Service
Summary
Spring Cloud Gateway provides API gateway support for SpringBoot applications, with powerful intelligent routing and filter functions. Gateway is an API gateway service built on the Spring ecosystem, 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: fuse, current limit, retry, etc.
Spring Cloud Gateway has the following features:
- Based on Spring Framework 5, Project Reactor and Spring Boot 2.0;
- Dynamic routing: can match any request attribute;
- Predicate (assertion) and Filter (filter) can be specified for routing;
- Integrated Hystrix circuit breaker function;
- Integrate Spring Cloud service discovery function;
- Easy to write Predicate (assertion) and Filter (filter);
- Request current limiting function;
- Support path rewriting.
Configuration composition
- Route: Route is the basic module for building a gateway. It consists of ID, target URI, a series of assertions and filters. If the assertion is true, it will match the route;
- Predicate (assertion): Refers to the Function Predicate of Java 8. The input type is ServerWebExchange in the Spring framework. This allows developers to match all content in the HTTP request, such as request headers or request parameters. If the request matches the assertion, it is routed;
- Filter (filter): Refers to an instance of GatewayFilter in the Spring framework. With filters, the request can be modified before and after the request is routed.
1. Create an api-gateway module
2 Use gateway alone
2.1 New gateway dependency in pom.xml
<?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">
<parent>
<artifactId>cloud-hoxton-sr8</artifactId>
<groupId>com.zqh.www</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>api-gateway</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.2 Startup
package com.zqh.www;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.Environment;
@SpringBootApplication
public class ApiGatewayApplication {
private final static Logger logger = LoggerFactory.getLogger(ApiGatewayApplication.class);
public static void main(String[] args) {
Environment env = SpringApplication.run(ApiGatewayApplication.class, args).getEnvironment();
logger.info(
"\n----------------------------------------------------------\n\t"
+ "Application '{}' is running! Access URLs:\n\t"
+ "Local: \t\thttp://localhost:{}{}"
+ "\n----------------------------------------------------------",
env.getProperty("spring.application.name"), env.getProperty("server.port"),
env.getProperty("server.servlet.context-path") != null ? env.getProperty("server.servlet.context-path") : "");
}
}
2.3 ed
server:
port: 8093
service-url:
user-service: http://localhost:8084
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
# 路由的ID
- id: user-service
# 匹配后路由地址
uri: ${service-url.user-service}
predicates:
# 发送指定路径的请求会匹配该路由。
- Path=/api/user/*
# # 发送指定方法的请求会匹配该路由。
# - Method=GET
# # 在指定时间之后的请求会匹配该路由。
# - After=2020-10-20T12:00:00+08:00[Asia/Shanghai]
# # 在指定时间之前的请求会匹配该路由。
# - Before=2020-10-20T12:00:00+08:00[Asia/Shanghai]
# # 在指定时间区间内的请求会匹配该路由。
# - Between=2020-10-20T12:00:00+08:00[Asia/Shanghai], 2020-10-30T12:00:00+08:00[Asia/Shanghai]
# # 带有指定Cookie的请求会匹配该路由
# - Cookie=username,jourwon
# # 带有指定请求头的请求会匹配该路由。
# - Header=auth
# #带有指定Host的请求会匹配该路由。
# - Host=www.zqh.com
# # 从指定远程地址发起的请求可以匹配该路由。
# - RemoteAddr=192.168.1.1/24
filters:
# - AddRequestParameter=username,z
# - StripPrefix=1
# - PrefixPath=/api
logging:
level:
org.springframework.cloud.gateway: debug
2.4 predicates-test cases
Note: If there are multiple conditions, all the conditions must be met to match the relevant route
2.4.1 predicates - Path
Description: Send a request that matches the path or will match the route.
yml configuration:-Path=/api/user/*
Interface request: http://localhost:8093/api/user/getUserList is
equivalent to: http://localhost:8084/api/user/ getUserList
2.4.2 predicates - Method
Description: Sending a request for the specified method will match the route.
Interface request: http://localhost:8093/api/user/getUserList
2.4.3 predicates - After
Description: Requests after the specified time will match the route.
Interface request: http://localhost:8093/api/user/getUserList
2.4.4 predicates - Before
Description: Requests before the specified time will match this route.
2.4.5 predicates - Between
Description: Requests within the specified time interval will match this route.
2.4.6 predicates - Cookie
Description: The request with the specified cookie will match the route.
Configuration:
predicates:
# 带有指定Cookie的请求会匹配该路由
- Cookie=username,z
Interface request:
2.4.7 predicates - Header
Description: A request with the specified request header will match the route.
Settings:
predicates:
# 带有指定请求头的请求会匹配该路由。
- Header=auth
Interface request:
2.4.8 predicates - Host
Description: Requests with the specified Host will match the route.
Settings:
predicates:
#带有指定Host的请求会匹配该路由。
- Host=www.zqh.com
2.4.9 predicates - RemoteAddr
Description: Requests from the specified path will match the route.
Settings:
predicates:
#从指定远程地址发起的请求可以匹配该路由。
- RemoteAddr=192.168.0.100
2.5 filters-test case
2.5.1 filters - AddRequestParameter
Description: Add request parameters to GET request
Configuration:
service-url:
user-service: http://localhost:8084
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
# 路由的ID
- id: user-service
# 匹配后路由地址
uri: ${service-url.user-service}
predicates:
# 发送指定路径的请求会匹配该路由。
- Path=/api/user/*
filters:
- AddRequestParameter=username,z
Request: http://localhost:8093/api/user/getUserList is
equivalent to: http://localhost:8084 /api/user/getUserList ?username=z
2.5.2 filters - StripPrefix
Description: The path of the request at the beginning will remove the specified number of bits.
Configuration:
service-url:
user-service: http://localhost:8084
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
# 路由的ID
- id: user-service
# 匹配后路由地址
uri: ${service-url.user-service}
predicates:
# 发送指定路径的请求会匹配该路由。
- Path=/api/user/*
filters:
- StripPrefix=1
Request: http://localhost:8093/api/user/getUserList is
equivalent to: http://localhost:8084 /user/getUserList
2.5.3 filters - PrefixPath
Description: Add the specified path prefix to all GET requests
Configuration:
service-url:
user-service: http://localhost:8084
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
# 路由的ID
- id: user-service
# 匹配后路由地址
uri: ${service-url.user-service}
predicates:
# 发送指定路径的请求会匹配该路由。
- Path=/user/*
filters:
- PrefixPath=/api
Request: http://localhost:8093/user/getUserList is
equivalent to: http://localhost:8084 /api /user/getUserList
2.5.3 filters - hystrix
Description: Hystrix filter allows you to add the circuit breaker function to the gateway routing to protect your services from cascading failures and provide service degradation processing.
pom.xml:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
fr:
service-url:
user-service: http://localhost:8084
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
# 路由的ID
- id: user-service
# 匹配后路由地址
uri: ${service-url.user-service}
predicates:
# 发送指定路径的请求会匹配该路由。
- Path=/api/user/*
filters:
- name: Hystrix
args:
name: fallbackcmd
#转发路径
fallback-uri: forward:/fallback
controller:
package com.zqh.www.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@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;
}
}
Test:
Normal condition: Service exception: (Close user-service service to simulate service disconnection)
2.5.3 filters - RequestRateLimiter
Description: The RequestRateLimiter filter can be used for current limiting. The RateLimiter implementation is used to determine whether the current request is allowed to proceed. If the request is too large, the HTTP 429-status will be returned by default.
pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
fr:
service-url:
user-service: http://localhost:8084
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
# 路由的ID
- id: user-service
# 匹配后路由地址
uri: ${service-url.user-service}
predicates:
# 发送指定路径的请求会匹配该路由。
- Path=/api/user/*
filters:
- name: RequestRateLimiter
args:
# 每秒允许处理的请求数量
redis-rate-limiter.replenishRate: 1
# 每秒最大处理的请求数量
redis-rate-limiter.burstCapacity: 2
# 限流策略,对应策略的Bean
key-resolver: "#{@ipKeyResolver}"
config:
package com.zqh.www.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;
import java.util.Objects;
@Configuration
public class RedisRateLimiterConfig {
// 如果你是采用第二个的策略,那么第一个策略的@Bean记得要注释掉,否则他会报找到2个参数
// @Bean
public KeyResolver userKeyResolver() {
return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest().getQueryParams().getFirst("username")));
}
@Bean
public KeyResolver ipKeyResolver() {
return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getHostName());
}
}
Test:
Normal situation: Abnormal situation: Return 429 in case of quick request
2.5.4 filters - Retry
Description: The filter for retrying routing requests can determine whether to retry based on the HTTP status code returned by the routing request.
yml :
service-url:
user-service: http://localhost:8084
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
# 路由的ID
- id: user-service
# 匹配后路由地址
uri: ${service-url.user-service}
predicates:
# 发送指定路径的请求会匹配该路由。
- Path=/api/user/*
filters:
- name: Retry
args:
#需要进行重试的次数
retries: 1
#返回哪个状态码需要进行重试,返回状态码为5XX进行重试
statuses: BAD_GATEWAY
backoff:
firstBackoff: 10ms
maxBackoff: 50ms
factor: 2
basedOnPreviousValue: false
Test:
Normal: Exception: (adding a null pointer to the service provider), 2 errors will be output, which means 1 retry
3. Microservices use gateway
3.1 pom.xm dependency
<dependencies>
<!-- 配合注册中心使用 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
</dependencies>
3.2 Startup
package com.zqh.www;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.core.env.Environment;
/**
* 开启服务发现客户端
*
* @EnableEurekaClient只适用于Eureka作为注册中心,@EnableDiscoveryClient 可以是其他注册中心。
*/
// 如果你是启动的是alone的配置,请注释@EnableDiscoveryClient,并且注释 pom.xml 里面的 eureka-client 依赖,不然会出现链接错误
@EnableDiscoveryClient
@SpringBootApplication
public class ApiGatewayApplication {
private final static Logger logger = LoggerFactory.getLogger(ApiGatewayApplication.class);
public static void main(String[] args) {
Environment env = SpringApplication.run(ApiGatewayApplication.class, args).getEnvironment();
logger.info(
"\n----------------------------------------------------------\n\t"
+ "Application '{}' is running! Access URLs:\n\t"
+ "Local: \t\thttp://localhost:{}{}"
+ "\n----------------------------------------------------------",
env.getProperty("spring.application.name"), env.getProperty("server.port"),
env.getProperty("server.servlet.context-path") != null ? env.getProperty("server.servlet.context-path") : "");
}
}
3.3 margins
server:
port: 8093
eureka:
client:
service-url:
#注册地址
defaultZone: http://root:root@localhost:8081/eureka/
#显示服务器IP加端口
instance:
hostname: localhost
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${server.port}
spring:
application:
name: api-gateway
cloud:
gateway:
discovery:
locator:
#开启从注册中心动态创建路由的功能
enabled: true
#使用小写服务名
lower-case-service-id: true
routes:
# 路由的ID
- id: user-service
# 在结合注册中心使用过滤器的时候,uri的协议为lb,这样才能启用Gateway的负载均衡功能。
uri: lb://user-service
predicates:
# 发送指定路径的请求会匹配该路由。
- Path=/api/user/*
# # 发送指定方法的请求会匹配该路由。
# - Method=GET
# # 在指定时间之后的请求会匹配该路由。
# - After=2020-10-20T18:00:00+08:00[Asia/Shanghai]
# # 在指定时间之前的请求会匹配该路由。
# - Before=2020-10-20T12:00:00+08:00[Asia/Shanghai]
# # 在指定时间区间内的请求会匹配该路由。
# - Between=2020-10-20T12:00:00+08:00[Asia/Shanghai], 2020-10-30T12:00:00+08:00[Asia/Shanghai]
# # 带有指定Cookie的请求会匹配该路由
# - Cookie=username,z
# # 带有指定请求头的请求会匹配该路由。
# - Header=auth
# #带有指定Host的请求会匹配该路由。
# - Host=www.zqh.com
# # 从指定远程地址发起的请求可以匹配该路由。
# - RemoteAddr=192.168.1.1/24
filters:
- name: Retry
args:
#需要进行重试的次数
retries: 3
#返回哪个状态码需要进行重试,返回状态码为5XX进行重试
statuses: BAD_GATEWAY
backoff:
firstBackoff: 10ms
maxBackoff: 50ms
factor: 2
basedOnPreviousValue: false
# - name: RequestRateLimiter
# args:
# # 每秒允许处理的请求数量
# redis-rate-limiter.replenishRate: 1
# # 每秒最大处理的请求数量
# redis-rate-limiter.burstCapacity: 2
# # 限流策略,对应策略的Bean
# key-resolver: "#{@ipKeyResolver}"
# - name: Hystrix
# args:
# name: fallbackcmd
# #转发路径
# fallback-uri: forward:/fallback
# - AddRequestParameter=username,z
# - StripPrefix=1
# - PrefixPath=/api
logging:
level:
org.springframework.cloud.gateway: debug