Gateway网关简介以及使用

这篇具有很好参考价值的文章主要介绍了Gateway网关简介以及使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、概述简介

官网:https://docs.spring.io/spring-cloud-gateway/docs/3.1.3/reference/html/

1.1. Gateway是什么

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

什么是网关?

网关(Gateway)又称网间连接器,网关在网络层实现服务之间网络互连。用程序的话来说就是请求转发。他就好比小区的门一样,你想进来小区,必须通过门才能进来。为什么要有这个门?为了方便管理以及安全考虑,就好比现在疫情期间,动不动小区封了,假如小区没有门,想要封小区还得费特别大的劲将小区给围住。

再回到程序当中,现在非常流行微服务系统,将整体应用拆分为了多个模块,那么问题来了,前端页面肯定会涉及到调用不同微服务的接口,一个微服务就代表着一个端口的应用,每个微服务都是独立的,那么前端在调用的时候不可能将访问地址设置成多个呀。设置成多个当然也可以,弊端就是开发过程当中我们涉及到环境(域名服务器ip)的切换,那还得改多个,因此网关为解决这个问题而生,网关可以将多个微服务访问的地址进行聚拢起来,你要访问哪个微服务的接口,直接访问网关,网关负责给你转发到对应的微服务地址上,因此前端只需要知道网关的地址服务地址就可以了。

Gateway和Nginx两个网关的区别

在学习Gateway网关的时候很容易联想到Nginx,甚至刚接触的时候会好奇很多架构图上面 画的两个网关竟然都用到了,那么他们两个到底有什么关联性?

下图当中圈出来的就是Gateway所在的位置。而Nginx属于在Gateway上层。甚至可以在外部请求的上层,因为Nginx可以用来做网关层的负载均衡,同时他还可以用来做流量入口。因为他本身就是服务器,实际开发当中都是通过Nginx来做流量入口的。

什么是流量入口?

流量入口的意思就是假如我有个html放到linux当中,那么外面的人怎么才能访问到linux当中的页面呢?Nginx可以用来解决这个问题,他本身就是一个服务器,使用过程就是开启端口然后监听请求,当请求来了,可以将请求 指向本机的任意可访问的html文件。

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关

Gateway可以称之为微服务网关(业务网关),而Nginx可以作为整个应用的流量网关,以及微服务网关的负载均衡。业务网关针对具体的业务需要提供特定的流控策略、缓存策略、鉴权认证策略等等。流量网关通常只专注于全局的Api管理策略,比如全局流量监控、日志记录、全局限流、黑白名单控制、接入请求到业务系统的负载均衡等,有点类似防火墙。Kong 就是典型的流量网关。

  • nginx是用C语言写的,自定义扩展的话,要么写C要么写lua
  • gateway是java语言的一个框架,可以在框架上进行代码的扩展与控制,例如:安全控制,统一异常处理,XXS,SQL注入等;权限控制,黑白名单,性能监控,日志打印等;

Gateway底层使用了Netty通讯框架

SpringCloud Gateway 使用的Webflux中的reactor-netty响应式编程组件。

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关

1.2. Gateway能干嘛

  • 反向代理
  • 鉴权
  • 限流
  • 熔断
  • 日志监控

1.3. Zuul和gateway

目前在cloud官网当中新版本已经将zuul彻底移除了。Zuul1.0已经进入了维护阶段,而Gateway是SpringCloud团队研发的,是亲儿子产品,值得信赖。而且很多功能Zuul都没有用起来也非常的简单便捷。在版本选型上我们基本上不会再考虑zuul了。

Zuul 1.x 基于Servlet 2. 5使用阻塞架构它不支持任何长连接(如 WebSocket) Zuul 的设计模式和Nginx较像,每次 I/ O 操作都是从工作线程中选择一个执行,请求线程被阻塞到工作线程完成,但是差别是Nginx 用C++ 实现,Zuul 用 Java 实现,而 JVM 本身会有第一次加载较慢的情况,使得Zuul 的性能相对较差。

