Spring 官方最终还是按捺不住推出了自己的网关组件:Spring Cloud Gateway ,相比之前我们使用的 Zuul(1.x) 它有哪些优势呢?Zuul(1.x) 基于 Servlet,使用阻塞 API,它不支持任何长连接,如 WebSockets,Spring Cloud Gateway 使用非阻塞 API,支持 WebSockets,支持限流等新特性。
Spring Cloud Gateway
Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。
Spring Cloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Netflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。
相关概念:
- Route(路由):这是网关的基本构建块。它由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配。
- Predicate(断言):这是一个 Java 8 的 Predicate。输入类型是一个 ServerWebExchange。我们可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。
- Filter(过滤器):这是
org.springframework.cloud.gateway.filter.GatewayFilter
的实例,我们可以使用它修改请求和响应。
工作流程:
客户端向 Spring Cloud Gateway 发出请求。如果 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。 过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。
Spring Cloud Gateway 的特征:
- 基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0
- 动态路由
- Predicates 和 Filters 作用于特定路由
- 集成 Hystrix 断路器
- 集成 Spring Cloud DiscoveryClient
- 易于编写的 Predicates 和 Filters
- 限流
- 路径重写
一、新建spring-cloud-gateway服务工程
1.选中spring-cloud-gate包的支持,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 https://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.3.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>lf.liyouyou</groupId> <artifactId>spring-cloud-gateway</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring-cloud-gateway</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.SR8</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </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> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2.配置yml中路由规则
spring: application: name: gateway-service cloud: gateway: routes: - id: route_configclient # 请求 http://localhost:9005/gateway/hello转发到 http://localhost:9004/hello uri: http://localhost:9004 predicates: - Path=/gateway/* filters: - StripPrefix=1 #前缀, 在当前路径匹配中表示去掉第一个前缀 /gateway server: port: 9005
3.启动项目并测试,发现可以跳转并返回值
二、配置Cookie路由
修改yml配置,新增Cookie路由规则
spring: application: name: gateway-service cloud: gateway: routes: - id: route_configclient # 请求 http://localhost:9005/gateway/hello转发到 http://localhost:9004/hello uri: http://localhost:9004 predicates: - Path=/gateway/* filters: - StripPrefix=1 #前缀, 在当前路径匹配中表示去掉第一个前缀 /gateway - id: cookie_route # 请求 http://localhost:9005/gateway/hello转发到 http://localhost:9004/hello predicates: - Cookie=lf,lf.liyouyou uri: https://home.cnblogs.com/u/flgb/ server: port: 9005
启动,用postman 进行测试,直接访问http://localhost:9005/ 返回404
添加cookie,配置key=value
再次发起请求,注意默认是get请求,返回了页面信息,断言匹配成功
查看请求中的cookie ,对比yml配置
三、自定义Header路由规则
1. 可以参照CookieRoutePredicateFactory自定义路由一个AuthRoutePredicateFactory用来判断header头的路由,其中RoutePredicateFactory是固定后缀
AuthRoutePredicateFactory类代码如下:
package lf.liyouyou.Config; import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.CookieRoutePredicateFactory; import org.springframework.http.HttpHeaders; import org.springframework.stereotype.Component; import org.springframework.validation.annotation.Validated; import org.springframework.web.server.ServerWebExchange; import javax.validation.constraints.NotEmpty; import java.util.Arrays; import java.util.List; import java.util.function.Predicate; @Component public class AuthRoutePredicateFactory extends AbstractRoutePredicateFactory<AuthRoutePredicateFactory.Config> { public static final String NAME_KEY = "name"; public AuthRoutePredicateFactory() { super(Config.class); } @Override public Predicate<ServerWebExchange> apply(Config config) { //自定义断言规则,判断header中是否包含某个值 return (exchange->{ HttpHeaders headers = exchange.getRequest().getHeaders(); List<String> list = headers.get(config.getName()); return list.size()>0; }); } @Override public List<String> shortcutFieldOrder() { //自定义属性顺序,配置的断言时进行顺序匹配, // 这里就定义一个属性值,则第一个值就是config.name的值 return Arrays.asList(NAME_KEY); } @Validated public static class Config { @NotEmpty private String name; public void setName(String name) { this.name = name; } public Config() { } public String getName() { return this.name; } } }
2. 配置application.yml路由策略
spring: application: name: gateway-service cloud: gateway: routes: - id: route_configclient # 请求 http://localhost:9005/gateway/hello转发到 http://localhost:9004/hello uri: http://localhost:9004 predicates: - Path=/gateway/* filters: - StripPrefix=1 #前缀, 在当前路径匹配中表示去掉第一个前缀 /gateway - id: cookie_route # 请求 http://localhost:9005/gateway/hello转发到 http://localhost:9004/hello predicates: - Cookie=lf,lf.liyouyou uri: https://home.cnblogs.com/u/flgb/ - id: header_route predicates: - Path=/header/** - Auth=Authorization uri: https://home.cnblogs.com/u/flgb/ filters: - StripPrefix=1 #前缀, 在当前路径匹配中表示去掉第一个前缀 /header server: port: 9005
3. 启动工程,可以看到控制台输出:
证明路由配置生效
4. postman测试
直接访问
配置上header参数值,再访问
四、自定义RouteFilter
Configuration类
package lf.liyouyou.Config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; import javax.validation.constraints.NotEmpty; import java.util.Arrays; import java.util.List; //order过滤器优先级 @Component public class LFGatewayFilterFactory extends AbstractGatewayFilterFactory<LFGatewayFilterFactory.LFConfig> { public static final String NAME_KEY = "name"; Logger logger = LoggerFactory.getLogger(LFGatewayFilterFactory.class); public LFGatewayFilterFactory() { super(LFConfig.class); } @Override public List<String> shortcutFieldOrder() { return Arrays.asList(NAME_KEY); } @Override public GatewayFilter apply(LFConfig config) { //Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain); //Fiter pre/post return ((exchange,chain)->{ //TODO logger.info("pre fiter request,name: {}",config.getName()); return chain.filter(exchange).then( Mono.fromRunnable(()->{ //TODO logger.info("post :response filter!"); }) ); }); } public static class LFConfig { @NotEmpty private String name; public void setName(String name) { this.name = name; } public LFConfig() { } public String getName() { return this.name; } } }
yml配置filter,新增标黄地方
spring: application: name: gateway-service cloud: gateway: routes: - id: route_configclient1 #u8BF7u6C42 http://localhost:9005/gateway/hellolfu4F1Au8F6Cu53D1u5230http://localhost:9003/hello uri: http://localhost:9003 #u5728u670Du52A1u6CE8u518Cu4E2Du5FC3u627Eu670Du52A1u540Du4E3A data-produceru7684u670Du52A1 predicates: - Path=/gateway/** #u8BBEu7F6Eu8DEFu7531u65ADu8A00,u4EE3u7406servicerIdu4E3Adata-service1u7684/ data-service1 /u8DEFu5F84 filters: - StripPrefix=1 - LF= hello lf
重新启动,访问http://localhost:9005/gateway/hello,查看控制台日志,发现已经生效
五、GlobalFIlter实现负载均衡
1、spring-cloud-gateway添加注册中心的依赖
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 https://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.3.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>lf.liyouyou</groupId> <artifactId>spring-cloud-gateway</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring-cloud-gateway</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.SR8</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </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> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2.yml新增标黄配置,开启注册中心支持,配置负载均衡路由
spring: application: name: gateway-service cloud: gateway: discovery: locator: enabled: true lower-case-service-id: true routes: - id: route_configclient1 #u8BF7u6C42 http://localhost:9005/gateway/hellolfu4F1Au8F6Cu53D1u5230http://localhost:9003/hello uri: http://localhost:9003 #u5728u670Du52A1u6CE8u518Cu4E2Du5FC3u627Eu670Du52A1u540Du4E3A data-produceru7684u670Du52A1 predicates: - Path=/gateway/** #u8BBEu7F6Eu8DEFu7531u65ADu8A00,u4EE3u7406servicerIdu4E3Adata-service1u7684/ data-service1 /u8DEFu5F84 filters: - StripPrefix=1 - LF= hello lf - id: route_configclient # u8BF7u6C42 http://localhost:9005/gateway/hellou8F6Cu53D1u5230 http://localhost:9004/hello uri: http://localhost:9004 predicates: - Path=/gateway/* filters: - StripPrefix=1 #u524Du7F00uFF0C u5728u5F53u524Du8DEFu5F84u5339u914Du4E2Du8868u793Au53BBu6389u7B2Cu4E00u4E2Au524Du7F00 /gateway - id: cookie_route # u8BF7u6C42 http://localhost:9005/gateway/hellou8F6Cu53D1u5230 http://localhost:9004/hello predicates: - Cookie=lf,lf.liyouyou uri: https://home.cnblogs.com/u/flgb/ - id: header_route predicates: - Path=/header/** - Auth=Authorization uri: https://home.cnblogs.com/u/flgb/ filters: - StripPrefix=1 #u524Du7F00uFF0C u5728u5F53u524Du8DEFu5F84u5339u914Du4E2Du8868u793Au53BBu6389u7B2Cu4E00u4E2Au524Du7F00 /header - id: lb_route predicates: - Path=/lb/** filters: - StripPrefix=1 uri: lb://spring-cloud-config-client eureka: client: service-url: defaultZone: http://localhost:8000/eureka/ server: port: 9005
3、取消spring-cloud-config-client服务只能启动单个实例的限制
4、修改/hellolf返回值
package lf.liyouyou.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @RequestMapping("/hellolf") public String Hellolf(){ return "hello lf 9999"; } }
5、修改端口为9999,再次启动,看到注册中心上有两个spring-cloud-config-client服务
6、测试结果如下
六、基于redis限流器的实现
1、新增依赖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 https://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.3.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>lf.liyouyou</groupId> <artifactId>spring-cloud-gateway</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring-cloud-gateway</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.SR8</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis-reactive</artifactId> <version>2.0.5.RELEASE</version> </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> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2.新增keyResolver代码
package lf.liyouyou.Config; import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; @Component public class IpAddressKeyResolver implements KeyResolver { @Override public Mono<String> resolve(ServerWebExchange exchange) { return Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()); } }
3、新增yml配置
spring: application: name: gateway-service redis: host: 192.168.31.151 port: 6379 password: cloud: gateway: discovery: locator: enabled: true lower-case-service-id: true routes: - id: route_configclient1 #u8BF7u6C42 http://localhost:9005/gateway/hellolfu4F1Au8F6Cu53D1u5230http://localhost:9003/hello uri: http://localhost:9003 #u5728u670Du52A1u6CE8u518Cu4E2Du5FC3u627Eu670Du52A1u540Du4E3A data-produceru7684u670Du52A1 predicates: - Path=/gateway/** #u8BBEu7F6Eu8DEFu7531u65ADu8A00,u4EE3u7406servicerIdu4E3Adata-service1u7684/ data-service1 /u8DEFu5F84 filters: - StripPrefix=1 - LF= hello lf - id: route_configclient # u8BF7u6C42 http://localhost:9005/gateway/hellou8F6Cu53D1u5230 http://localhost:9004/hello uri: http://localhost:9004 predicates: - Path=/gateway/* filters: - StripPrefix=1 #u524Du7F00uFF0C u5728u5F53u524Du8DEFu5F84u5339u914Du4E2Du8868u793Au53BBu6389u7B2Cu4E00u4E2Au524Du7F00 /gateway - id: cookie_route # u8BF7u6C42 http://localhost:9005/gateway/hellou8F6Cu53D1u5230 http://localhost:9004/hello predicates: - Cookie=lf,lf.liyouyou uri: https://home.cnblogs.com/u/flgb/ - id: header_route predicates: - Path=/header/** - Auth=Authorization uri: https://home.cnblogs.com/u/flgb/ filters: - StripPrefix=1 #u524Du7F00uFF0C u5728u5F53u524Du8DEFu5F84u5339u914Du4E2Du8868u793Au53BBu6389u7B2Cu4E00u4E2Au524Du7F00 /header - id: lb_route predicates: - Path=/lb/** filters: - StripPrefix=1 uri: lb://spring-cloud-config-client - id: ratelimiter_route predicates: - Path=/ratelimiter/** filters: - StripPrefix=1 - name: RequestRateLimiter args: deny-empty-key: true key-resolver: "#{@ipAddressKeyResolver}" #默认类名称首字母小写 redis-rate-limite r.replenishRate: 1 redis-rate-limiter.burstCapacity: 2 uri: lb://spring-cloud-config-client eureka: client: service-url: defaultZone: http://localhost:8000/eureka/ server: port: 9005
4.重新启动spring-cloud-gateway测试,重复刷新 http://localhost:9005/ratelimiter/hellolf,出现:429代表被限流
六、GateWay动态路由的实现
gateway官网
https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/#creating-and-deleting-a-particular-route 官网预留了actuator接口,
可以动态创建、删除路由、路由刷新机制,不过默认是存放在内存中的,重启服务后新创建的、删除的都会消失。将其改造存储在redis中支持gateway的动态路由
可以参考docker篇安装redis镜像。https://i.cnblogs.com/posts?cateId=1625602
1.spring-cloud-gateway导入包,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 https://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.3.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>lf.liyouyou</groupId> <artifactId>spring-cloud-gateway</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring-cloud-gateway</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.SR8</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <!--<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis-reactive</artifactId> <version>2.0.5.RELEASE</version> </dependency>--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.72</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</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> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
编写自定义存储类:
package lf.liyouyou.Config; import com.alibaba.fastjson.JSON; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.gateway.route.RouteDefinition; import org.springframework.cloud.gateway.route.RouteDefinitionRepository; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.util.ArrayList; import java.util.HashMap; @Component public class RedisRouteDefinitionRepository implements RouteDefinitionRepository { public static final String GATEWAY_ROUTE_KEY = "gateway_route_key"; @Autowired RedisTemplate redisTemplate; @Override public Flux<RouteDefinition> getRouteDefinitions() { ArrayList<RouteDefinition> routeDefinitions = new ArrayList<>(); redisTemplate.opsForHash().values(GATEWAY_ROUTE_KEY).stream() .forEach(route->{ routeDefinitions.add(JSON.parseObject(route.toString(),RouteDefinition.class)); }); return Flux.fromIterable(routeDefinitions); } @Override public Mono<Void> save(Mono<RouteDefinition> route) { return route.flatMap(routeDefinition -> { redisTemplate.opsForHash().put(GATEWAY_ROUTE_KEY,routeDefinition.getId(), JSON.toJSONString(routeDefinition)); return Mono.empty(); }); } @Override public Mono<Void> delete(Mono<String> routeId) { return routeId.flatMap(id->{ if(redisTemplate.opsForHash().hasKey(GATEWAY_ROUTE_KEY,id)){ redisTemplate.opsForHash().delete(GATEWAY_ROUTE_KEY,id); return Mono.empty(); } return Mono.defer(()->Mono.error(new RuntimeException("not found the RouteDefinition Exception!"))); }); } }
yml添加redis和actuator配置
spring: application: name: gateway-service redis: host: 192.168.31.151 port: 6379 password: management: endpoints: web: exposure: include: "*"
启动:post测试,官网资料添加路由截图如下:
postman测试返回,1成功
报文如下:
"filters": [{ "args":{ "_genkey_0":1 }, "name": "StripPrefix" }], "uri": "https://www.baidu.com", "order": 0 }
访问http://localhost:9005/actuator/gateway/routes 查看最新路由信息(基于事件机制刷新),也可以调用(http://localhost:9005/actuator/gateway/routes/refresh)进行刷新,查询baidu_route发现已存在,访问http://localhost:9005/baidu 发现已经可以跳转到百度
查看redis保存路由的信息:
docker exec -it 启动的redis容器名称 redis-cli 进入redis client端
可以看到redis中已经保存了gateway_route_key的相关信息。
我们重新启动spring-cloud-gateway,再次访问http://localhost:9005/baidu 发现还是跳转到了百度。证明动态路由永久生效。