Springcloud Gateway:动态配置,过滤器源码思路(1)

简介: Springcloud Gateway:动态配置,过滤器源码思路(1)

微服务网关服务

认识 gateway 微服务网关组件


Spring Cloud GateWay 是 spring 官方推出的一款 基于 springframework5,Project Reactor和 spring boot2 之上开发的网关,其性能,高吞吐量,将代替zuul称为新一代的网关,用于给微服务提供 统一的api管理方式


与第一代的区别


和第一代网关zuul 相比 不同的事 gateway 是异步非阻塞的 (netty+webflux实现); zuul是同步阻塞请求的,性能上有这很大的差异


Gateway 组成部分

2.png



工作模型

3.png


请求发送到网关,由分发器将请求匹配到响应的 handlerMapping(这里的handlermapping不是MVC的那个,可以理解为匹配url的网关处理器)

请求和处理器之间有一个映射,路由到网关处理程序, web Handler他最用是把请求放入过滤器链路中,

执行特定的请求和过滤器链路,(我们自定义的)依次执行过滤器

最终到达代理微服务

思考


可以看到我们这个模型图 都是双向剪头的 那么找到了对应的 服务 返回的结果是如何回来的呢?


首先网关有相关的代理服务,然后把请求交给对应的代理服务处理,处理完后,将结果返回到Gateway客户端。


这里 filter 可以看到时 用虚线隔开的


pre filter : 请求必须要执行完pre filter并且执行完毕之后才会到对应的代理服务中处理,


post filter :对应的代理服务执行完处理完之后,才会执行 psot filter中的过滤器


模块搭建 三部曲


我们创建 gateway服务项目

    <dependencies>
        <!-- spring cloud alibaba nacos discovery 依赖 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!-- zipkin = spring-cloud-starter-sleuth + spring-cloud-sleuth-zipkin-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.kafka</groupId>
            <artifactId>spring-kafka</artifactId>
            <version>2.5.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.hyc.ecommerce</groupId>
            <artifactId>e-commerce-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

编写配置

server:
  port: 9001
  servlet:
    context-path: /imooc
spring:
  application:
    name: e-commerce-gateway
  cloud:
    nacos:
      discovery:
        enabled: true # 如果不想使用 Nacos 进行服务注册和发现, 设置为 false 即可
        server-addr: 127.0.0.1:8848 # Nacos 服务器地址
        namespace: 1bc13fd5-843b-4ac0-aa55-695c25bc0ac6
        metadata:
          management:
            context-path: ${server.servlet.context-path}/actuator
    # 静态路由
  #    gateway:
  #      routes:
  #        - id: path_route # 路由的ID
  #          uri: 127.0.0.1:8080/user/{id} # 匹配后路由地址
  #          predicates: # 断言, 路径相匹配的进行路由
  #            - Path=/user/{id}
  kafka:
    bootstrap-servers: 127.0.0.1:9092
    producer:
      retries: 3
    consumer:
      auto-offset-reset: latest
  zipkin:
    sender:
      type: kafka # 默认是 web
    base-url: http://localhost:9411/
  main:
    allow-bean-definition-overriding: true  # 因为将来会引入很多依赖, 难免有重名的 bean
# 这个地方独立配置, 是网关的数据, 代码 GatewayConfig.java 中读取被监听
nacos:
  gateway:
    route:
      config:
        data-id: e-commerce-gateway-router
        group: e-commerce
# 暴露端点
management:
  endpoints:
    web:
      exposure:
        include: '*'
  endpoint:
    health:
      show-details: always

谓词 Predicate 的原理与应用

想要 理解gateway 的Predicate ,首先我们要 理解 java 8 中的Predicate

我们先去看看 java8 的predicate吧

java8 predicate

由 java 8 引入位于 package java.util.function;包中 是一个 函数式接口

@FunctionalInterface  // 是一个函数式接口

public interface Predicate<T>  


2.png


来看这个 test 方法

