Spring Cloud Gateway服务网关

一、简介

1. 概述

Spring Cloud Gateway 是 Spring 官方基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,Spring Cloud Gateway 旨在为微服务架构提供一种简单而有效的统一的 API 路由管理方式。Spring Cloud Gateway 作为 Spring Cloud 生态系中的网关,目标是替代 Netflix ZUUL,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/埋点,和限流等。
Spring Cloud Gateway服务网关_第1张图片

2. Spring Cloud Gateway 功能特征

  • 基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0
  • 动态路由
  • Predicates 和 Filters 作用于特定路由
  • 集成 Hystrix 断路器
  • 集成 Spring Cloud DiscoveryClient
  • 易于编写的 Predicates 和 Filters
  • 限流
  • 路径重写

3. Spring Cloud Gateway 工程流程

Spring Cloud Gateway服务网关_第2张图片

客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。

过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(pre)或之后(post)执行业务逻辑。
Spring Cloud Gateway服务网关_第3张图片


二、搭建Spring Cloud Gateway微服务

1. pom.xml


<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">
    <modelVersion>4.0.0modelVersion>

    <parent>
        <groupId>com.banmingi.nodeappgroupId>
        <artifactId>parentartifactId>
        <version>0.0.1-SNAPSHOTversion>
    parent>

    <artifactId>gatewayartifactId>
    <packaging>jarpackaging>
    <inceptionYear>2019-NowinceptionYear>

    <dependencies>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-actuatorartifactId>
        dependency>

        
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <scope>providedscope>
        dependency>

        
        
        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-gatewayartifactId>
        dependency>
        <dependency>
            <groupId>javax.servletgroupId>
            <artifactId>javax.servlet-apiartifactId>
        dependency>


    dependencies>

    <licenses>
        <license>
            <name>Apache 2.0name>
            <url>https://www.apache.org/licenses/LICENSE-2.0.txturl>
        license>
    licenses>

    <developers>
        <developer>
            <id>374564448id>
            <name>banminginame>
            <email>[email protected]email>
        developer>
    developers>

    <build>
        <plugins>
            
            <plugin>
                <groupId>org.mybatis.generatorgroupId>
                <artifactId>mybatis-generator-maven-pluginartifactId>
                <version>1.3.6version>
                <configuration>
                    <configurationFile>
                        ${basedir}/src/main/resources/generator/generatorConfig.xml
                    configurationFile>
                    <overwrite>trueoverwrite>
                    <verbose>trueverbose>
                configuration>
                <dependencies>
                    <dependency>
                        <groupId>mysqlgroupId>
                        <artifactId>mysql-connector-javaartifactId>
                        <version>8.0.17version>
                    dependency>
                    <dependency>
                        <groupId>tk.mybatisgroupId>
                        <artifactId>mapperartifactId>
                        <version>4.1.5version>
                    dependency>

                dependencies>
            plugin>

            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
                <configuration>
                    <mainClass>
                        com.banmingi.nodeapp.gateway.GatewayApplication
                    mainClass>
                configuration>
            plugin>
        plugins>
    build>

project>

特别注意:

  • Spring Cloud Gateway 不使用 Web 作为服务器,而是 使用 WebFlux 作为服务器,Gateway 项目已经依赖了 starter-webflux,所以这里 千万不要依赖 starter-web
  • 由于过滤器等功能依然需要 Servlet 支持,故这里还需要依赖 javax.servlet:javax.servlet-api

2. 配置文件

server:
  port: 9000

spring:
  main:
    allow-bean-definition-overriding: true
  application:
    name: gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

    gateway:
      discovery:
        locator:
          #让gateway从服务发现组件上面找到其他微服务并自动代理
          enabled: true

# 暴露所有 actuator 端点
management:
  endpoints:
    jmx:
      exposure:
        include: '*'
# 健康检查展示详情
  endpoint:
    health:
      show-details: always

3. 转发定律

在这里插入图片描述

4. 核心概念

  • **Route(路由):**Spring Cloud Gateway的元素基础,可简单理解成一条转发的规则。包含ID、目标URL、Predicate集合以及Filter集合。

  • **Predicate(谓词):**即java.util.Predicate,Spring Cloud Gateway使用Predicate实现路由的匹配条件。

  • **Filter(过滤器):**修改请求及响应。

路由匹配示例:

spring:
  cloud:
    gateway:
      discovery:
        locator:
          #让gateway从服务发现组件上面找到其他微服务
          enabled: true
      routes:
        - id: between_router
          uri: lb://user-center
          predicates:
            - Path=/users/1
          filters:
            - AddRequestHeader=X-Request-Foo,Bar

三、Spring Cloud Gateway路由谓词工厂详解

1. 内置路由工厂

官方提供的路由谓词工厂详解

2. 自定义谓词路由工厂

