• SpringCloud搭建微服务之Gateway网关


    1. 概述

    Gateway是在Spring生态系统之上构建的API网关服务,旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤器功能,基于WebFlux框架实现,而WebFlux框架底层又使用了高性能的Reactor模式通信框架Netty。常用功能有反向代理、鉴权、流量控制、熔断和日志监控

    1.1. Gateway特性

    1. 动态路由:能够匹配任何请求属性
    2. 可以对路由指定Predicate(断言)和Filter(过滤器),且易于编写
    3. 集成Hystrix断路器功能
    4. 集成Spring Cloud服务发现功能
    5. 请求限流功能
    6. 支持路径重写

    1.2. 核心概念

    Route(路由)
    是构建网关的基本模块,由ID、目标URI、一系列断言和过滤器组成,断言为true时匹配该路由
    Predicate(断言)
    请求与断言相匹配则进行路由
    Filter(过滤)
    可以在请求被路由前或之后对请求进行修改

    1.3. Gateway网关请求流程

    1. 客户端向Gateway发出请求,然后在Gateway Handler Mapping中找到与请求相匹配的路由,将其发送到Gateway Web Handler
    2. Handler再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回
    3. 过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(pre)或之后(post)执行业务逻辑
    4. Filter在pre类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换
    5. 在post类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等

    流程图如下
    gateway流程图

    2. 搭建Gateway网关服务

    2.1. 引入核心依赖

    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-gatewayartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    2.2. 编写application.yml配置文件

    server:
      port: 8812
    spring:
      application:
        name: cloud-gateway
      cloud:
        gateway:
          routes:
            - id: provider_routh
              uri: http://localhost:8770
              predicates:
                - Path=/provider/getProviderInfo/**
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.3. 编写主启动类

    @SpringBootApplication
    public class GatewayApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(GatewayApplication.class, args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.4. 验证

    依次启动Eureka Server、Provider和Gateway三个微服务,在浏览器输入地址http://localhost:8812/provider/getProviderInfo/world
    网关访问

    2.5. 代码配置网关

    新建一个GatewayConfig类

    @Configuration
    public class GatewayConfig {
    
        @Bean
        public RouteLocator routeLocator(RouteLocatorBuilder builder) {
            RouteLocatorBuilder.Builder routes = builder.routes();
            routes.route("provider_routh", predicate -> predicate.path("/provider/getProviderConfigInfo/**")
                    .uri("http://localhost:8770")).build();
            return routes.build();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    再次启动Gateway服务,在浏览器地址输入http://localhost:8812/provider/getProviderConfigInfo/zhangsan就可以直接跳转到百度新闻网
    配置类实现跳转

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

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

    3.1. 引入Eureka Client依赖

    <dependency>
       <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    3.2. 修改application.yml

    spring:
      application:
        name: cloud-gateway
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
          routes:
            - id: provider_routh
              uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
              predicates:
                - Path=/provider/getProviderInfo/**
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3.3. 验证

    在浏览器地址栏输入http://localhost:8812/provider/getProviderInfo/zhangsan
    动态路由匹配

    4. Route Predicate

    Spring Cloud Gateway包括许多内置的Route Predicate工厂,所有这些Predicate都与HTTP请求的不同属性匹配,多个Route Predicate工厂可以进行组合,常见的如下:

    4.1. After Route Predicate

    指定日期(ZonedDateTime)之后才能访问请求路径

    spring:
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
          routes:
            - id: provider_routh
              uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
              predicates:
                - After=2022-09-07T17:42:47.789+08:00[Asia/Shanghai]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4.2. Before Route Predicate

    指定日期(ZonedDateTime)之前才能访问请求路径

    spring:
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
          routes:
            - id: provider_routh
              uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
              predicates:
                - Before=2022-09-08T17:42:47.789+08:00[Asia/Shanghai]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4.3. Between Route Predicate

    指定日期(ZonedDateTime)之间才能访问请求路径

    spring:
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
          routes:
            - id: provider_routh
              uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
              predicates:
                - Between=2022-09-07T17:42:47.789+08:00[Asia/Shanghai], 2022-09-08T17:42:47.789+08:00[Asia/Shanghai]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4.4. Cookie Route Predicate

    通过获取对应的 Cookie name 值和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行

    spring:
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
          routes:
            - id: provider_routh
              uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
              predicates:
                - Cookie=username, zhangsan
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4.5. Header Route Predicate

    请求中必须带有消息头,且要匹配名称和值

    spring:
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
          routes:
            - id: provider_routh
              uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
              predicates:
                - Header=X-Request-Id, \d+
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4.6. Host Route Predicate

    一组匹配的域名列表,用.号作为分隔符,通过参数中的主机地址作为匹配规则

    spring:
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
          routes:
            - id: provider_routh
              uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
              predicates:
                - Host=**.xlhj.org,**.xlhj.com
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4.7. Method Route Predicate

    HTTP请求方式进行匹配POST/GET

    spring:
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
          routes:
            - id: provider_routh
              uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
              predicates:
                - Method=GET,POST
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4.8. Path Route Predicate

    请求路径进行匹配

    spring:
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
          routes:
            - id: provider_routh
              uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
              predicates:
                - Path=/provider/getProviderInfo/**
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4.9. Query Route Predicate

    查询条件匹配,一个参数时,表示请求参数中必须包含此值;两个参数时,表示请求参数中包含此值,参数值匹配第二个参数

    spring:
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
          routes:
            - id: provider_routh
              uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
              predicates:
                - Query=username, zhangsan
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4.10. RemoteAddr Route Predicate

    IP地址进行匹配

    spring:
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
          routes:
            - id: provider_routh
              uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
              predicates:
                - RemoteAddr=192.168.1.1/24
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4.11. Weight Route Predicate

    权重进行匹配

    spring:
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
          routes:
            - id: provider_routh
              uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
              predicates:
                - Weight=group1, 2
            - id: order_routh
              uri: http://localhost:8770
              predicates:
                - Weight=group1, 8
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    20%请求走上面服务,80%请求走下面服务

    5. 过滤器Filter

    用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用,主要有两类,即GatewayFilter和GlobalFilter

    5.1. 常用过滤器

    AddRequestHeader:请求头过滤器

    spring:
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
          routes:
            - id: provider_routh
              uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
              predicates:
                - Path=/provider/getProviderInfo/**
              filters:
                - AddRequestHeader=X-Request-Id, xlhj
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    AddRequestParameter:请求参数过滤器

    spring:
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
          routes:
            - id: provider_routh
              uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
              predicates:
                - Path=/provider/getProviderInfo/**
              filters:
                - AddRequestParameter=X-Request-Id, xlhj
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    其他过滤器用法都差不多

    5.2. 自定义过滤器

    自定义全局过滤器需要实现GlobalFilter和Ordered两个接口,常用语全局日志记录和统一权限认证,新建一个GatewayGlobalFilter类,代码如下:

    @Component
    public class GatewayGlobalFilter implements GlobalFilter, Ordered {
    
        private static final Logger logger = LoggerFactory.getLogger(GatewayGlobalFilter.class);
    
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            logger.info("执行自定义全局过滤器");
            String requestId = exchange.getRequest().getQueryParams().getFirst("X-Request-Id");
            if (StringUtils.isBlank(requestId)) {
                logger.info("请求参数为空!");
                exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
                return exchange.getResponse().setComplete();
            }
            return chain.filter(exchange);
        }
    
        @Override
        public int getOrder() {
            return 0;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    5.3. 验证

    重新启动gateway微服务,浏览器地址栏输入http://localhost:8812/provider/getProviderInfo/world?X-Request-Id=xlhj
    过滤器验证

  • 相关阅读:
    iOS证书和描述文件申请详情步骤
    JavaScript学习之路---JavaScript操作BOM
    697226-52-1, 细胞穿膜肽TAT-amide
    自定义ProjectSettings设置项
    Ubuntu安装redis详细教程
    uniapp 添加定位权限及弹出权限弹框
    Unity --- 给游戏物体做标记 以及 快捷键补充
    基于stm32微控制器的绘图机器人设计
    MES系统防呆措施之具体场景学习
    【Pygame实战】强烈推荐:教你用百行代码编写一款《小蜜蜂历险记》不信?来看看(玩儿嗨了~)
  • 原文地址:https://blog.csdn.net/liu320yj/article/details/126659127