需要输入一个的参数 返回 boolean 类型 通常用于 stream的filter 中 表示是否满足过滤条件

可能到这里,都是比较懵的。上手编写 java8 predicate 的效果

理解一下

Java 8 Predicate 常用的一些方法 执行测试看到效果就会 理解很多,这里提供 Test code

/**
 * @author : 冷环渊
 * @date : 2021/12/6
 * @context: java8 predicate 使用方法与思想
 * @params :  null
 * @return :  * @return : null
 */
@SpringBootTest
@Slf4j
@RunWith(SpringRunner.class)
public class PredicateTest {
    public static List<String> MICRO_SERVER = Arrays.asList(
            "nacos", "authority", "gateway", "ribbon", "feign", "Hystrix", "e-comerce"
    );
    /*
     * test 方法主要是 用于参数符不符合规则 返回值事 boolean
     * */
    @Test
    public void testPredicateTest() {
        Predicate<String> letterlengthLimit = s -> s.length() > 5;
        MICRO_SERVER.stream().filter(letterlengthLimit).forEach(System.out::println);
    }
    /*
     * and 方法  等同于 我们的逻辑 与 && 存在短路 特性 不符合就全部返回 false 需要所有条件都满足
     * */
    @Test
    public void testPredicateAnd() {
        Predicate<String> letterlengthLimit = s -> s.length() > 5;
        Predicate<String> letterStartWith = s -> s.startsWith("gate");
        MICRO_SERVER.stream().filter(
                letterlengthLimit.and(letterStartWith)
        ).forEach(System.out::println);
    }
    /*
     *  Or 等同于 逻辑 或 ||  只要满足 其中一个条件 就可以通过过滤
     * */
    @Test
    public void testPredicateOr() {
        Predicate<String> letterlengthLimit = s -> s.length() > 5;
        Predicate<String> letterStartWith = s -> s.startsWith("gate");
        MICRO_SERVER.stream().filter(
                letterlengthLimit.or(letterStartWith)
        ).forEach(System.out::println);
    }
    /*
     * 等同于 逻辑 非 !
     * */
    @Test
    public void testPredicateNegate() {
        Predicate<String> letterStartWith = s -> s.startsWith("gate");
        MICRO_SERVER.stream().filter(
                letterStartWith.negate()
        ).forEach(System.out::println);
    }
    /*
     * is Equal 类似于 Eqeual() 区别在于 先判断对象是否为 null
     * 部位 null 在使用 equals 来比较
     * */
    @Test
    public void testPredicateIsEqual() {
        Predicate<String> equalGateway = s -> Predicate.isEqual("gateway").test(s);
        MICRO_SERVER.stream().filter(
                equalGateway
        ).forEach(System.out::println);
    }
}

简单了解了一下,Predicate 这里我们去查看一下,gateway的 路径匹配路由工厂PathRoutePredicateFactory


从名字我们可以看出,这个工厂是负责 路径匹配的


看到 apply方法


他其实就是集成了 java8 的predicate


这里我们看到返回的GatewayPredicate,这里其实就是对请求的url


首先这个方法先获得了 path方法获取到当前请求的路径信息

之后和我们的配置进行一个匹配(正则表达式)返回匹配,否则就在去寻找

Tips:


这里我们首先要理解 Predicate 的几个方法