Zuul 2.x理念更先进,想基于Netty非阻塞和支持长连接,但SpringCloud目前还没有整合。 Zuul 2.x的性能较 Zuul 1.x 有较大提升。在性能方面,根据官方提供的基准测试, Spring Cloud Gateway 的 RPS(每秒请求数)是Zuul 的 1. 6 倍

Spring Cloud Gateway 建立 在 Spring Framework 5、 Project Reactor 和 Spring Boot 2 之上, 使用非阻塞 API。Spring Cloud Gateway 还支持WebSocket, 并且与Spring紧密集成拥有更好的开发体验

1.4. gateway三大核心概念

  • Route(路由):路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由。
  • Predicate(断言):参考的是Java8的java.util.function.Predicate,开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由。
  • Filter(过滤):指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关
web请求,通过一些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。

  • predicate就是我们的匹配条件;
  • 而filter,就可以理解为一个无所不能的拦截器,可以在执行前后来执行自己的逻辑,有了这两个元素,再加上目标uri,就可以实现一个具体的路由了

1.5. gateway工作流程

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关
客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler

Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。
过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。

Filter在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。

核心逻辑:路由转发+执行过滤器链

二、实战练习

2.1. 入门demo

假如我有个8001端口的服务,然后他有以下两个接口,但是我又不想让别人通过8001端口访问,我想让他通过9527访问怎么办?很简单通过Gateway搭建一个网关服务即可解决该问题。

@RestController
@Slf4j
public class PaymentController {

    @Autowired
    private PaymentMapper paymentMapper;

    @Value("${server.port}")
    private String serverPort;

    @GetMapping(value = "/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
        Payment payment = paymentMapper.selectById(id);
        log.info("*****查询结果:{}", payment);
        if (payment != null) {
            return new CommonResult(200, "查询成功, 服务端口:" + serverPort, payment);
        } else {
            return new CommonResult(444, "没有对应记录,查询ID: " + id + ",服务端口:" + serverPort, null);
        }
    }

    @GetMapping(value = "/payment/lb")
    public String getPaymentLB() {
        return serverPort;
    }
}

接下来搭建一个9527端口的Gateway入门级别的网关服务

1、以下是使用到的核心依赖,一般都会采用聚合工程,由父工程存放dependencyManagement当中的依赖,其他子模块引入使用的组件即可,单纯的练习图省劲的话,创建一个独立可运行的boot项目也可以。

关于搭建聚合我这里就尽量减省步骤了,不会搭建的可以看我的这一篇文章:https://blog.csdn.net/weixin_43888891/article/details/125267683?spm=1001.2014.3001.5502

<dependencyManagement>
    <dependencies>
        <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-dependencies</artifactId>
           <version>2.6.8</version>
           <type>pom</type>
           <scope>import</scope>
       </dependency>
        <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-dependencies</artifactId>
           <version>2021.0.3</version>
           <type>pom</type>
           <scope>import</scope>
       </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <!--gateway-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
 </dependencies>   

