Spring Cloud 面试题——Spring Cloud Gateway

news2025/1/16 15:48:22

目录

  • 1.什么是 API 网关?有什么作用?
  • 2.有哪些常见的网关?
  • 3.什么是 Spring Cloud Gateway?有什么作用?有什么优缺点?
  • 4.✨Spring Cloud Gateway 的工作流程是什么样的?
  • 5.✨Spring Cloud Gateway 中的路由 (Route) 是指什么?它由哪几部分组成?
  • 6.Spring Cloud Gateway 中的断言 (Predicate) 是指什么?有哪些内置断言?
  • 7.在 Spring Cloud Gateway 中如何自定义断言?
  • 8.Spring Cloud Gateway 中的路由和断言是什么关系?
  • 9.Spring Cloud Gateway 中的过滤器 (Filter) 是指什么?有哪些过滤器?
    • 9.1.概述
    • 9.2.分类
      • 9.2.1.请求和响应
      • 9.2.2.作用范围
  • 10.在 Spring Cloud Gateway 中如何自定义过滤器?
    • 10.1.自定义全局过滤器
    • 10.2.自定义局部过滤器
  • 11.在 Spring Cloud Gateway 如何自定义全局异常处理?
  • 12.如何使用 Spring Cloud Gateway 进行限流?
    • 12.1.使用 RequestRateLimiter 过滤器
    • 12.2.结合 Sentinel 进行限流

参考:
Spring Cloud Gateway 介绍
6000 字 | 16 图 | 深入理解 Spring Cloud Gateway 的原理
Spring Cloud Gateway 官方文档
SpringCloud 网关组件 Gateway 原理深度解析

1.什么是 API 网关?有什么作用?

(1)API 网关是一个在分布式系统中作为入口的服务器,用于接收所有外部请求,并将这些请求路由到相应的服务端节点上。它是构建微服务架构中的关键组件之一。

(2)API 网关的作用如下:

  • 聚合和转发请求:API 网关接收来自客户端的请求,并根据路由规则将请求转发到正确的后端服务。它可以聚合多个微服务的接口调用,从而简化客户端的请求流程,提高性能和可靠性。
  • 负载均衡:通过在网关层实现负载均衡算法,将请求分发到后端的多个服务实例上,实现请求的平衡和分散,提高系统的并发处理能力和容错能力。
  • 认证和授权:API 网关可以作为认证和授权的入口,对请求进行身份验证和权限校验。它可以通过集成身份验证机制(如 OAuth、JWT 等)实现用户认证,以及通过配置访问控制规则来授权访问。
  • 缓存和性能优化:API 网关可以缓存部分经常请求的结果,从而减轻服务器端的负载,提高系统的响应速度和性能。
  • 安全防护:API 网关可以对请求进行安全检查和过滤,防止恶意请求和攻击,保护后端服务的安全和稳定。
  • 监控和日志:API 网关可以对请求进行统一的监控和日志记录,帮助开发者了解系统的运行情况,进行故障排查和性能优化。

(3)总之,API 网关充当了微服务架构中客户端后端服务之间的中间层集中管理和解耦了微服务的接入和治理。它提供了路由转发、负载均衡、认证授权、缓存和性能优化等功能,简化了系统的复杂性,提供了安全性、可靠性和可扩展性,是构建高效、可靠的分布式系统的重要组件。

2.有哪些常见的网关?

(1)以下是几个常见的网关系统:

  • Spring Cloud Gateway:Spring Cloud Gateway 是基于 Spring Framework 5、Spring Boot 2 和 Project Reactor 等技术构建的网关系统。它提供了路由、过滤、负载均衡、熔断、限流等功能,可以作为微服务架构中的统一入口,实现请求的转发和管理。Spring Cloud Gateway 是一个轻量级的网关解决方案,易于集成和扩展。
  • Netflix Zuul:Zuul 是由 Netflix 开发的网关系统,属于 Netflix OSS(Open Source Software)家族的一员。它提供了路由、过滤、负载均衡等功能,可以与 Eureka、Ribbon、Hystrix 等 Netflix 开源组件集成使用。Zuul 1.x 版本基于 Servlet 技术栈实现,而 Zuul 2.x 版本采用了 Netty 作为底层实现。
  • Kong:Kong 是一个快速、可扩展和分布式的开源 API 网关,它基于 Nginx 构建,并提供了管理界面和插件系统。Kong 支持动态路由、认证授权、限流、监控等功能,可以与多种后端服务(如微服务、数据库等)进行集成,使用方便简单。