之后去分析一个 Gateway 的一个 Predicate 实现 查看一下 Gateway是如何实现的

  @Override                        //这里config 其实就是我们的路由配置
  public Predicate<ServerWebExchange> apply(Config config) {
    final ArrayList<PathPattern> pathPatterns = new ArrayList<>();
    synchronized (this.pathPatternParser) {
      pathPatternParser.setMatchOptionalTrailingSeparator(
          config.isMatchOptionalTrailingSeparator());
      config.getPatterns().forEach(pattern -> {
        PathPattern pathPattern = this.pathPatternParser.parse(pattern);
        pathPatterns.add(pathPattern);
      });
    }
    return new GatewayPredicate() {
      @Override
      public boolean test(ServerWebExchange exchange) {
        PathContainer path = parsePath(
            exchange.getRequest().getURI().getRawPath());
        Optional<PathPattern> optionalPathPattern = pathPatterns.stream()
            .filter(pattern -> pattern.matches(path)).findFirst();
        if (optionalPathPattern.isPresent()) {
          PathPattern pathPattern = optionalPathPattern.get();
          traceMatch("Pattern", pathPattern.getPatternString(), path, true);
          PathMatchInfo pathMatchInfo = pathPattern.matchAndExtract(path);
          putUriTemplateVariables(exchange, pathMatchInfo.getUriVariables());
          return true;
        }
        else {
          traceMatch("Pattern", config.getPatterns(), path, false);
          return false;
        }
      }
      @Override
      public String toString() {
        return String.format("Paths: %s, match trailing slash: %b",
            config.getPatterns(), config.isMatchOptionalTrailingSeparator());
      }
    };
  }

alibaba nacos 实现动态路由配置


这里其实动态静态的配置,就是是否放到nacos上的区别


静态路由 配置写在配置文件中 (yml 或者 proprieties文件中),端点,是 spring.cloud,gateway,缺点是每次更改都系要网关重新部署

动态其实就是,从nacos上获取到配置,我们需要创建配置在nacos web端,之后相关服务启动的时候,我们需要配置 config 定义要去哪里获取到配置,我们在gateway解析配置,监听变化,如果有变化就刷新配置就好了


相关文章
|
5天前
|
算法 NoSQL API
SpringCloud&Gateway网关限流
SpringCloud&Gateway网关限流
42 7
|
5天前
|
Java 应用服务中间件 Nacos
Spring Cloud 常用各个组件详解及实现原理(附加源码+实现逻辑图)
Spring Cloud 常用各个组件详解及实现原理(附加源码+实现逻辑图)
39 0
|
5天前
|
负载均衡 Java 网络安全
gateway基本配置
gateway基本配置
1315 4
|
5天前
|
架构师 Java API
Gateway基本配置
Gateway基本配置
19 0
|
5天前
|
安全 Java API
gateway基本配置
【5月更文挑战第7天】API Gateway在微服务架构中起着关键作用,作为客户端与后端服务的统一入口,负责路由转发、安全控制和负载均衡。本文深入介绍了API Gateway的基本配置、常见问题、跨平台配置差异及避免错误的方法。内容包括路由和过滤器配置、动态路由、安全性配置、限流和熔断机制,以及自定义过滤器和服务降级策略。通过示例代码和实践指南,帮助读者理解和部署API Gateway。
38 3
|
5天前
|
负载均衡 监控 Java
新手入门gateway基本配置详解与深入分析
欢迎关注 `威哥爱编程` 一起交流学习,人生海海,相遇就是缘分,让我们以技术为信物,成为相互惦记的人。
|
5天前
|
Java 微服务 Spring
SpringCloud&Gateway全局过滤器
SpringCloud&Gateway全局过滤器
11 1
|
5天前
|
监控 Java API
第七章 Spring Cloud 之 GateWay
第七章 Spring Cloud 之 GateWay
23 0
|
5天前
|
Java Maven Nacos
Spring Cloud Eureka 服务注册和服务发现超详细(附加--源码实现案例--及实现逻辑图)
Spring Cloud Eureka 服务注册和服务发现超详细(附加--源码实现案例--及实现逻辑图)
32 0
|
5天前
|
人工智能 监控 安全
Java+Spring Cloud +Vue+UniApp微服务智慧工地云平台源码
视频监控系统、人员实名制与分账制管理系统、车辆管理系统、环境监测系统、大型设备监测(龙门吊、塔吊、升降机、卸料平台等)、用电监测系统、基坑监测系统、AI算法分析(安全帽佩戴、火焰识别、周界报警、人员聚众报警、升降机超载报警)、安全培训、设备监测。
31 4