2、添加配置

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
      - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
        uri: http://localhost:8001          #匹配后提供服务的路由地址
        predicates:
        - Path=/payment/get/**         # 断言,路径相匹配的进行路由

      - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
        uri: http://localhost:8001          #匹配后提供服务的路由地址
        predicates:
        - Path=/payment/lb/**         # 断言,路径相匹配的进行路由

3、测试访问:http://localhost:9527/payment/get/1

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关
gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关

4、总结

通过以上示例,我们可以基本的掌握Gateway到底是干什么的,说白了就是请求转发。

如果程序引用了spring-cloud-starter-gateway,但不希望启用网关,请设置spring.cloud.gateway.enabled=false

设置完之后再想通过网关来转发请求,会直接404。

2.2. 网关路由两种配置方式

java代码配置:

@Configuration
public class GateWayConfig {
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        RouteLocatorBuilder.Builder routes = builder.routes();

        routes.route("path_route", r ->
                r.path("/payment/get/**").uri("http://localhost:8001")).build();

        return routes.build();
    }
}

配置文件配置

spring:
  cloud:
    gateway:
      routes:
      - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
        uri: http://localhost:8001          #匹配后提供服务的路由地址
        predicates:
        - Path=/payment/get/**         # 断言,路径相匹配的进行路由

这两种可以实现同样的结果,假如两个都存在,并且Path是一样的,代码配置的要比配置文件配置的级别高,这时候会路由到代码配置的uri当中。

实际开发当中我们基本上都会用配置文件的方式来配置,很少会用java配置。

2.3. 配合注册中心使用

以上示例是直接将请求转发到了ip+端口服务上。只有配合注册中心使用,才能通过服务名称来调用完成微服务的负载均衡。

如果对注册中心不是很了解的可以去看一下我之前的文章,有Eureka、Consul、zookeeper注册中心教程,所谓的注册中心我们可以把它当做就是一个map,服务的ip+端口号(或者是域名)就是value,而服务名称当做key。然后调用者通过服务名称来获取到调用服务的域名。这样假如微服务是集群,但是他们的服务名称是一样的,这样就可以很轻松的通过服务名来获取集群的ip+端口,有了ip+端口,就剩下负载均衡轮询调用了。

这里我直接就是通过Eureka注册中心来进行演示了。正常情况下,我们可以选择将网关服务注册到注册中心,也可以不进行注册,网关服务最重要的是要具备服务发现功能,至于要不要注册上去我们可以根据自己的业务场景来决定。

1.引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2.修改配置

eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    service-url:
      # false表示不向注册中心注册自己。
      register-with-eureka: true
      # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          # uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由

        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          # uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/lb/**         # 断言,路径相匹配的进行路由
      enabled: true

通过服务名称去注册中心获取ip和地址这不用我们操心,都由框架为我们解决了,我们只需要知道要调用的服务名称即可。

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关

uri: lb://cloud-payment-service:需要注意的是uri的协议为Ib,表示启用Gateway的负载均衡功能。

3.启动类添加注解:@EnableEurekaClient(代表的是启用Eureka)
4.测试:首先将两个提供者(两个提供者是一样的服务,只不过启动了两个,称之为集群)注册到注册中心,然后由网关来进行转发。

1个是8001,另一个是8002
gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关
访问两次会发现他是轮询的。

三、Predicate的使用

3.1. Predicate是什么?

启动网关服务的时候会发现有一排日志,如下所示:
gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关
Route Predicate Factories是什么?

首先我们会发现一共有12个,他们每个都有自己的应用场景,我们也可以看看官网介绍:

Spring Cloud Gateway 将路由匹配为 Spring WebFluxHandlerMapping基础架构的一部分。Spring Cloud Gateway 包含许多内置的路由谓词工厂。所有这些谓词都匹配 HTTP 请求的不同属性。您可以将多个路由谓词工厂与逻辑and语句结合起来。(谓词工厂也就是我们所说的断言)

作用:如果请求与断言相匹配则进行路由,如果不匹配直接404

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关

3.2. 12个Predicate使用讲解

  1. After Route Predicate

作用:就是通过设置一个时间,然后After代表的是后的意思,也就是设置的时间 之后 是可以访问这个路由的,在这个时间之前是访问不了的,注意:这个设置的是时区时间。

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关

public static void main(String[] args) {
    ZonedDateTime zbj = ZonedDateTime.now(); // 从默认时区中的系统时钟获取当前日期时间
    System.out.println(zbj);
//        ZonedDateTime zny = ZonedDateTime.now(ZoneId.of("America/New_York")); // 用指定时区获取当前时间
//        System.out.println(zny);
}

执行结果:

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关

用法示例: 如下示例当中会发现我实际上相当于设置了两个predicates(断言),path也算是一个,After又是一个,在实际开发当中,根据自己的实际场景可以随便使用断言。

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          # uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由
            - After=2022-08-20T00:10:15.434859+08:00[Asia/Shanghai]
  1. Before Route Predicater:Before就是设置的时间之前可以访问,过了时间之后不可以访问
- Before=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]
  1. Between Route Predicate:两个时间的区间是可以访问的,过了时间之后不可以访问
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
  1. Cookie Route Predicate:Cookie路由谓词工厂有两个参数,cookie和namea regexp(这是一个 Java 正则表达式)。此谓词匹配具有给定名称且其值与正则表达式匹配的 cookie。
- Cookie=username,zzyy

不带cookie访问直接404

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关

带上cookie访问

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关

  1. Header Route Predicater:Header路由谓词工厂有两个参数,the和headera regexp(这是一个 Java 正则表达式)。此谓词与具有给定名称且值与正则表达式匹配的标头匹配。
- Header=X-Request-Id, \d+

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关

  1. Host Route Predicate:路由谓词工厂采用Host一个参数:主机名列表patterns。该模式是一种 Ant 风格的模式,.以分隔符为分隔符。
- Host=**.baidu.com

正确:curl http://localhost:9527/payment/lb -H “Host: www.baidu.com”
正确:curl http://localhost:9527/payment/lb -H “Host: java.baidu.com”
错误:curl http://localhost:9527/payment/lb -H “Host: java.baidu.net”

  1. Method Route Predicate:设置了之后只有GET请求会路由
- Method=GET
  1. Path Route Predicate:关于path的上面示例当中我们就已经用到了。
- Path=/payment/lb/**
  1. Query Route Predicate:支持传入两个参数,一个是属性名,一个为属性值,属性值可以是正则表达式。
- Query=username, \d+  # 要有参数名username并且值还要是整数才能路由

示例:http://localhost:9527/payment/lb?username=31

  1. RemoteAddr Route Predicate:路由谓词工厂采用的RemoteAddr列表(最小大小为 1)sources,它们是 CIDR 表示法(IPv4 或 IPv6)字符串,例如192.168.0.1/16(其中192.168.0.1是 IP 地址和16子网掩码)。
- RemoteAddr=192.168.1.1/24
  1. Weight Route Predicate:Weight路由谓词工厂有两个参数:和group(weight一个 int)。权重是按组计算的。以下示例配置权重路由谓词:

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关

该路由会将约 80% 的流量转发到weighthigh.org,将约 20% 的流量转发到weightlow.org

  1. XForwarded Remote Addr Route Predicate:这可以与反向代理一起使用,例如负载平衡器或 Web 应用程序防火墙,其中仅当请求来自这些反向代理使用的受信任的 IP 地址列表时才允许请求。
- XForwardedRemoteAddr=192.168.1.1/24

可以把它当做IF判断,当满足的时候才能路由到uri,否则直接报异常。

四、Filter的使用

4.1. Filter是什么?

过滤器可以在执行方法前执行方法后进行过滤,所谓的过滤就是可以在请求上加一些操作,例如匹配到路由后可以在请求上添加个请求头,或者参数等等。

Gateway过滤器分为了两种:路由过滤器 和 全局过滤器

  1. 路由过滤器:路由过滤器针对于某一个路由进行使用,其中官网给我们提供了30多种类型的路由过滤器。

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关

  1. 全局过滤器:全局的往往是我们经常会用到的,他和路由过滤器区别就是,他是针对于所有路由进行设置的过滤规则,实际开发当中很少会针对于某一个路由使用Filter,大部分都会采用全局过滤器。

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关

4.2. 常用的GatewayFilter

(1)AddRequestHeader GatewayFilter:相当于是给匹配到路由的request,添加Header

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          # uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          filters:
            - AddRequestHeader=X-Request-red, blue
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由
@GetMapping(value = "/payment/get/{id}")
public CommonResult<Payment> getPaymentById(HttpServletRequest request, @PathVariable("id") Long id) {
    String header = request.getHeader("X-Request-red");
    System.out.println(header);
    Payment payment = paymentMapper.selectById(id);
    log.info("*****查询结果:{}", payment);
    if (payment != null) {
        return new CommonResult(200, "查询成功, 服务端口:" + serverPort, payment);
    } else {
        return new CommonResult(444, "没有对应记录,查询ID: " + id + ",服务端口:" + serverPort, null);
    }
}

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关

(2)The RequestRateLimiter GatewayFilter Factory:通过这个Filter就可以利用redis来完成限流

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关

通过上面示例足以明白Filter的作用,官方提供了30多种Filter,如果有针对于单个路由需要过滤的,可以上官网查看,看看哪个符合自己的使用场景直接使用即可。

注意:下面这两种filters写法是等价的!

spring:
  cloud:
    gateway:
      routes:
      - id: setstatus_route
        uri: https://example.org
        filters:
        - name: AddRequestHeader
          args:
            status: X-Request-red, blue
      - id: setstatusshortcut_route
        uri: https://example.org
        filters:
        - AddRequestHeader=X-Request-red, blue

4.3. 自定义全局过滤器

全局过滤器到底什么时候用?

利用全局过滤器我们可以用来做统一网关鉴权,以及全局日志记录等等。

怎么用?

实现implements GlobalFilter, Ordered两个接口,然后重写两个方法即可。一个是filter方法,一个是getOrder方法。全局过滤器可以存在多个,多个的时候根据getOrder方法的返回值大小就行排序执行,数字最小的过滤器优先执行。

@Component //必须加,必须加,必须加
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("time:" + new Date() + "\t 执行了自定义的全局过滤器: " + "MyLogGateWayFilter" + "hello");

        String uname = exchange.getRequest().getQueryParams().getFirst("uname");
        if (uname == null) {
            System.out.println("****用户名为null,无法登录");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        // 这个就是继续执行的意思
        return chain.filter(exchange);
    }

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

假如我请求没有写到uname的参数,这时候直接406!

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关

带上之后访问成功!

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关

除了以上常用的全局过滤器外,官网还提供了很多,比如Netty全局过滤器,websocket全局过滤器,这些基本上很少会用到,真正用到的时候看官网即可。

以下示例分别显示了如何设置全局前置和后置过滤器:其实还是基于全局过滤器,只不过展现的方式不一样了,这里是直接通过bean注解来注入到容器,然后使用的是匿名类。注释掉的代码是官网给的案例!

@Configuration
public class GateWayFilter {

    @Bean
    public GlobalFilter customGlobalFilter() {
//        return (exchange, chain) -> exchange.getPrincipal()
//                .map(Principal::getName)
//                .defaultIfEmpty("Default User")
//                .map(userName -> {
//                    //adds header to proxied request
//                    exchange.getRequest().mutate().header("CUSTOM-REQUEST-HEADER", userName).build();
//                    return exchange;
//                })
//                .flatMap(chain::filter);
        return new GlobalFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                System.out.println("请求前执行,这里可以放请求前的逻辑");
                exchange.getRequest().mutate().header("CUSTOM-REQUEST-HEADER", "lisi").build();
                return chain.filter(exchange);
            }
        };
    }

    @Bean
    public GlobalFilter customGlobalPostFilter() {
//              return (exchange, chain) -> chain.filter(exchange)
//                .then(Mono.just(exchange))
//                .map(serverWebExchange -> {
//                    //adds header to response
//                    serverWebExchange.getResponse().getHeaders().set("CUSTOM-RESPONSE-HEADER",
//                            HttpStatus.OK.equals(serverWebExchange.getResponse().getStatusCode()) ? "It worked" : "It did not work");
//                    return serverWebExchange;
//                })
//                .then();

        return new GlobalFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                return chain.filter(exchange).then(Mono.just(exchange)).map(serverWebExchange -> {
                    System.out.println("请求后执行,这里是当网关拿到转发服务的请求响应后会执行");
                    //adds header to response
                    serverWebExchange.getResponse().getHeaders().set("CUSTOM-RESPONSE-HEADER",
                            HttpStatus.OK.equals(serverWebExchange.getResponse().getStatusCode()) ? "It worked" : "It did not work");
                    return serverWebExchange;
                }).then();
            }
        };
    }
}

4.4. 实现指定路由跳过全局过滤器

在Spring Cloud Gateway中GlobalFilter可以方便的全局拦截或统计,有时候希望在某些路由中可以跳过GlobalFilter,可以通过GatewayFilter与GlobalFilter组合来实现。

1.GlobalFilter全局过滤器如下

@Component //必须加,必须加,必须加
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        if (exchange.getAttribute(IgnoreGlobalFilterFactor.ATTRIBUTE_IGNORE_GLOBAL_FILTER) != null) {
            return chain.filter(exchange);
        }
        System.out.println("1111111111");
        // 这个就是继续执行的意思
        return chain.filter(exchange);
    }

    /**
     * 这里假如设置1的话,他会优先于IgnoreGlobalFilterFactor过滤器,
     * 我们主要要依靠IgnoreGlobalFilterFactor过滤器来进行赋值,然后全局过滤器根据赋值没赋值决定执行不执行过滤器
     * 所以一定要保证IgnoreGlobalFilterFactor要比全局拦截器执行早,那么我们全局过滤器的这个order数值就要设置的大一点
     * @return
     */
    @Override
    public int getOrder() {
        return 10;
    }
}