(2)以上是一些常见的网关系统,它们都提供了类似的基本功能,包括路由转发、负载均衡、认证授权、限流、监控等。选择适合自身需求的网关系统时,可以根据具体的技术栈、性能要求、可扩展性和社区支持等因素进行评估和选择。

3.什么是 Spring Cloud Gateway?有什么作用?有什么优缺点?

(1)Spring Cloud Gateway 属于 Spring Cloud 生态中的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。它的目标是替代 Netflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控和限流。

(2)Spring Cloud Gateway的主要作用如下:

  • 路由转发:Spring Cloud Gateway 可以根据配置的路由规则将请求转发到相应的后端服务。它支持根据请求的 URI、请求头、请求参数等信息进行路由匹配和转发,实现动态的服务路由。
  • 过滤器功能:Spring Cloud Gateway 提供了一套强大的过滤器机制,可以灵活地对请求进行预处理、后处理和过滤。开发者可以通过自定义过滤器来实现请求的验证、参数校验、请求日志、安全处理等功能。
  • 负载均衡:Spring Cloud Gateway集成了多种负载均衡器,如 Netflix RibbonSpring Cloud LoadBalancer。它可以根据负载均衡算法将请求均匀地分发到后端的多个服务实例上,提高系统的并发处理能力和容错能力。
  • 动态路由配置:Spring Cloud Gateway 支持动态的路由配置,可以通过微服务注册中心(如 Eureka、Consul 等)或统一的配置中心(如Spring Cloud Config)实现动态路由的更新和发布,无需重启网关服务。
  • 集成 Spring Cloud 生态系统:Spring Cloud Gateway 可以与其他 Spring Cloud 组件无缝集成,如 Spring Cloud Config、Spring Cloud Discovery(如 Eureka、Consul)和 Spring Security 等,实现统一的配置管理、服务注册与发现、安全认证等。

(3)Spring Cloud Gateway 的优缺点如下:

  • 优点:
    • 性能强劲:是第一代网关 Zuul 的 1.6 倍;
    • 功能强大:内置了很多实用的功能,例如转发、监控、限流等;
    • 设计优雅,容易扩展;
  • 缺点:
    • 其实现依赖 Netty 与 WebFlux,不是传统的 Servlet 编程模型,学习成本高;
    • 不能将其部署在 Tomcat、Jetty 等 Servlet 容器里,只能打成 jar 包执行;
    • Spring Boot 2.0 及以上的版本才支持 Spring Cloud Gateway;

4.✨Spring Cloud Gateway 的工作流程是什么样的?

Spring Cloud Gateway 的工作流程如下图所示,具体步骤为:

  • 请求发送:客户端向 Spring Cloud Gateway(下面称为网关)发送请求;
  • 路由判断;当请求到达网关后,先由 Gateway Handler Mapping 进行处理,确定与该请求匹配的路由,该路由会映射到后端的某个服务,此外还会根据路由断言来判断路由是否可用;
  • 请求过滤:断言成功后请求会到达 Gateway Web Handler,这里面有很多过滤器,并组成过滤器链 (Filter Chain),这些过滤器可以对请求进行拦截和修改,例如修改请求和响应、做权限验证、添加请求日志等操作,然后将请求转发到实际的后端服务。
  • 服务处理:后端服务接收到请求,并进行具体的业务处理;
  • 响应过滤:后端将处理得到的结果返回给网关,网关再次通过一系列的过滤器对响应进行各种过滤操作;
  • 响应返回:响应经过过滤处理后,最终被网关返回给客户端。
    在这里插入图片描述

上述图片来源于 Spring 官网

5.✨Spring Cloud Gateway 中的路由 (Route) 是指什么?它由哪几部分组成?

