前言  

网关有以下几个作用:

  • 统一入口:未全部为服务提供一个唯一的入口,网关起到外部和内部隔离的作用,保障了后台服务的安全性。
  • 鉴权校验:识别每个请求的权限,拒绝不符合要求的请求。
  • 动态路由:动态的将请求路由到不同的后端集群中。
  • 减少客户端与服务端的耦合:服务可以独立发展,通过网关层来做映射。

一、什么是Spring Cloud Gateway?

  • Spring Cloud 第一代网关 Zuul , Spring Cloud 第二代网关 GateWay。
  • Spring Cloud Gateway 是由 WebFlux + Netty + Reactor 实现的响应式的 API 网关。
  • Spring Cloud Gateway 不能在传统的 servlet 容器中工作,也不能构建成 war 包!
  • Spring Cloud Gateway 为微服务架构提供一种简单且有效的 API 路由的管理方式,并基于 Filter 的方式提供网关的基本功能,例如说安全认证、监控、限流等等

注意:Spring Cloud Gateway会和spring-webmvc的依赖冲突,需要排除spring-webmvc 

二、Spring Cloud Gateway核心概念

  • 路由(route)

路由是网关中最基础的部分,路由信息包括一个ID、一个目的URI、一组断言工厂、一组Filter组成。如果断言为真,则说明请求的URL和配置的路由匹配。

  • 断言(predicates)

Java8中的断言函数,SpringCloud Gateway中的断言函数类型是Spring5.0框架中的ServerWebExchange。断言函数允许开发者去定义匹配Http request中的任何信息,比如请求头和参数等。

  • 过滤器(Filter)

SpringCloud Gateway中的filter分为Gateway FilIer和Global Filter。Filter可以对请求和响应进行处理。

三、Spring Cloud Gateway如何工作的?

java网关对比 spring网关作用_java网关对比

 四、Spring Cloud Gateway快速开始

1. 环境搭建:Maven项目子模块,pom配置。

2. 配置文件:基础配置、路由配置断言配置、过滤器配置。

3. 代码部分:自定义路由/断言/过滤器等,(无实现可无此配置)

详情参考:官网配置使用

1、环境搭建

<!-- 依赖 父工程-->
    <parent>
        <groupId>org.example</groupId>
        <artifactId>lxnmall</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <!-- 本工程基础信息-->
    <groupId>com.lxnmall</groupId>
    <artifactId>gateway</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>lxnmall-gateway</name>

    <dependencies>
        <!-- 本工程依赖其他公共模块 要排除web mvc -->
        <dependency>
            <groupId>org.lxnmall</groupId>
            <artifactId>lxnmall-common</artifactId>
            <version>1.0-SNAPSHOT</version>
            <exclusions>
                <exclusion>
                    <groupId>com.alibaba</groupId>
                    <artifactId>druid-spring-boot-starter</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.github.pagehelper</groupId>
                    <artifactId>pagehelper-spring-boot-starter</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- gateway的依赖添加-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!-- 整合其他的依赖添加-->
    </dependencies>

2、 配置文件

1)基础信息

java网关对比 spring网关作用_java_02

server:
  port: 8888
spring:
  application:
    name: lixiunan-gateway
  cloud:
    gateway:
      # 是否开启网关
      enabled: true
      discovery:
        locator:
          # 默认为false,设为true开启: 通过微服务创建路由的功能,即可以通过微服务名访问服务
          lower-case-service-id: true
          enabled: true

2)路由\断言\过滤器配置

server:
  port: 8888
spring:
  application:
    name: lixiunan-gateway
  cloud:
    gateway:
      # 是否开启网关
      enabled: true
      discovery:
        locator:
          # 默认为false,设为true开启: 通过微服务创建路由的功能,即可以通过微服务名访问服务
          lower-case-service-id: true
          enabled: true
      # 设置路由:路由id、路由到微服务的uri、断言
      routes:
        # 路由ID,全局唯一
        - id: lxnmall-product
          # 详见【解释1】
          uri: lb://lxnmall-product
          # 断言配置
          predicates:
            # 路径配置:原路径为http://localhost:8001/order/getProduct...
            - Path=/product/**
            # #######以下非必需#######################
            # 时间匹配:在指定的日期时间之后发生的请求才可以进网关,入参是ZonedDateTime类型
            - After=2021-10-18T22:22:07.783+08:00[Asia/Shanghai]
            # Cookie匹配:cookie里username为lixiunan的可以进
            - Cookie=username, lixiunan
            # Header匹配  请求中带有请求头名为 x-request-id,其值与 \d+ 正则表达式匹配
            #- Header=X-Request-Id, \d+
          #配置过滤器工厂
          #filters:
            # - AddRequestHeader=X-Request-color, red  #添加请求头

【解释1】:目标微服务的请求地址原始 uri: http://localhost:8001;LoadBalancerClientFilter 会查看exchange的属性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 的值如果该值的scheme是 lb,比如:lb://lxnmall-product ,它将会使用Spring Cloud的LoadBalancerClient 来将 lxnmall-product解析成实际的host和port,并替换掉 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 的内容。  

3、自定义路由断言工厂

自定义路由断言工厂步骤:

  • 继承 AbstractRoutePredicateFactory 类,重写 apply 方法的逻辑。
  • 命名需要以 RoutePredicateFactory 结尾
  • yml配置文件中配置

1)继承 AbstractRoutePredicateFactory 类,重写 apply 方法的逻辑

@Component
@Slf4j
public class LixiunanRoutePredicateFactory extends AbstractRoutePredicateFactory<CheckAuthRoutePredicateFactory.Config> {

    public LixiunanRoutePredicateFactory() {
        super(Config.class);
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        return new GatewayPredicate() {

            @Override
            public boolean test(ServerWebExchange serverWebExchange) {
                log.info("调用LixiunanRoutePredicateFactory");
                //需要实现的断言
                //......
                
                return true;
            }
        };
    }
}

2) yml配置文件中配置

spring:
  cloud:
    gateway:
      #设置路由:路由id、路由到微服务的uri、断言
      routes:
      - id: lixiunan_route  #路由ID,全局唯一
        uri: http://localhost:6666  #目标微服务的请求地址和端口
        predicates:
         # 测试:http://localhost:8888/lxn/...
        - Path=/lxn/**   #Path路径匹配
        #自定义断言工厂
        - name: Lixiunan

3-2、自定义过滤器工厂

自定义路由断言工厂步骤:

  • 继承AbstractNameValueGatewayFilterFactory
  • 名称必须要以GatewayFilterFactory结尾
  • yml配置使用

1) 继承AbstractNameValueGatewayFilterFactory

@Component
@Slf4j
public class LixiunanGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {

    @Override
    public GatewayFilter apply(NameValueConfig config) {
        return (exchange, chain) -> {
            log.info("调用LixiunanGatewayFilterFactory");
            //实现适配逻辑
            //......
            //加入监听链中生效
            return chain.filter(exchange);
        };
    }
}

2)yml配置使用自定义适配器工厂

spring:
  cloud:
    gateway:
      routes:
      - id: lixiunan_route  #路由ID,全局唯一
        uri: http://localhost:8888  #目标微服务的请求地址和端口
        #配置过滤器工厂
        filters:
        - Lixiunan

注:Gateway跨域配置(CORS Configuration) 

Spring Cloud Gateway

spring:
  cloud:
    gateway:
        globalcors:
          cors-configurations:
            '[/**]':
              allowedOrigins: "*"
              allowedMethods:
              - GET
              - POST
              - 。。。