2.自定义GatewayFilter

@Component
public class IgnoreGlobalFilterFactor extends AbstractGatewayFilterFactory<IgnoreGlobalFilterFactor.Config> {

    public static final String ATTRIBUTE_IGNORE_GLOBAL_FILTER = "@ignoreGlobalFilter";

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

    @Override
    public GatewayFilter apply(Config config) {
        return this::filter;
    }

    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        exchange.getAttributes().put(ATTRIBUTE_IGNORE_GLOBAL_FILTER, true);
        return chain.filter(exchange);
    }

	// 这个名称就是yml当中设置的名称,也就是这个过滤器会去yml当中获取,看看有在filters当中设置IgnoreGlobalFilter,如果设置了执行,执行相当于是赋值了一下,然后在全局过滤器根据是否能拿到这个值来决定是否跳过过滤器
    @Override
    public String name() {
        return "IgnoreGlobalFilter";
    }

    public static class Config {
    }
}

3.yml配置

IgnoreGlobalFilter这个就是我们自定义的,假如哪个路由要跳过直接在filters当中设置即可。

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          # uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          filters:
            - IgnoreGlobalFilter
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由

五、Http超时配置

5.1. 全局超时

  • connect-timeout必须以毫秒为单位指定。
  • response-timeout必须指定为 java.time.Duration