在 Spring Cloud Gateway 中,路由 (Route) 是定义请求转发规则的对象。它指定了接收到的请求应该如何进行路由,并将请求转发到指定的目标服务。一个路由由以下几个要素组成:

  • id:作为路由的唯一标识符,可以用于配置和管理路由。
  • uri:指定请求要转发的目标服务的地址。可以是一个完整的 URL,也可以是一个注册在服务注册中心的服务名。
  • predicates:用于匹配请求的一系列条件,如果请求满足所有的匹配条件,它将会被路由到该路由所指定的目标 URI。
  • filters:用于在请求被路由之前或之后对请求进行处理和修改的组件。过滤器可以对请求进行增强、校验、修改和校验等操作。
  • order:用于多个 Route 之间的排序,数值越小排序越靠前,匹配优先级越高。

(2)以下是一个路由的示例配置:

spring:
  cloud:
    gateway:
      routes:
        - id: example_route
          uri: http://example.com
          predicates:
            - Path=/example/**
          filters:
            - AddRequestHeader=X-Request-Id, 1234567890
          order: 1 

在上述示例中,我们定义了一个 id 为 example_route 的路由,将匹配到路径为 /example/** 的请求转发到 http://example.com。同时,还使用了一个过滤器,将请求头 X-Request-Id 添加到请求中,值为 1234567890

(3)通过路由的配置,Spring Cloud Gateway 能够根据请求的路径、请求头、请求方法等条件进行请求的转发和过滤。你可以根据具体的业务需求配置不同的路由来实现灵活的请求路由和转发策略。

6.Spring Cloud Gateway 中的断言 (Predicate) 是指什么?有哪些内置断言?

(1)在 Spring Cloud Gateway 中,断言 (Predicate) 用于定义路由规则的匹配条件。它是一个逻辑函数,可以根据请求的特性进行条件判断,以确定是否匹配该路由规则

(2)断言的主要作用在于路由匹配,即通过断言对请求的特征进行匹配,确定是否满足该路由规则的条件。常用的断言条件包括请求的 URI、请求的方法、请求的头信息、请求的参数等。只有当请求满足断言的条件时,才会进一步考虑该路由规则的转发

(3)在配置断言时,可以使用多个断言组合,通过逻辑运算符(如AND、OR、NOT)来定义更复杂的路由规则。常见的内置断言如下:

在这里插入图片描述

上述图片来源于网络。

下面是一个示例:

在这里插入图片描述

(4)需要注意的是,断言的选择和配置需要结合具体的业务需求和场景来进行,合理定义条件判断能够提高路由的准确性和效率。同时,过多或过于复杂的断言条件可能会导致路由规则的维护和管理复杂化,因此需要根据实际情况进行权衡和选择。

7.在 Spring Cloud Gateway 中如何自定义断言?

要实现自定义断言,需要创建一个继承了 AbstractRoutePredicateFactory 类的路由断言工厂类,并完成相关配置和逻辑处理。然后,将该自定义断言添加到路由配置中。具体细节如下:

  • 创建自定义的路由断言工厂类 AgeRoutePredicateFactory
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

/*
	这是一个自定义的路由断言工厂类,要求有两个:
	1.名字必须是 配置+RoutePredicateFactory
	2.必须继承 AbstractRoutePredicateFactory<配置类>
*/
@Component
public class AgeRoutePredicateFactory extends AbstractRoutePredicateFactory<AgeRoutePredicateFactory.Config> {

    //构造函数
    public AgeRoutePredicateFactory() {
        super(AgeRoutePredicateFactory.Config.class);
    }

    //读取配置文件的中参数值,并将其赋值到配置类中的属性上
    public List<String> shortcutFieldOrder() {
        //这个位置的顺序必须跟配置文件中的值的顺序对应
        return Arrays.asList("minAge", "maxAge");
    }

    //断言逻辑
    public Predicate<ServerWebExchange> apply(AgeRoutePredicateFactory.Config config) {
        return new Predicate<ServerWebExchange>() {
            @Override
            public boolean test(ServerWebExchange serverWebExchange) {
                //1.接收前台传入的 age 参数
                String ageStr = serverWebExchange.getRequest().getQueryParams().getFirst("age");
                //2.先判断是否为空
                if (StringUtils.isNotEmpty(ageStr)) {
                    //3.如果不为空,再进行路由逻辑判断
                    int age = Integer.parseInt(ageStr);
                    return age <= config.getMaxAge() && age >= config.getMinAge();
                }
                return false;
            }
        };
    }

