SpringCloud06_Gateway的概述工程案例代码微服务动态路由Predicate的使用详解Filter(建议收藏)

Posted 所得皆惊喜

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud06_Gateway的概述工程案例代码微服务动态路由Predicate的使用详解Filter(建议收藏)相关的知识,希望对你有一定的参考价值。

①. gateway的概述

  • ①. SpringCloud Gateway是SpringCloud的一个全新项目,基于spring5.0 + spring boot2.0+Project Reactor等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的API路由管理方式

  • ②. SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty

  • ③. SpringCloud Gateway的目标提供统一的路由方式且基于Filter键的方式提供了网关基本的功能,例如:安全 | 监控 | 指标和限流(动态路由、认证授权、令牌限流)

在这里插入图片描述在这里插入图片描述

②. 路由、断言、过滤器

  • ①. 路由(route) 路由信息的组成:由一个ID、一个目的URL、一组断言工厂、一组Filter组成。如果路由断言为真,说明请求URL和配置路由匹配

  • ②. 断言(Predicate) 参考的是java8的java.util.function.Predicate开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由

  • ③. 过滤器(Filter) 一个标准的Spring WebFilter。 Spring Cloud Gateway中的Filter分为两种类型的Filter,分别是Gateway Filter和Global Filter。过滤器Filter将会对请求和响应进行修改处理
    在这里插入图片描述

③. 新建module9527 yml的配置方式

  • ①. cloud-gateway-gateway9527

  • ②. pom
    注意:要移除web和boot防止报错

   <dependencies>
        <!--新增gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <!--
        移除这两个
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>-->
        <!--   <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</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-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>
  • ③. 主启动类
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient
public class GateWayMain9527 {
    public static void main(String[] args) {
        SpringApplication.run(GateWayMain9527.class, args);
    }
}
  • ④. yml配置(重点)
server:
  port: 9527
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001   #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**   #断言,路径相匹配的进行路由

        - id: payment_routh2
          uri: http://localhost:8001
          predicates:
            - Path=/payment/lb/**   #断言,路径相匹配的进行路由
eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

在这里插入图片描述在这里插入图片描述

④. 硬编码 注入RouteLocator的Bean

  • ①. 当我们访问http://localhost:9527/guonei 会跳转到http://news.baidu.com/guonei(了解)
@Configuration
public class GateWayConfig {
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        /*
        id相当于yml中配置的唯一标识
        当你访问http://localhost:9527/guonei
       就会跳转到http://news.baidu.com/guonei
         */
        routes.route("path_rote_xiaozhi",
                r -> r.path("/guonei")
                        .uri("http://news.baidu.com/guonei")).build();
        return routes.build();
    }
    @Bean
    public RouteLocator customRouteLocator2(RouteLocatorBuilder builder) {
        RouteLocatorBuilder.Builder routes = builder.routes();
        routes.route("path_route_xiaozhi2", r -> r.path("/guoji").uri("http://news.baidu.com/guoji")).build();
        return routes.build();
    }
}

在这里插入图片描述

⑤. 通过微服务名实现动态路由

  • ①. 默认情况下Gateway会根据注册中心注册的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能

  • ②. 一个eureka7001 + 两个服务提供者8001/8002
    在这里插入图片描述

  • ③. YML 掌握

  1. 需要注意的是uri的协议为lb,表示启用Gateway的负载均衡功能
  2. lb://serviceName是spring cloud gateway在微服务中自动为我们创建的负载均衡uri
server:
  port: 9527
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:
        - id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001   #匹配后提供服务的路由地址
          uri: lb://CLOUD-PAYMENT-SERVICE   #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**   #断言,路径相匹配的进行路由

        - id: payment_routh2
          #uri: http://localhost:8001
          uri: lb://CLOUD-PAYMENT-SERVICE   #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/lb/**   #断言,路径相匹配的进行路由
eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka
  • ④. 测试:http://localhost:9527/payment/lb (8001/8002两个端口切换)
    在这里插入图片描述

⑥. Predicate的使用

①. Predicate的概述

  • ①. Predicate就是为了实现一组匹配规则,让请求过来找到对应的Route进行处理

  • ②. Predicate的介绍(启动我们的gatewat9527)
    在这里插入图片描述

  • ③. Route Predicate Factories这个是什么东东?
    在这里插入图片描述

  • ③. 常用的Route Predicate
    下面代码非常重要,需要重点掌握

//常用的时间串串
public class ZonedDateTimeDemo {
    public static void main(String[] args) {
        ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区
        System.out.println(zbj);//2021-07-16T19:39:36.874+08:00[Asia/Shanghai]
        ZonedDateTime zny = ZonedDateTime.now(ZoneId.of("America/New_York")); // 用指定时区获取当前时间
        //2021-07-16T07:39:36.876-04:00[America/New_York]
        System.out.println(zny);
    }
}

②. 常用的Route Predicate

  • ①. After Route Predicate