spring:
  cloud:
    gateway:
      httpclient:
        connect-timeout: 1000
        response-timeout: 5s

一旦路由转发的请求,在返回response超过了5s,网关服务会直接返回给客户单504!

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关

假如单个路由的不想受全局超时限制可以这样做

  - id: per_route_timeouts
    uri: https://example.org
    predicates:
      - name: Path
        args:
          pattern: /delay/{timeout}
    metadata:
      response-timeout: -1

5.2. 每条路由超时

  - id: per_route_timeouts
    uri: https://example.org
    predicates:
      - name: Path
        args:
          pattern: /delay/{timeout}
    metadata:
      response-timeout: 200
      connect-timeout: 200

六、执行器API

所谓的执行器API就是端点监控。Gateway给我们提供了大量的API,我们可以通过接口的形式访问到当前网关的路由以及Filter等状态信息。

1.要引入actuator依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

2.开启执行器API

management:
  endpoint:
    gateway:
      enabled: true
  endpoints:
    web:
      exposure:
        include: gateway

这样就可以通过api来直接访问了,具体有哪些API我们可以参照官网来看。

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关

七、故障排除-日志级别

logging:
  level:
    org.springframework.cloud.gateway: trace

开启之后只要是通过网关调用服务都会有如下日志!

gateway,# SpringCloudAlibaba,gateway,java,spring cloud,网关文章来源地址https://www.toymoban.com/news/detail-813280.html