    //配置类,用于接收配置文件中的对应参数
    @Data
    @NoArgsConstructor
    public static class Config {
        private int minAge; // 18
        private int maxAge; // 60
    }
}
  • 在配置文件中,添加一个 Age 的断言配置,要求请求中的 age 在 18 ~ 60 之间:

在这里插入图片描述

8.Spring Cloud Gateway 中的路由和断言是什么关系?

路由和断言之间的关系如下:

  • 一对多:一个路由规则可以包含多个断言;
  • 同时满足:如果一个路由规则中有多个断言,则需要同时满足才能匹配;
  • 第一个匹配成功:如果一个请求可以匹配多个路由,则映射第一个匹配成功的路由;

9.Spring Cloud Gateway 中的过滤器 (Filter) 是指什么?有哪些过滤器?

9.1.概述

(1)在Spring Cloud Gateway中,过滤器 (Filter) 是用于在请求路由过程中对请求和响应进行处理和修改的组件。过滤器可以在请求被路由到目标服务之前或之后执行一些操作,如校验请求、修改请求头、记录日志、添加认证等。

9.2.分类

9.2.1.请求和响应

请求和响应的角度来划分,过滤器可以以下两种:

  • Pre 类型:在请求被转发到微服务之前,对请求进行拦截和修改,例如参数校验、权限校验、流量监控、日志输出以及协议转换等操作。
  • Post 类型:微服务处理完请求后,返回响应给网关,网关可以再次进行处理,例如修改响应内容或响应头、日志输出、流量监控等。

9.2.2.作用范围

作用范围的角度来划分,过滤器可以以下两种:

(1)全局过滤器 (Global Filter):全局过滤器对所有的路由都生效,可以用于实现全局的请求处理逻辑。常见的全局过滤器如下所示:
在这里插入图片描述

全局过滤器最常见的用法是进行负载均衡。配置如下所示:

spring:
  cloud:
    gateway:
      routes:
        - id: product_route				# 第三方微服务路由规则
          uri: lb://service-product 	# 负载均衡,将请求转发到注册中心注册的 service-product 服务
          predicates: 
            - Path=/product-serv/** 
          filters: #过滤器
            - StripPrefix=1   # 转发之前去掉 1 层路径(这里是去掉 /product-serv)

这里有个关键字 lb,用到了全局过滤器 LoadBalancerClientFilter,当匹配到这个路由后,会将请求转发到 service-product 服务,且支持负载均衡转发,也就是先将 service-product 解析成实际的微服务的 host 和 port,然后再转发给实际的微服务。

(2)局部过滤器 (Gateway Filter):路由过滤器只对指定的路由生效,可以用于实现对特定路由的请求处理逻辑。常见的局部过滤器如下所示:

在这里插入图片描述

10.在 Spring Cloud Gateway 中如何自定义过滤器?

10.1.自定义全局过滤器

(1)内置的过滤器已经可以完成大部分的功能,但是对于企业开发的一些业务功能处理,还是需要我们自己编写过滤器来实现的,那么我们一起通过代码的形式自定义一个过滤器,去完成统一的权限校验。开发中的鉴权逻辑如下:

  • 当客户端第一次请求服务时,服务端对用户进行信息认证(登录);
  • 认证通过,将用户信息进行加密形成 token,返回给客户端,作为登录凭证;
  • 以后每次请求,客户端都携带认证的 token;
  • 服务端对 token 进行解密,判断是否有效;

在这里插入图片描述

(2)如上图,对于验证用户是否已经登录鉴权的过程可以在网关统一检验。检验的标准就是请求中是否携带 token 凭证以及 token 的正确性。下面的我们自定义一个 GlobalFilter,去校验所有请求的请求参数中是否包含“token”,如何不包含请求参数“token”则不转发路由,否则执行正常的逻辑。

package com.itheima.filters;

import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

//自定义全局过滤器,作用是统一鉴权,需要实现 GlobalFilter 和 Ordered 接口
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {

    //完成判断逻辑
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getQueryParams().getFirst("token");
        if (!StringUtils.equals(token, "admin")) {
            System.out.println("鉴权失败");
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        //调用 chain.filter 继续向下游执行
        return chain.filter(exchange);
    }

    //顺序,数值越小,优先级越高
    @Override
    public int getOrder() {
        return 0;
    }
}

10.2.自定义局部过滤器

要实现自定义局部过滤器,需要创建一个继承了 AbstractGatewayFilterFactory 类的过滤器工厂类,并完成相关配置和逻辑处理。然后,将该自定义自定义局部过滤器添加到路由配置中。具体细节如下:

  • 创建自定义的过滤器工厂类 LogGatewayFilterFactory
package com.itheima.filters;

import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.List;

//自定义局部过滤器
@Component
public class LogGatewayFilterFactory
        extends AbstractGatewayFilterFactory<LogGatewayFilterFactory.Config> {

    //构造函数
    public LogGatewayFilterFactory() {
        super(LogGatewayFilterFactory.Config.class);
    }

    //读取配置文件中的参数,并将其赋值到配置类中
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("consoleLog", "cacheLog");
    }

    //过滤器逻辑
    @Override
    public GatewayFilter apply(LogGatewayFilterFactory.Config config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                if (config.isCacheLog()) {
                    System.out.println("cacheLog 已经开启了....");
                }
                if (config.isConsoleLog()) {
                    System.out.println("consoleLog 已经开启了....");
                }
                return chain.filter(exchange);
            }
        };
    }

    //配置类,用于接收配置参数
    @Data
    @NoArgsConstructor
    public static class Config {
        private boolean consoleLog;
        private boolean cacheLog;
    }
}
  • 在配置文件中,添加一个 Log 的过滤器配置:

在这里插入图片描述

11.在 Spring Cloud Gateway 如何自定义全局异常处理?

(1)在 SpringBoot 项目中,我们捕获全局异常只需要在项目中配置 @RestControllerAdvice@ExceptionHandler 就可以了。不过,这种方式在 Spring Cloud Gateway 下不适用。Spring Cloud Gateway 中实现自定义全局异常常用的一种方式是实现 ErrorWebExceptionHandler 接口并重写其中的 handle 方法。下面是一个示例:

@Component
public class GlobalExceptionHandler implements ErrorWebExceptionHandler {

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        // 自定义异常处理逻辑
        // ...
    }
}

(2)需要注意的是,Spring Boot 中的全局异常处理器可以返回 ResponseEntity 或直接通过 @ResponseBody 返回响应体,而 Spring Cloud Gateway 的全局异常处理则需要返回 Mono<Void> 作为响应结果。这么设计是因为 Spring Cloud Gateway 是基于响应式编程模型构建的,响应是通过异步的方式处理的,因此需要返回 Mono 或 Flux 作为响应。另外,Spring Cloud Gateway 的异常处理还与 ServerWebExchange 对象有关,你可以通过该对象获取到请求和响应的相关信息。

(3)需要注意的是,Spring Cloud Gateway 使用 ErrorWebExceptionHandler 来处理异常,而不是 @ExceptionHandler 注解。这是因为 Spring Cloud Gateway 处理请求的过程是一个管道的形式,异常可能会在不同的过滤器中抛出,需要一个统一的异常处理器来处理这些异常。

(4)总结起来,Spring Boot 和 Spring Cloud Gateway 的全局异常处理方式有所不同,主要是基于各自的Web框架特性和响应式编程模型的需求而设计。

相关知识点:
Spring Boot 面试题——全局异常处理

12.如何使用 Spring Cloud Gateway 进行限流?

12.1.使用 RequestRateLimiter 过滤器

Spring Cloud Gateway 内置了一个 RequestRateLimiter 过滤器,可以基于令牌桶算法实现请求的限流。你可以在路由配置中使用该过滤器来实现限流功能。示例如下:

spring:
  cloud:
    gateway:
      routes:
        - id: example_route
          uri: http://example.com
          predicates:
            - Path=/example/**
          filters:
            - RequestRateLimiter=10

以上示例中,example_route 路由使用了 RequestRateLimiter 过滤器,每秒最多处理 10 个请求

12.2.结合 Sentinel 进行限流

(1)Sentinel 支持对 Spring Cloud Gateway、Zuul 等主流网关进行限流,并且从 1.6.0 版本开始,Sentinel 提供了 Spring Cloud Gateway 的适配模块,可以提供两种资源维度的限流:

  • Route 维度:即在 Spring 配置文件中配置的路由条目,资源名为对应的 Route Id;
  • 自定义 API 维度:用户可以利用 Sentinel 提供的 API 来自定义一些 API 分组

(2)具体步骤如下:

  • 导入依赖
<dependency>
	<groupId>com.alibaba.csp</groupId>
	<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>
  • 编写配置类:基于 Sentinel 的 Spring Cloud Gateway 限流是通过其提供的过滤器来完成的,使用时只需注入对应的 SentinelGatewayFilter 实例以及 SentinelGatewayBlockExceptionHandler 实例即可。
@Configuration
public class GatewayConfiguration {
    private final List<ViewResolver> viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;
    public GatewayConfiguration(ObjectProvider<List<ViewResolver>>
                                        viewResolversProvider,
                                ServerCodecConfigurer serverCodecConfigurer) {
        this.viewResolvers =
                viewResolversProvider.getIfAvailable(Collections::emptyList);
        this.serverCodecConfigurer = serverCodecConfigurer;
    }
    
    // 初始化一个限流的过滤器
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }
    
    // 配置初始化的限流参数
    @PostConstruct
    public void initGatewayRules() {
        Set<GatewayFlowRule> rules = new HashSet<>();
        rules.add(
                new GatewayFlowRule("product_route") //资源名称,对应路由id
                        .setCount(1) // 限流阈值
                        .setIntervalSec(1) // 统计时间窗口,单位是秒,默认是 1 秒
        );
        GatewayRuleManager.loadRules(rules);
    }
    
    // 配置限流的异常处理器
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler
    sentinelGatewayBlockExceptionHandler() {
        return new SentinelGatewayBlockExceptionHandler(viewResolvers,
                serverCodecConfigurer);
    }
    
    // 自定义限流异常页面
    @PostConstruct
    public void initBlockHandlers() {
        BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
            public Mono<ServerResponse> handleRequest(ServerWebExchange
                                                              serverWebExchange, Throwable throwable) {
                Map map = new HashMap<>();
                map.put("code", 0);
                map.put("message", "接口被限流了");
                return ServerResponse.status(HttpStatus.OK).
                        contentType(MediaType.APPLICATION_JSON_UTF8).
                        body(BodyInserters.fromObject(map));
            }
        };
        GatewayCallbackManager.setBlockHandler(blockRequestHandler);
    }
}
  • 自定义 API 分组:自定义 API 分组是一种更细粒度的限流规则定义。
/**
 * 配置初始化的限流参数
 */