Spring Cloud Gateway默认提供了一系列的路由谓词工厂,但如果这些内置的谓词工厂不能满足我们的需求,就需要编写自己的路由谓词工厂了。

**例如:**自定义路由工厂,使其在9:00~17:00这个期间才能访问。

配置:

spring:
  cloud:
    gateway:
      discovery:
        locator:
          #让gateway从服务发现组件上面找到其他微服务
          enabled: true
      routes:
        - id: between_router
          uri: lb://user-center
          predicates:
            - TimeBetween=上午9:00,下午11:00

创建名为TimeBetweenRoutePredicateFactory的类,继承AbstractRoutePredicateFactory

注意这个类前缀为TimeBetween,与配置里面谓词的名字相一致,而且这个类一定要以RoutePredicateFactory结尾。

@Component
public class TimeBetweenRoutePredicateFactory extends AbstractRoutePredicateFactory<TimeBetweenConfig> {
    public TimeBetweenRoutePredicateFactory() {
        super(TimeBetweenConfig.class);
    }
    @Override
    public Predicate<ServerWebExchange> apply(TimeBetweenConfig config) {
        LocalTime start = config.getStart();
        LocalTime end = config.getEnd();
        return exchange -> {
            LocalTime now = LocalTime.now();
            //时间处于 start 和 end 之间
            return now.isAfter(start) && now.isBefore(end);
        };
    }
    
    /**
     * 控制 配置类和配置文件的映射关系和顺序
     * @return
     */
    @Override
    public List<String> shortcutFieldOrder() {
        //映射
        //上午9:00  下午5:00是Gateway的时间格式形式
        //配置文件中的上午9:00对应配置实体类中的start,下午5:00对应end
        return Arrays.asList("start","end");
    }
}

@Data
public class TimeBetweenConfig {
    private LocalTime start;
    private LocalTime end;
}

四、Spring Cloud Gateway过滤器工厂详解

1. 内置过滤器

局部过滤器

全局过滤器

2. 自定义过滤器工厂

  1. 过滤器的声明周期

    • **pre:**Gateway转发请求之前
    • **post:**Gateway转发请求之后
  2. 自定义过滤器工厂的方式

    • 继承AbstractGatewayFilterFactory

      参考示例:org.springframework.cloud.gateway.filter.factory.RequestSizeGatewayFilterFactory

      配置形式:
      Spring Cloud Gateway服务网关_第4张图片

    • 继承AbstractNameValueGatewayFilterFactory

      参考示例:org.springframework.cloud.gateway.filter.factory.AddRequestHeaderGatewayFilterFactory

      配置形式:
      Spring Cloud Gateway服务网关_第5张图片

  3. 核心API
    Spring Cloud Gateway服务网关_第6张图片

  4. 编写一个过滤器工厂

    **例如:**进入这个过滤器工厂时就打印一下日志。

    配置:

    spring:
      cloud:
        gateway:
          discovery:
            locator:
              #让gateway从服务发现组件上面找到其他微服务
              enabled: true
          routes:
            - id: between_router
              uri: lb://user-center
              predicates:
                - TimeBetween=上午9:00,下午11:00
              filters:
                - PreLog=a,b
    

    创建名为PreLogGatewayFilterFactory的类继承AbstractNameValueGatewayFilterFactory,

    注意这个类前缀为PreLog,与配置里面filter的名字相一致,而且这个类一定要以GatewayFilterFactory结尾

    @Slf4j
    @Component
    public class PreLogGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
        @Override
        public GatewayFilter apply(NameValueConfig config) {
    
            return ((exchange,chain) -> {
    
                log.info("请求进来了 = {},{}",config.getName(),config.getValue());
    
                ServerHttpRequest modifiedRequest = exchange.getRequest()
                        .mutate()
                        .build();
                ServerWebExchange modifiedExchange = exchange.mutate().request(modifiedRequest).build();
    
                return chain.filter(modifiedExchange);
            });
        }
    }
    

3. 过滤器的执行顺序

  • **结论1:**Order越小越靠前执行

  • **结论2:**过滤器工厂的Order按配置顺序从1开始递增
    Spring Cloud Gateway服务网关_第7张图片

  • **结论3:**如果配置了默认过滤器,则先执行相同Order的默认过滤器
    Spring Cloud Gateway服务网关_第8张图片

  • **结论4:**如需自行控制Order,可返回OrderedGatewayFilter


五、Spring Cloud Gateway整合Sentinel

后面会讲到,再回来做总结


六、Spring Cloud Gateway监控

Spring Cloud Gateway监控


七、排错、调试技巧总结

Spring Cloud Gateway排错、调试技巧总结


八、Spring Cloud Gateway限流

Spring Cloud Gateway限流详解

你可能感兴趣的:(Spring,Cloud,Alibaba)