到了这里,关于Gateway网关简介以及使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SpringCloudAlibaba之Gateway

    1、简介         网关是系统唯一对外的入口,介于客户端与服务器端之间,用于对请求进行鉴权、限流、路由、监控等功能。 2、Gateway主要功能 2.1、 route 路由 路由是网关的最基本组成,由一个路由 id、一个目标地址 url,一组断言工厂及一组 filter 组成。若断言为 true,

    2024年01月19日
    浏览(37)
  • Gateway服务网关使用教程

    目录 1.为什么需要网关 2.gateway快速入门 1)创建gateway服务,引入依赖 2)编写启动类 3)编写基础配置和路由规则 4)重启测试 5)网关路由的流程图 3.断言工厂 4.过滤器工厂 4.1.路由过滤器的种类 4.2.请求头过滤器 4.3.默认过滤器 4.4.总结 5.全局过滤器 5.1.全局过滤器作用 5.2.自

    2024年02月09日
    浏览(52)
  • SpringCloudAlibaba Gateway(一)简单集成

    随着服务模块的增加,一定会产生多个接口地址,那么客户端调用多个接口只能使用多个地址,维护多个地址是很不方便的,这个时候就需要统一服务地址。同时也可以进行统一认证鉴权的需求。那么服务网关就充当这样的角色。 Gateway ​ 网关为众多微服务挡在前面,做路由

    2024年02月10日
    浏览(41)
  • 【SpringCloud Gateway】SpringCloud各微服务之间用户登录信息共享的实现思路——gateway网关token校验以及向微服务发送请求携带token

            最近在学习SpringCloud项目时,想到了一些问题,各个微服务分别部署在不同的服务上,由naocs作为注册中心实现负载均衡,彼此之间通过Feign相互调用通信,信息同步并不像单体项目那样方便,传统单体项目的登录验证方式似乎在SpringCloud中不能满足项目的需求。那么

    2024年02月05日
    浏览(47)
  • 网关Gateway过滤器的使用

    前言: 最近在学习微服务相关的知识,看了黑马的相关课程,将关于Gateway过滤器的知识又总结了一些,希望能帮到各位小伙儿们以及加深下自己的印象🎊 如果文章有什么需要改进的地方还请大佬多多指教🥂 小威先感谢大家的支持了😁 Gateway网关的过滤器分为两种,一种是

    2023年04月09日
    浏览(49)
  • SpringCloud-Gateway网关的使用

    本文介绍如何再 SpringCloud 项目中引入 Gateway 网关并完成网关服务的调用。Gateway 网关是一个在微服务架构中起到入口和路由控制的关键组件。它负责处理客户端请求,进行路由决策,并将请求转发到相应的微服务。Gateway 网关还可以实现负载均衡、安全认证、日志记录等功能

    2024年02月22日
    浏览(37)
  • 如何使用 Gateway 搭建网关服务及实现动态路由?

    网关作为微服务中非常重要的一部分,是必须要掌握的;本文记录一下我是如何使用Gateway搭建网关服务及实现动态路由的,帮助大家学习如何快速搭建一个网关服务,了解路由相关配置,鉴权的流程及业务处理,有兴趣的一定看到最后,非常适合没接触过网关服务的同学当作

    2024年02月09日
    浏览(60)
  • 网关 GateWay 的使用详解、路由、过滤器、跨域配置!

    SpringCloudGateway网关是所有微服务的统一入口。 1.1 它的主要作用是: 反向代理(请求的转发) 路由和负载均衡 身份认证和权限控制 对请求限流 1.2 相比于Zuul的优势: SpringCloudGateway基于Spring5中提供的WebFlux,是一种响应式编程的实现,性能更加优越。 Zuul的实现方式比较老式

    2024年02月07日
    浏览(60)
  • 网关 GateWay 的使用详解、路由、过滤器、跨域配置

    SpringCloudGateway网关是所有微服务的统一入口。 1.1 它的主要作用是: 反向代理(请求的转发) 路由和负载均衡 身份认证和权限控制 对请求限流 1.2 相比于Zuul的优势: SpringCloudGateway基于Spring5中提供的WebFlux,是一种响应式编程的实现,性能更加优越。 Zuul的实现方式比较老式

    2024年02月14日
    浏览(56)
  • 【Spring Cloud】深入探索统一网关 Gateway 的搭建,断言工厂,过滤器工厂,全局过滤器以及跨域问题

    在微服务架构中,网关是至关重要的组件,具有多重职责,为整个系统提供了一系列关键功能。从下面的微服务结构图中,我们可以明确网关的几项主要作用: 微服务结构图: 请求过滤与安全: 用户的所有请求首先经过网关,这使得网关成为系统的第一道防线。通过对传入

    2024年02月07日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包