Administrator
Administrator
Published on 2025-01-06 / 0 Visits
0
0

微服务项目教程-Gateway网关组件(四)

Description

Gateway 介绍

SpringCloud Gateway是spring官方基于Spring 5.0、Spring Boot2.0和Project Reactor等技术开发的网关,旨在为微服务架构提供简单、有效和统一的API路由管理方式.
SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty.
SpringCloud Gateway不仅提供统一的路由方式,并且还基于Filer链的方式提供了网关基本的功能,例如:鉴权、监控/指标、流量控制、熔断限流等.

Gateway核心
  • Route(路由): 路由是网关最基础的部分,路由信息有一个ID、一个目的URL、一组断言和一组Filter组成。如果断言路由为真,则说明请求的URL和配置匹配

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

  • Filter(过滤器): 一个标准的Spring webFilter。SpringCloud Gateway中的Filter分为两种类型的Filter,分别是Gateway Filter和Global Filter。使用过滤器,可以在请求被路由前或者之后对请求进行修改

第一步 在父工程(pom.xml)


    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-boot.version>2.3.2.RELEASE</spring-boot.version>
        <spring-cloud.version>Hoxton.SR9</spring-cloud.version>
        <spring-cloud-alibaba.version>2.2.6.RELEASE</spring-cloud-alibaba.version>
        <log4j-slf4j.version>2.17.0</log4j-slf4j.version>
    </properties>


    <dependencyManagement>
        <dependencies>
          <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--springcloud alibaba依赖-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>


第二步 在网关子工程(pom.xml)中添加网关依赖和Nacos客户端依赖
    <!-- 别忘记继承父工程 -->
    <parent>
        <groupId>org.lanqiao</groupId>
        <artifactId>lanqiao-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

      <!-- 添加网关依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!-- 添加 nacos 客户端依赖 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>


第三步 在启动类上添加注解@EnableDiscoveryClient (可选)


//注册发现客户端开关(依赖中自动开启此注解)
@EnableDiscoveryClient
@SpringBootApplication
public class ProviderXxxxxxApplication {
  public static void main(String[] args) {
    SpringApplication.run(ProviderXxxxxxApplication.class, args);
  }
}

第四步 在网关子工程 application.yml 中添加nacos 注册发现地址
server:
  port: 10000
spring:
  application:
    name: lanqiao-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848



spring.cloud.nacos.discovery.server-addr :nacos注册中心的地址和进程端口
spring.application.name :微服务的名字,要具有唯一性

第五步 在网关工程 application.yml 中添加路由
server:
  port: 10000