//常用的时间串串
public class ZonedDateTimeDemo {
    public static void main(String[] args) {
        ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区
        System.out.println(zbj);//2021-07-16T19:39:36.874+08:00[Asia/Shanghai]
        ZonedDateTime zny = ZonedDateTime.now(ZoneId.of("America/New_York")); // 用指定时区获取当前时间
        //2021-07-16T07:39:36.876-04:00[America/New_York]
        System.out.println(zny);
    }
}
spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能
      routes:
        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          # uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
           # 断言,路径相匹配的进行路由
	       - Path=/payment/lb/**        
	       # 断言,路径相匹配的进行路由
	       - After=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         
  • ②. Before Route Predicate
    在这里插入图片描述
    在这里插入图片描述
  • ③. Between Route Predicate
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          # uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由

        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          # uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/lb/**         # 断言,路径相匹配的进行路由
            #- After=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,路径相匹配的进行路由
            #- Before=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,路径相匹配的进行路由
            - Between=2020-02-02T17:45:06.206+08:00[Asia/Shanghai],2020-03-25T18:59:06.206+08:00[Asia/Shanghai]
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:
        - id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001   #匹配后提供服务的路由地址
          uri: lb://CLOUD-PAYMENT-SERVICE   #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**   #断言,路径相匹配的进行路由
            - After=2021-07-28T10:59:34.102+08:00[Asia/Shanghai]
        - id: payment_routh2
          #uri: http://localhost:8001
          uri: lb://CLOUD-PAYMENT-SERVICE   #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/lb/**   #断言,路径相匹配的进行路由
            #- Before=2021-07-28T10:59:34.102+08:00[Asia/Shanghai]
            #- Cookie=username, TANGZHI
            - Header=X-Request-Id, \\d+ # 请求头要有X-Request-Id属性并且值为整数的正则表达式

在这里插入图片描述

  • ⑥. Host Route Predicate
    正确:curl http://localhost:9527/payment/lb -H “Host: www.tangzhi.com”
    正确:curl http://localhost:9527/payment/lb -H “Host: java.tangzhi2.com”
    错误:curl http://localhost:9527/payment/lb -H “Host: java.tangzhi2.net”
 - Host=**.tangzhi.com,**.tangzhi2.com

在这里插入图片描述在这里插入图片描述

  • ⑦. Method Route Predicate
- Method=GET

在这里插入图片描述在这里插入图片描述

  • ⑧. Path Route Predicate
# 断言,路径相匹配的进行路由
- Path=/payment/lb/**         

在这里插入图片描述

  • ⑨. Query Route Predicate
- Query=username, \\d+  # 要有参数名username并且值还要是整数才能路由

在这里插入图片描述

  • ⑩. All code如下:
spring
	cloud:
	  gateway:
	    discovery:
	      locator:
	        enabled: true  #开启从注册中心动态创建路由的功能,利用微服务名进行路由
	    routes:
	      - id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
	        #uri: http://localhost:8001   #匹配后提供服务的路由地址
	        uri: lb://cloud-payment-service
	        predicates:
	          - Path=/payment/get/**   #断言,路径相匹配的进行路由
	
	      - id: payment_routh2
	        #uri: http://localhost:8001   #匹配后提供服务的路由地址
	        uri: lb://cloud-payment-service
	        predicates:
	          - Path=/payment/lb/**   #断言,路径相匹配的进行路由
	          #- After=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
	          #- Cookie=username,zhangshuai #并且Cookie是username=zhangshuai才能访问
	          #- Header=X-Request-Id, \\d+ #请求头中要有X-Request-Id属性并且值为整数的正则表达式
	          #- Host=**.tangzhi.com
	          #- Method=GET
	          #- Query=username, \\d+ #要有参数名称并且是正整数才能路由

⑦. Filter的使用

①. Filter的概述

  • ①. 路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用

  • ②. Spring Cloud Gateway 内置了多种路由过滤器,他们都由GatewayFilter的工厂类来产生

②. Spring Cloud Gateway的Filter

  • ①. 生命周期,Only Two(pre、post)

  • ②. 种类,Only Two(GatewayFilter、GlobalFilter)

在这里插入图片描述
在这里插入图片描述

③. 自定义过滤器(自定义全局GlobalFilter)

  • ①. 在com.atguigu.springcloud.filter创建MyLogGateWayFilter类
@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter,Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        log.info("*********come in MyLogGateWayFilter: "+new Date());
        String uname = exchange.getRequest().getQueryParams().getFirst("username");
        if(StringUtils.isEmpty(username)){
            log.info("*****用户名为Null 非法用户,(┬_┬)");
            //设置响应状态码为未授权
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);//给人家一个回应
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange以上是关于SpringCloud06_Gateway的概述工程案例代码微服务动态路由Predicate的使用详解Filter(建议收藏)的主要内容,如果未能解决你的问题,请参考以下文章

SpringCloud --- 服务网关 (Gateway)

十一SpringCloud实用篇_Gateway服务网关

十一SpringCloud实用篇_Gateway服务网关

SpringCloud - Spring Cloud Alibaba 之 Gateway 集成Sentinel

SpringCloud 网关 Gateway

SpringCloud-2.0-周阳:(12. 服务网关 - Gateway)