@PostConstruct
public void initGatewayRules() {
    Set<GatewayFlowRule> rules = new HashSet<>();
    rules.add(new
            GatewayFlowRule("product_api1").setCount(1).setIntervalSec(1));
    rules.add(new
            GatewayFlowRule("product_api2").setCount(1).setIntervalSec(1));
    GatewayRuleManager.loadRules(rules);
}

//自定义 API 分组
@PostConstruct
private void initCustomizedApis() {
    Set<ApiDefinition> definitions = new HashSet<>();
    ApiDefinition api1 = new ApiDefinition("product_api1")
            .setPredicateItems(new HashSet<ApiPredicateItem>() {{
				//以 /product-serv/product/api1 开头的请求
                add(new ApiPathPredicateItem().setPattern("/product_serv/product/api1/**").
                        setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
            }});
    ApiDefinition api2 = new ApiDefinition("product_api2")
            .setPredicateItems(new HashSet<ApiPredicateItem>() {{
				//以 /product-serv/product/api2/demo1 完成的 url 路径匹配
                add(new ApiPathPredicateItem().setPattern("/product_serv/product/api2/demo1"));
            }});
    definitions.add(api1);
    definitions.add(api2);
    GatewayApiDefinitionManager.loadApiDefinitions(definitions);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/944346.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

百度中文点选验证码研究

之前百度都是只有旋转验证码&#xff0c;最近总是出现中文点选验证码。而且中文数量比较多&#xff0c;大图中有固定的7个中文字符需要识别。 我首先想到使用通用的中文识别&#xff0c;当时我尝试了很多出名的中文识别但是效果都非常差&#xff0c;基本上全错&#xff0c;完全…

解决AD(Altium Designer)导入HFSS的dxf文件只有轮廓,填充的方法

解决Altium Designer导入HFSS的dxf文件只有轮廓&#xff0c;填充的方法 环境操作 环境 Altium Designer (19.0.4) 操作 设计》规则 左键框选 工具》转换》从选择的元素创建铺铜 选好点击apply 多重复几次&#xff0c;就全填充完了。

SQL语句优化

当表中有百万数据的时候&#xff0c;我们要怎么去查询数据&#xff0c;平时写的sql也许就会很慢了。 SQL的执行顺序 SELECT DISTINCT <select_list> FROM <left_table> <join_type> JOIN <right_table> ON <join_condition> WHERE<where_co…

经济大环境不好是你给自己找的理由吗?

最近很多自媒体博主都在说的一个现象&#xff0c;就是今年的经济形势比口罩那几年都要难过&#xff0c;全球的经济都面临打的挑战&#xff0c;就业岗位的缺失&#xff0c;22-35岁的青年失业率攀升很多人都在痛苦的边缘挣扎。 我国灵活就业人数已超2亿&#xff0c;平台经济快速发…

在ros中利用串口serial发布fdilink的gps话题

文章目录 介绍FDILink通讯协议数据帧组成数据包 数据处理打开串口在头文件中定义参数串口读取 代码运用依赖&#xff1a;使用&#xff1a; 源码 介绍 DETA100系列 是一个提供 GNSS/INS & AHRS 系统的模组&#xff0c;在最苛刻的条件下提供准确的位置、速度、加速度和姿态数…

国标GB28181安防监控视频平台EasyGBS新功能:批量绑定角色与取消设备

国标GB28181协议视频平台EasyGBS是基于国标GB28181协议的视频云服务平台&#xff0c;支持多路设备同时接入&#xff0c;并对多平台、多终端分发出RTSP、RTMP、FLV、HLS、WebRTC等格式的视频流。国标视频监控平台可提供视频监控直播、云端录像、云存储、检索回放、智能告警、语音…

多线程(额外扩展)(面试会用)

1 线程状态 1.1 状态介绍 当线程被创建并启动以后&#xff0c;它既不是一启动就进入了执行状态&#xff0c;也不是一直处于执行状态。线程对象在不同的时期有不同的状态。那么Java中的线程存在哪几种状态呢&#xff1f;Java中的线程 状态被定义在了java.lang.Thread.State枚…

中央发文:提高青年人才资助比例, 放宽学历、年龄限制 (附2023国自然资助比例统计)~

8 月 27 日&#xff0c;中共中央办公厅、国务院办公厅印发《关于进一步加强青年科技人才培养和使用的若干措施》&#xff08;以下简称《若干措施》&#xff09;&#xff0c;明确提出包括提高国家自然科学基金对青年科技人才的资助比例&#xff0c;放宽学历、年龄限制等措施&…

五、多表查询-4.5子查询-表子查询

一、概述 子查询返回的结果是多行多列&#xff0c;这种子查询称为表子查询。 常用的操作符&#xff1a;in 经常出现在from之后 二、演示 【例1】查询与“鹿掌客”、“宋院桥”的职位和薪资相同的员工信息 1、查询与“鹿掌客”、“宋院桥”的职位和薪资 返回的结果是一个表…

请问现在开融资融券账户交易佣金利率最低是多少?怎么开户!

请问现在开融资融券账户交易佣金利率最低是多少&#xff1f;怎么开户&#xff01; 融资融资利率没有最低的说法&#xff0c;利率一般都是相对的&#xff0c;融资融券的利率通常约为6%以上&#xff0c;当然这个也会根据市场货币的政策有所变动&#xff0c;比如现在的的货币政策…

极智嘉(Geek+)再获重磅荣誉,持续力领跑智慧物流行业发展

近日&#xff0c;全球仓储机器人引领者极智嘉(Geek)再度传来好消息&#xff0c;凭借着全球化的专业服务能力和稳健增长的亮眼海外成绩&#xff0c;一举荣登“2023出海品牌服务商”价值榜&#xff0c;成为唯一登榜的物流机器人企业。 作为率先出海的物流机器人企业&#xff0c…

如何在VR头显端实现低延迟的RTSP或RTMP播放

技术背景 VR&#xff08;虚拟现实技术&#xff09;给我们带来身临其境的视觉体验&#xff0c;广泛的应用于城市规划、教育培训、工业仿真、房地产、水利电力、室内设计、文旅、军事等众多领域&#xff0c;常用的行业比如&#xff1a; 教育行业&#xff1a;VR头显可以用于教育…

成都瀚网科技:抖店怎么上精选联盟?

在抖音电商平台上&#xff0c;选定的联盟是一个非常重要的入口。对于商家来说&#xff0c;能够进入选定的联盟意味着更多的曝光度和流量&#xff0c;从而获得更好的销售机会。那么&#xff0c;抖店是如何进入精选联盟的呢&#xff1f; 1、抖店如何加入特色联盟&#xff1f; 提供…

arm版Linux下安装es集群

背景&#xff1a;由于生产上网络没通&#xff0c;没办法&#xff0c;只能自己安装一个es集群的测试环境了&#xff0c;我的电脑是Mac M2&#xff0c;安装的Linux是centos7&#xff0c;也是arm版的。 第一步&#xff1a;查看自己Linux系统的版本 命令&#xff1a;uname -a 例如…

用Kubernetes(k8s)的ingress部署https应用

用Kubernetes的ingress部署https应用 环境准备Ingress安装域名证书准备 部署应用通过ingress暴露应用根据ssl证书生成对应的secret创建ingress暴露部署的应用确认自己安装了ingress创建ingress 访问你暴露的应用 环境准备 Ingress安装 我之前有一片文章写的是用ingress暴露应…

揭秘:企业在线帮助中心的一些技巧秘密!

企业在线帮助中心是现代企业为了提供更好的客户服务而建立的一个重要渠道。它可以帮助客户解决问题、获取产品信息和技术支持。在这篇文章中&#xff0c;我将揭秘一些企业在线帮助中心的技巧秘密&#xff0c;希望能够帮助企业提供更好的客户服务。 一、清晰的导航结构 一个清…

js删除字符串中的指定字符串

1. 使用 replace() 方法 replace() 将字符串中的指定子字符串替换为新的字符串。 如果删除指定的子字符串&#xff0c;可以将它替换为空字符串。 var str "Hello, World!";var substringToRemove "World";var newStr str.replace(substringToRemove, &q…

太阳能景观凉亭

丰富的太阳辐射能是重要的能源&#xff0c;是取之不尽、用之不竭的、无污染、廉价、人类能够自由利用的能源。太阳能每秒钟到达地面的能量高达80万千瓦&#xff0c;假如把地球表面0.1%的太阳能转为电能&#xff0c;转变率5%&#xff0c;每年发电量可达5.61012千瓦小时&#xff…

Oatpp编译使用Windows版本----windows搭建http服务器

来源&#xff1a;微信公众号「编程学习基地」 文章目录 一、Oatpp 编译下载源码cmake构建工程Configue配置x64Generate构建项目 VS2019编译项目 二、Oatpp搭建http服务器VS2019创建空项目导入oatpp项目配置 一、Oatpp 编译 下载源码 下载源码&#xff1a;https://github.com…

装备一台ubuntu

问题&#xff1a;linux在执行ifconfig时出现 Command ‘ifconfig‘ not found ,but can be installed with: 这种情况解决方案&#xff08;参考&#xff09; 描述&#xff1a; 1、安装好linux后想查一下ip地址&#xff0c;一查出现了这种情况 2、执行了这个命令&#xff0c;出…