spring:
  application:
    name: lanqiao-gateway
  cloud:
    gateway:
      routes:
        - id: lanqiao-gateway
          uri: lb://lanqiao-passenger
          predicates:
          ## 当请求的路径为api/passenger开头的时,负载均衡到lanqiao-passenger微服务
            - Path=/api/passenger/**
          filters:
          ## StripPrefix=1就代表截取路径的个数为1,比如前端过来请求/api/passenger/view,匹配成功后,路由到后端的请求路径就会变成http://localhost:20000/passenger/view,去掉api前缀路径。
            - StripPrefix=1 

gateWay的主要功能之一是转发请求,转发规则的定义主要包含三个部分

  • Route(路由) 路由是网关的基本单元,由ID、URI、一组Predicate、一组Filter组成,根据Predicate进行匹配转发。

  • Predicate(谓语、断言) 路由转发的判断条件,目前SpringCloud Gateway支持多种方式,常见如:Path、Query、Method、Header等,写法必须遵循 key=vlue的形式

  • Filter(过滤器) 过滤器是路由转发请求时所经过的过滤逻辑,可用于修改请求、响应内容

通过网关访问微服务

http://localhost:10000/api/passenger/hello

如果访问失败,可跨过网关直接访问微服务接口,测试微服务接口是否正常,然后排查是否是网关问题
如果访问失败,网关配置不存在问题的情况下,尝试把 lb://lanqiao-passenger 换成http://localhost:20000

断言(Predicate)工厂介绍

Spring Cloud Gateway包括许多内置的路由谓词工厂。所有这些谓词都与HTTP请求的不同属性相匹配。你可以用逻辑 and 语句组合多个路由谓词工厂。

官网:https://springdoc.cn/spring-cloud-gateway/#gateway-request-predicates-factories

过滤器 filter介绍

Gateway提供了基于路由的局部过滤器和全局性的过滤器

  1. 路由过滤器:

路由(Route)过滤器(Filter)允许以某种方式修改传入的 HTTP 请求或传出的 HTTP 响应。路由过滤器的范围是一个特定的路由。Spring Cloud Gateway 包括许多内置的 GatewayFilter 工厂。下面列举了几个常用的过滤器案例。

AddRequestHeader:

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: https://example.org
        filters:
        - AddRequestHeader=X-Request-red, blue

这个列表将 X-Request-red:blue header添加到所有匹配请求的下游请求的header信息中。

PrefixPath:

spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: https://example.org
        filters:
        - PrefixPath=/mypath

这就把 /mypath 作为所有匹配请求的路径的前缀。因此,一个到 /hello 的请求会被发送到 /mypath/hello。

RewritePath:

spring:
  cloud:
    gateway:
      routes:
      - id: rewritepath_route
        uri: https://example.org
        predicates:
        - Path=/red/**
        filters:
        - RewritePath=/red/?(?<segment>.*), /$\{segment}

对于请求路径为 /red/blue 的情况,在进行下游请求之前将路径设置为 /blue。注意,由于YAML的规范,$ 应该被替换成 $\。

StripPrefix:
StripPrefix GatewayFilter 工厂需要一个参数,即 parts。parts 参数表示在向下游发送请求之前要从路径中剥离的部分的数量。下面的列表配置了一个 StripPrefix GatewayFilter。

spring:
  cloud:
    gateway:
      routes:
      - id: nameRoot
        uri: https://nameservice
        predicates:
        - Path=/name/**
        filters:
        - StripPrefix=2

当通过网关向 /name/blue/red 发出请求时,向 nameservice 发出的请求看起来像 nameservice/red。

  1. 全局 Filter

//在filter 包下 建立自定义过滤器类
@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("custom global filter");
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -1;
    }
}



当一个请求与路由匹配时,filter web handler将 GlobalFilter 的所有实例和 GatewayFilter 的所有路由特定实例添加到一个过滤链中。这个组合的过滤链由 org.springframework.core.Ordered 接口进行排序,你可以通过实现 getOrder() 方法来设置这个接口。

由于 Spring Cloud Gateway 区分了过滤器逻辑执行的 “pre” 和 “post” 阶段(见如何工作),优先级最高的过滤器在 “pre” 阶段是第一个,在 “post” 阶段是最后一个。

跨域Cors配置

gateway提供了对某个路由的跨域配置,也提供了全局的跨域配置,相比而言全局的跨域配置更一劳永逸。


spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOrigins: "*"
            allowedMethods:
            - GET
            - POST
            - PUT
            - DELETE
            - OPTIONS
            allowedHeaders: '*'
            maxAge: 30

maxAge属性:配置预检请求的有效时间, 单位是“秒”,表示:在多长时间内,不需要发出第二次预检请求

全配置案例

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id: a
          uri: lb://cloud-service-a
          predicates:
            - Path=/a/**
          filters:
            - StripPrefix=1    # 转发时,去掉一层前缀 zeus
        - id: b
          uri: lb://cloud-service-b
          predicates:
            - Path=/b/**
          filters:
            - StripPrefix=1  # 转发时,去掉一层前缀 apollo
      globalcors:
        cors-configurations:
          '[/**]':
            # 允许携带认证信息
            allowCredentials: false
            # 允许跨域的源(网站域名/ip),设置*为全部
            allowedOrigins: "*"
            # 允许跨域的method, 默认为GET和OPTIONS,设置*为全部
            allowedMethods:
              - GET
              - PUT
              - POST
              - DELETE
              - OPTIONS
            # 允许跨域请求里的head字段,设置*为全部
            allowedHeaders: "*"
        #解决双重跨域 RETAIN_FIRST RETAIN_LAST RETAIN_UNIQUE
        default-filters:
          - DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials, RETAIN_FIRST
        add-to-simple-url-handler-mapping: true  
        # 如果没有匹配到路由依然能够跨域



    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
server:
  port:   10000
logging:
  level:
    org:
      springframework:
        cloud:
          gateway:  debug
      lanqiao:
        gateway:
          filter: debug


my:
  token:
    whiteURIS:
      - /login
      - /register
      - /logout








Comment