【SpringCloud Alibaba】(九)学习 Gateway 服务网关

news2024/11/14 15:20:53

目录

  • 1、网关概述
    • 1.1、没有网关的弊端
    • 1.2、引入 API 网关
  • 2、主流的 API 网关
    • 2.1、Nginx+Lua
    • 2.2、Kong 网关
    • 2.3、Zuul 网关
    • 2.4、Apache Shenyu 网关
    • 2.5、SpringCloud Gateway 网关
  • 3、SpringCloud Gateway 网关
    • 3.1、Gateway 概述
    • 3.2、Gateway 核心架构
  • 4、项目整合 SpringCloud Gateway 网关
    • 4.1、新建网关模块
    • 4.2、初步整合 Gateway
  • 5、网关 Gateway 整合 Nacos
  • 6、网关 Gateway 整合 Nacos 最简配置
  • 7、网关 Gateway 整合 Sentinel 限流
    • 7.1、实现 route 维度限流
    • 7.2、实现自定义 API 分组维度限流
  • 代码地址

1、网关概述

当采用分布式、微服务的架构模式开发系统中,服务网关是整个系统中必不可少的一部分。

1.1、没有网关的弊端

当一个系统使用分布式、微服务架构后,系统会被拆分为一个个小的微服务,每个微服务专注一个小的业务。那么,客户端如何调用这么多微服务的接口呢?如果不做任何处理,没有服务网关,就只能在客户端记录下每个微服务的每个接口地址,然后根据实际需要去调用相应的接口。如下:

在这里插入图片描述

这种直接使用客户端记录并管理每个微服务的每个接口的方式,存在着太多的问题。比如,这里我列举几个常见的问题:

  • 由客户端记录并管理所有的接口缺乏安全性。
  • 由客户端直接请求不同的微服务,会增加客户端程序编写的复杂性。
  • 涉及到服务认证与鉴权规则时,需要在每个微服务中实现这些逻辑,增加了代码的冗余性。
  • 客户端调用多个微服务,由于每个微服务可能部署的服务器和域名不同,存在跨域的风险。
  • 当客户端比较多时,每个客户端上都管理和配置所有的接口,维护起来相对比较复杂

1.2、引入 API 网关

API 网关,其实就是整个系统的统一入口。网关会封装微服务的内部结构,为客户端提供统一的入口服务,同时,一些与具体业务逻辑无关的通用逻辑可以在网关中实现,比如认证、授权、路由转发、限流、监控等。引入 API 网关后,如下所示:

在这里插入图片描述

可以看到,引入 API 网关后,客户端只需要连接 API 网关,由 API 网关根据实际情况进行路由转发,将请求转发到具体的微服务,同时,API 网关会提供认证、授权、限流和监控等功能。

2、主流的 API 网关

当系统采用分布式、微服务的架构模式后,API 网关就成了整个系统不可分割的一部分。业界通过不断的探索与创新,实现了多种API网关的解决方案。目前,比较主流的API网关有:Nginx + Lua、Kong 网关、Zuul 网关、Apache Shenyu 网关、SpringCloud Gateway 网关。

2.1、Nginx+Lua

Nginx 的一些插件本身就实现了限流、缓存、黑白名单和灰度发布,再加上 Nginx 的反向代理和负载均衡,能够实现对服务接口的负载均衡和高可用。而 Lua 语言可以实现一些简单的业务逻辑,Nginx 又支持 Lua 语言。所以,可以基于 Nginx + Lua 脚本实现网关。

2.2、Kong 网关

Kong 网关基于 Nginx 与 Lua 脚本开发,性能高,比较稳定,提供多个限流、鉴权等插件,这些插件支持热插拔,开箱即用。Kong 网关提供了管理页面,但是,目前基于 Kong 网关二次开发比较困难。

2.3、Zuul 网关

Zuul 网关是 Netflix 开源的网关,功能比较丰富,主要基于 Java 语言开发,便于在 Zuul 网关的基础上进行二次开发。但是 Zuul 网关无法实现动态配置规则,依赖的组件相对来说也比较多,在性能上不如 Nginx。

2.4、Apache Shenyu 网关

Dromara 社区开发的网关框架,ShenYu 的前名是 soul,最近正式加入了 Apache 的孵化器,因此改名为 ShenYu。其是一个异步的,高性能的,跨语言的,响应式的 API 网关,并在此基础上提供了非常丰富的扩展功能:

  • 支持各种语言(http 协议),支持 Dubbo、Spring-Cloud、Grpc、Motan、Sofa、Tars 等协议。
  • 插件化设计思想,插件热插拔,易扩展。
  • 灵活的流量筛选,能满足各种流量控制。
  • 内置丰富的插件支持,鉴权,限流,熔断,防火墙等等。
  • 流量配置动态化,性能极高。
  • 支持集群部署,支持 A/B Test,蓝绿发布

2.5、SpringCloud Gateway 网关

Spring 为了替换 Zuul 而开发的网关,SpringCloud Alibaba 技术栈中,并没有单独实现网关的组件。在后续的案例实现中,我们会使用 SpringCloud Gateway 实现网关功能。

3、SpringCloud Gateway 网关

3.1、Gateway 概述

Spring Cloud Gateway 是 Spring 公司基于 Spring 5.0, Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式

Geteway 作为 Spring Cloud 生态系统中的网关,目标是替代 Zuul,在 Spring Cloud2.0 以上版本中,没有对新版本的 Zuul 2.0 以上最新高性能版本进行集成,仍然还是使用的 Zuul 1.x 非 Reactor 模式的老版本

而为了提升网关性能,Spring Cloud Gateway 是基于 WebFlux 框架实现的,而 WebFlux 框架底
层则使用了高性能的 Reactor 模式通信框架 Netty。

Gateway 的目标提供统一的路由方式且基于 Filter 链的方式提供了网关基本的功能,例如:
安全,监控/指标,和限流

Spring Cloud Gateway 使用的 Webflux 中的 reactor-netty 响应式编程组件,底层使用 Netty 通讯框架

3.2、Gateway 核心架构

客户端请求到 Gateway 网关,会先经过 Gateway Handler Mapping 进行请求和路由匹配。匹配成功后再发送到 Gateway Web Handler 处理,然后会经过特定的过滤器链,经过所有前置过滤后,会发送代理请求。请求结果返回后,最后会执行所有的后置过滤器。如下图:

在这里插入图片描述

SpringCloud Gateway 的主要流程为:客户端请求会先打到 Gateway,具体的讲应该是 DispacherHandler(因为 Gateway 引入了 WebFlux,作用可以类比 MVC 的 DispacherServlet),Gateway 根据用户的请求找到相应的 HandlerMapping,请求和具体的 handler 之间有一个映射关系,网关会对请求进行路由,handler 会匹配到 RoutePredicateHandlerMapping,匹配请求对应的 Route,然后到达 Web 处理器,WebHandler 代理了一系列网关过滤器和全局过滤器的实例,这些过滤器可以对请求和响应进行修改,最后由代理服务完成用户请求,并将结果返回。

4、项目整合 SpringCloud Gateway 网关

4.1、新建网关模块

在项目中新建 shop-gateway 模块,新增网关模块后项目的结构如下图所示:

在这里插入图片描述

4.2、初步整合 Gateway

1、在服务网关 shop-gateway 模块的 pom.xml 文件中添加如下依赖:

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

2、在服务网关 shop-gateway 模块的 resources 目录下新建 application.yml 文件,并在文件中添加如下配置信息:

server:
  port: 10001
spring:
  application:
    name: server-gateway
  cloud:
    gateway:
      globalcors:                       # 配置跨域
        cors-configurations:
          '[/**]':
            allowedOrigins: "*"
            allowedMethods: "*"
            allowCredentials: true
            allowedHeaders: "*"
      routes:                           # 路由配置【数组】
        - id: user-gateway              # 路由 id
          uri: http://localhost:8060    # 路由地址
          order: 1                      # 路由排序,数字越大,优先级越低
          predicates:                   # 断言配置/路由转发的条件【数组】
            - Path=/server-user/**      # 路径匹配:当客户端请求的路径满足 Path 的规则时,进行路由转发操作
          filters:                      # 过滤器配置【数组】
            - StripPrefix=1             # 去掉前缀:去掉客户端请求的路径中的第一个路径,即去掉 /server-user
        - id: product-gateway
          uri: http://localhost:8070
          order: 1
          predicates:
            - Path=/server-product/**
          filters:
            - StripPrefix=1
        - id: order-gateway
          uri: http://localhost:8080
          order: 1
          predicates:
            - Path=/server-order/**
          filters:
            - StripPrefix=1

我们重点来看下 spring.cloud.gateway 节点下的配置。

  • globalcors:此节点下的配置是为了解决 SpringCloud Gateway 跨域的问题。
  • routes:表示一个路由数组,可以在此节点下配置多个路由信息。
  • id:当前路由的唯一标识。
  • order:路由的优先级,数字越小表示优先级越高。
  • predicates:网关断言,也就是路由转发的条件,也是一个数组,可以配置多个路由转发条件。
  • Path:当客户端请求的路径满足 Path 的规则时,进行路由转发操作。
  • filters:网关过滤器,在过滤器中可以修改请求的参数和 header 信息,以及响应的结果和 header 信息,网关过滤器也是一个数组,可以配置多个过滤规则。
  • StripPrefix:网关在进行路由转发之前,会去掉 1 层访问路径

3、在服务网关 shop-gateway 模块的 com.zzc 包下新建 ShopGatewayApplication 类,表示服务网关的启动类,源码如下所示:

@SpringBootApplication
public class ShopGatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(ShopGatewayApplication.class, args);
    }

}

4、由于之前项目中整合了 Nacos 和 Sentinel,所以,在启动项目前,要分别启动 Nacos 和 Sentinel
5、分别启动用户微服务、商品微服务、订单微服务和服务网关。
6、通过服务网关访问用户微服务,在浏览器中输入 http://localhost:10001/server-user/user/get/1001 ,如下所示:

在这里插入图片描述

直接通过用户微服务访问:http://localhost:8060/user/get/1001

7、产品微服务、订单微服务以此类推

5、网关 Gateway 整合 Nacos

在初步整合 SpringCloud Gateway 中,我们在服务网关模块的 application.yml 文件中 硬编码配置了服务转发的地址,如下所示:

  • 硬编码用户微服务地址
uri: http://localhost:8060
  • 硬编码商品微服务地址
uri: http://localhost:8070
  • 硬编码订单微服务地址
uri: http://localhost:8080

这里,我们将网关整合 Nacos 实现从 Nacos 注册中心获取转发的服务地址

1、在服务网关 shop-gateway 模块的 pom.xml 文件中继续添加如下依赖:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2、在服务网关 shop-gateway 模块的启动类上添加 @EnableDiscoveryClient 注解,如下所示:

@SpringBootApplication
@EnableDiscoveryClient
public class ShopGatewayApplication {
	// ...
}

3、将 application.yml 备份一份,命名为 application-simple.yml,并修改 application.yml配置文件,修改后的文件如下所示:

server:
  port: 10001
spring:
  application:
    name: server-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      globalcors:                       # 配置跨域
        cors-configurations:
          '[/**]':
            allowedOrigins: "*"
            allowedMethods: "*"
            allowCredentials: true
            allowedHeaders: "*"
      routes:                           # 路由配置【数组】
        - id: user-gateway              # 路由 id
          uri: lb://server-user         # 路由地址
          order: 1                      # 路由排序,数字越大,优先级越低
          predicates:                   # 断言配置/路由转发的条件【数组】
            - Path=/server-user/**      # 路径匹配:当客户端请求的路径满足 Path 的规则时,进行路由转发操作
          filters:                      # 过滤器配置【数组】
            - StripPrefix=1             # 去掉前缀:去掉客户端请求的路径中的第一个路径,即去掉 /server-user
        - id: product-gateway
          uri: lb://server-product
          order: 1
          predicates:
            - Path=/server-product/**
          filters:
            - StripPrefix=1
        - id: order-gateway
          uri: lb://server-order
          order: 1
          predicates:
            - Path=/server-order/**
          filters:
            - StripPrefix=1
      discovery:
        locator:
          enabled: true                   # 开启服务发现

①:上述配置中增加了 Nacos 相关的配置,如下所示:

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

②:新增了让 SpringCloud Gateway 可以发现 Nacos 中的服务配置,如下所示:

Spring:
 cloud:
   gateway:
     discovery:
       locator:
         enabled: true

③:另外,将硬编码的服务转发地址修改成从 Nacos 中按照名称获取微服务地址,并按照负载均衡策略分发

  • 从 Nacos 中获取用户微服务
uri: lb://server-user
  • 从 Nacos 中获取商品微服务
uri: lb://server-product
  • 从 Nacos 中获取订单微服务
uri: lb://server-order

其中,lb 指的是从 Nacos 中按照微服务的名称获取微服务地址,并按照负载均衡的策略分发。使用 lb从 Nacos 中获取微服务时,遵循如下的格式:

lb: //微服务名称

微服务的名称就是各个微服务在 application.yml 文件中配置的服务名称:

spring:
  application:
    name: 服务名称

4、分别启动用户微服务、商品微服务、订单微服务和服务网关
5、通过服务网关访问用户微服务,在浏览器中输入http://localhost:10001/server-user/user/get/1001 ,如下所示:

在这里插入图片描述

6、网关 Gateway 整合 Nacos 最简配置

SpringCloud Gateway 整合 Nacos 后,可以不用手动指定其他微服务的名称来从 Nacos 中获取微服务的地址。接下来,我们就来实现 SpringCloud Gateway 网关整合 Nacos 的最简配置。

1、将 application.yml 备份一份,命名为 application-nacos.yml,并修改 application.yml 配置文件,修改后的文件如下所示:

server:
  port: 10001
spring:
  application:
    name: server-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      globalcors:                       # 配置跨域
        cors-configurations:
          '[/**]':
            allowedOrigins: "*"
            allowedMethods: "*"
            allowCredentials: true
            allowedHeaders: "*"
      discovery:
        locator:
          enabled: true                 # 开启服务发现

application.yml 文件中,去掉了 spring.cloud.gateway.routes 节点及其下面的所有配置

2、分别启动用户微服务、商品微服务、订单微服务和服务网关
3、通过服务网关访问用户微服务,在浏览器中输入http://localhost:10001/server-user/user/get/1001 ,如下所示:

在这里插入图片描述

注意:SpringCloud Gateway 整合 Nacos 最简配置时,通过网关访问微服务的格式如下所示:

http(s)://网关IP:网关端口/访问的目标微服务名称/接口地址

7、网关 Gateway 整合 Sentinel 限流

Sentinel 从 1.6.0 版本开始,提供了 SpringCloud Gateway 的适配模块,并且可以提供两种资源维度的限流,一种是 route 维度;另一种是自定义 API 分组维度

  • route 维度:对 application.yml文件中配置的 spring.cloud.gateway.routes.id 限流,并且资
    源名为 spring.cloud.gateway.routes.id 对应的值。
  • 自定义 API 分组维度:利用 Sentinel 提供的 API 接口来自定义 API 分组,并且对这些 API 分组进行限流。

7.1、实现 route 维度限流

1、在服务网关 shop-gateway 模块的 pom.xml 文件中添加如下依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>

2、在服务网关 shop-gateway 模块中新建 com.zzc.config 包,并在包下新建 GatewayConfig 类。基于 Sentinel 的 Gateway 限流是通过其提供的 Filter 来完成的,使用时只需注入对应的SentinelGatewayFilter 实例以及 SentinelGatewayBlockExceptionHandler 实例即可。

GatewayConfig 类的源代码如下所示:

@Configuration
public class GatewayConfig {

    private final List<ViewResolver> viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;
    @Value("${spring.cloud.gateway.discovery.locator.route-id-prefix}")
    private String routeIdPrefix;

    public GatewayConfig(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 init() {
        this.initGatewayRules();
        this.initBlockHandlers();
    }

    /**
     * 配置初始化的限流参数
     */
    private void initGatewayRules() {
        Set<GatewayFlowRule> rules = new HashSet<>();
        /**
         * Sentinel整合SpringCloud Gateway使用的API类型为Route ID类型,也就是基于route
         维度时,
         * 由于Sentinel为SpringCloud Gateway网关生成的API名称规则如下:
         * 生成的规则为:${spring.cloud.gateway.discovery.locator.route-id-prefix}
         后面直接加上目标微服务的名称,如下所示。
         * ${spring.cloud.gateway.discovery.locator.route-id-prefix}目标微服务的名
         称
         * 其中,${spring.cloud.gateway.discovery.locator.route-id-prefix}是在yml文
         件中配置的访问前缀
         *
         * 为了让通过服务网关访问目标微服务链接后,请求链路中生成的API名称与流控规则中生成的
         API名称一致,以达到启动项目即可实现访问链接的限流效果,
         * 而无需登录Setinel管理界面手动配置限流规则,可以将
         * resource参数设置为${spring.cloud.gateway.discovery.locator.route-id
         prefix}目标微服务的名称
         *
         * 当然,如果不按照上述配置,也可以在项目启动后,通过服务网关访问目标微服务链接后,在
         Sentinel管理界面的请求链路中找到对应的API名称所代表的请求链路,
         * 然后手动配置限流规则。
         **/
        // 用户微服务网关
        // rules.add(this.getGatewayFlowRule("user-gateway"));
        // 商品微服务网关
        // rules.add(this.getGatewayFlowRule("product-gateway"));
        // 订单微服务网关
        // rules.add(this.getGatewayFlowRule("order-gateway"));
        //用户微服务网关
        rules.add(this.getGatewayFlowRule(getResource("server-user")));
        //商品微服务网关
        rules.add(this.getGatewayFlowRule(getResource("server-product")));
        //订单微服务网关
        rules.add(this.getGatewayFlowRule(getResource("server-order")));
        //加载规则
        GatewayRuleManager.loadRules(rules);
    }

    private String getResource(String targetServiceName){
        if (routeIdPrefix == null){
            routeIdPrefix = "";
        }
        return routeIdPrefix.concat(targetServiceName);
    }

    private GatewayFlowRule getGatewayFlowRule(String resource){
        //传入资源名称生成GatewayFlowRule
        GatewayFlowRule gatewayFlowRule = new GatewayFlowRule(resource);
        //限流阈值
        gatewayFlowRule.setCount(1);
        //统计的时间窗口,单位为
        gatewayFlowRule.setIntervalSec(1);
        return gatewayFlowRule;
    }

    /**
     * 配置限流的异常处理器
     */
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler
    sentinelGatewayBlockExceptionHandler() {
        return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }

    /**
     * 自定义限流异常页面
     */
    private void initBlockHandlers() {
        BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
                Map map = new HashMap<>();
                map.put("code", 1001);
                map.put("codeMsg", "接口被限流了");
                return ServerResponse.status(HttpStatus.OK).
                        contentType(MediaType.APPLICATION_JSON_UTF8).
                        body(BodyInserters.fromObject(map));
            }
        };
        GatewayCallbackManager.setBlockHandler(blockRequestHandler);
    }
}

GatewayConfig 类的源代码看上去比较多,但是都是一些非常简单的方法。

【注意】:Sentinel1.8.4 整合 Gateway 使用的 API 类型为 Route ID 类型时,也就是基于 route 维度时,由于 Sentinel 为 Gateway 网关生成的 API 名称规则如下:${spring.cloud.gateway.discovery.locator.route-id-prefix} 后面直接加上目标微服
务的名称。 其中,${spring.cloud.gateway.discovery.locator.route-id-prefix} 是在 yml 文件中配置的访问前缀。

当然,如果不按照上述配置,也可以在项目启动后,通过服务网关访问目标微服务链接后,在 Sentinel 管理界面的请求链路中找到对应的 API 名称所代表的请求链路,然后手动配置限流规则。

3、将服务网关 shop-gateway 模块的 application.yml 文件备份一份名称为 application-nacos simple.yml 的文件,并将 application.yml 文件的内容修改成如下所示:

server:
  port: 10001
spring:
  application:
    name: server-gateway
  main:
    allow-bean-definition-overriding: true  # 解决重复注册的问题
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    sentinel:
      transport:
        port: 7777
        dashboard: 127.0.0.1:8888
      web-context-unify: false          # 开启 sentinel 的 web 监控
      eager: true                       # 启动时加载所有规则到 Sentinel

    gateway:
      globalcors:                       # 配置跨域
        cors-configurations:
          '[/**]':
            allowedOrigins: "*"
            allowedMethods: "*"
            allowCredentials: true
            allowedHeaders: "*"
      discovery:
        locator:
          enabled: true                 # 开启服务发现
          route-id-prefix: gateway-     # 路由 id 前缀

其中:

  • spring.cloud.sentinel.eager:表示程序启动时,流控规则是否立即注册到 Sentinel,配置为
    true 表示立即注册到 Sentinel。
  • spring.cloud.gateway.discovery.locator.route-id-prefix:生成流控规则 API 名称的前缀

4、在 IDEA 中配置启动服务网关 shop-gateway 模块的参数 -Dcsp.sentinel.app.type=1,如下所示:

在这里插入图片描述

如果是在命令行启动网关服务的 Jar 包,则可以使用如下命令:

java -Dcsp.sentinel.app.type=1 shop-gateway.jar

或者在启动类 的 main() 方法中添加一行System.setProperty("csp.sentinel.app.type", "1"); 代码,如下所示:

public class ShopGatewayApplication {

    public static void main(String[] args) {
        System.setProperty("csp.sentinel.app.type", "1");
        SpringApplication.run(ShopGatewayApplication.class, args);
    }
}

5、分别启动用户微服务、商品微服务、订单微服务和服务网关,启动后会在 Sentinel 管理界面左侧菜单栏中看到 server-gateway 菜单,如下所示:

在这里插入图片描述

server-gateway 菜单下的流控规则子菜单中可以看到网关的流控规则已经注册到 Sentinel,如下所示:

在这里插入图片描述

6、通过服务网关访问用户微服务,在浏览器中输入http://localhost:10001/server-user/user/get/1001 ,不断刷新页面,如下所示:

在这里插入图片描述

可以看到,通过服务网关不断用户订单微服务时,触发了服务限流,并返回了自定义的限流结果数据。

7.2、实现自定义 API 分组维度限流

1、在服务网关 shop-gateway 模块的 com.zzc.config.GatewayConfig 配置类中新增
initCustomizedApis() 方法,初始化 API 管理的信息,源码如下所示:

private void initCustomizedApis() {
	Set<ApiDefinition> definitions = new HashSet<>();
	ApiDefinition api1 = new ApiDefinition("user_api1")
	        .setPredicateItems(new HashSet<ApiPredicateItem>() {{
	            // 以/server-user/user/api1 开头的请求
	            add(new ApiPathPredicateItem().setPattern("/server-user/user/api1/**").
	                    setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
	        }});
	ApiDefinition api2 = new ApiDefinition("user_api2")
	        .setPredicateItems(new HashSet<ApiPredicateItem>() {{
	            // 以/server-user/user/api2/demo1 完成的url路径匹配
	            add(new ApiPathPredicateItem().setPattern("/server-user/user/api2/demo1"));
	        }});
	definitions.add(api1);
	definitions.add(api2);
	GatewayApiDefinitionManager.loadApiDefinitions(definitions);
}

上述代码中,配置了两个 API 分组,每个 API 分组的规则如下:

  • user_api1 分组:匹配以 /server-user/user/api1 开头的所有请求。
  • user_api2 分组:精确匹配 /server-user/user/api2/demo1

2、在服务网关 shop-gateway 模块的 GatewayConfig 配置类中 init() 方法中调用 initCustomizedApis() 方法,为了避免 route 维度的限流对自定义 API 分组维度的限流产生影响,这里,同时在 init() 方法中注释掉调用 initGatewayRules() 方法,修改后的 init() 方法的代码如下所示:

@PostConstruct
public void init() {
    //this.initGatewayRules();
    this.initBlockHandlers();
    this.initCustomizedApis();
}

3、在用户微服务 shop-userUserController 类中新增四个测试接口,源码如下所示:

@GetMapping(value = "/api1/demo1")
public String api1Demo1(){
    log.info("访问了api1Demo1接口");
    return "api1Demo1";
}
@GetMapping(value = "/api1/demo2")
public String api1Demo2(){
    log.info("访问了api1Demo2接口");
    return "api1Demo2";
}
@GetMapping(value = "/api2/demo1")
public String api2Demo1(){
    log.info("访问了api2Demo1接口");
    return "api2Demo1";
}
@GetMapping(value = "/api2/demo2")
public String api2Demo2(){
    log.info("访问了api2Demo2接口");
    return "api2Demo2";
}

4、分别启动用户微服务、商品微服务、订单微服务和服务网关,启动后会在 Sentinel 管理界面左侧菜单栏中看到 server-gateway 菜单,由于我们注释了调用以 route 维度限流的方法,所以,在流控规则里的限流规则为空,如下所示:

在这里插入图片描述

在 API 管理里面会发现我们定义的 API 分组已经自动注册到 Sentinel 中了,如下所示:

在这里插入图片描述

5、在 Sentinel 管理界面的流控规则中,新增网关流控规则,如下所示:

在这里插入图片描述

点击新增网关流控规则后,会弹出新增网关流控规则配置框,按照如下方式为 user_api1 分组配置限流规则:

在这里插入图片描述

点击新增按钮后,按照同样的方式为 user_api2分组配置限流规则。

配置完毕后,在流控规则中的限流规则如下所示:

在这里插入图片描述

6、预期的测试结果如下。

  • 当频繁访问http://localhost:10001/server-user/user/api1/demo1 时会被限流。
  • 当频繁访问http://localhost:10001/server-user/user/api1/demo2 时会被限流。
  • 当频繁访问http://localhost:10001/server-user/user/api2/demo1 时会被限流。
  • 当频繁访问http://localhost:10001/server-user/user/api2/demo2 时不会被限流

注意:只有最后一个不会被限流

7、在浏览器上频繁访问http://localhost:10001/server-user/user/api1/demo1 ,如下所示:

在这里插入图片描述
至此,我们就成功在项目中整合了 SpringCloud Gateway 网关,并通过 Sentinel 整合 SpringCloud
Gateway 实现了网关的限流操作。

代码地址

代码已经上传至码云,码云地址

其中,数据库文件位于 db 文件夹下。

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

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

相关文章

【妙招大放送】:苹果手机数据恢复的4个技巧来啦!

手机是我们日常生活中不可或缺的一部分&#xff0c;它存储着照片、视频、联系人等许多重要的数据。但是&#xff0c;意外时有发生&#xff0c;我们有时会因为软件崩溃或者是手机损坏等的原因导致这些重要的数据丢失。那么&#xff0c;对于苹果用户来说&#xff0c;苹果手机数据…

电源技术中的深力科强力推荐一款低功耗、高效率同步降压变换器SiLM6609 致力于为您提供高品质电源技术解决方案

在能源紧张且智能化技术高速发展的当下&#xff0c;电源是电子设备不可或缺的核心。电源的质量和效率直接关系到设备的稳定运行和能耗控制&#xff0c;对于提高设备性能和降低运营成本至关重要。 为应对现代电子设备对性能与能耗的严苛要求&#xff0c;SiLM6609——低功耗、高…

.NET 一款通过白名单程序执行命令的工具

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

Adobe Photoshop PS v25.6 下载安装教程(PS下载)

前言 Adobe Photoshop 是一款专业强大的图片处理工具&#xff0c;从照片编辑和合成到数字绘画、动画和图形设计&#xff0c;一流的图像处理和图形设计应用程序是几乎每个创意项目的核心所在。利用 Photoshop 在桌面上的强大功能&#xff0c;您可以在灵感来袭时随时随地进行创作…

vue2使用electron-builder打包-使用electron的api实现文件下载

本项目用的是vue2版本开发&#xff0c;最后使用electron-builder打包成桌面应用程序 一、需求描述 1、用户点击按钮&#xff0c;下载html文件 2、代码 exportHtml() { //.html是放在public文件夹下面的本地文件axios.get("/html/合同模板.html").then(res > {let…

网络通信和TCP/IP协议详解

目录 网络协议 一、计算机网络是什么&#xff1f; 定义和分类 计算机网络发展简史 二、计算机网络体系结构 OSI 七层模型 TCP/IP 模型 TCP/IP 协议族 IP、TCP 和UDP TCP/IP 网络传输中的数据 地址和端口号 MAC 地址 IP 地址 端口号 综述 三、TCP 特性 TCP 三次握…

2024最新影视视频APP源码/猕猴桃影视系统源码/独立后台(支持安卓端+苹果端)

源码简介&#xff1a; 最新影视视频APP源码&#xff0c;它是猕猴桃影视系统源码&#xff0c;它有个独立的后台&#xff0c;无论你是安卓还是苹果用户&#xff0c;都能轻松使用呢。 绿豆源码、绿豆影视、小乌2.1&#xff0c;还有猕猴桃影视。追影兔新版本的整体结构设计已经全…

Transformer模型-3-基本工作流程

继 《Transformer模型-2-模型架构》该文主讲Transformer的基本工作流程。 第一步: 获取输入句子某单词的向量X。 X&#xff1a;是指某单词的向量&#xff0c;transformer是分别计算word embedding和position embedding并将两者相加得到向量X。 Embedding Embeddings 是一种将现…

Spring-bean的循环依赖

文章目录 什么是Spring的循环依赖?Setter 方法循环依赖三级缓存Spring 是如何利用三级缓存解决 Bean 的循环依赖&#xff1f;有了三级缓存为什么还需要二级缓存&#xff1f; 构造器循环依赖总结 什么是Spring的循环依赖? 在 Spring 框架中&#xff0c;循环依赖是指两个或多个…

萌化人心的AI宠物视频:1条爆款35万赞,带你轻松涨粉10万(附教程)

萌宠系的小动物配上可爱的 BGM&#xff0c;场景情绪感直接拉满。用 AI 做超萌宠物视频&#xff0c;涨粉确实香&#xff0c; 分享一个有趣的 AI 宠物玩法&#xff0c;使用用 AI 生成超萌动物&#xff08;水獭&#xff09;&#xff0c;做成宠物互动的场景式&#xff0c;这种视频播…

掌握Go语言的基本数据类型:编程世界的ABC

Go语言以其精炼的语法和卓越的性能&#xff0c;正日益成为现代软件开发的关键驱动力。在Go语言的众多特性中&#xff0c;基本数据类型的重要性不言而喻&#xff0c;它们是构建任何复杂应用程序的基石。正如掌握任何新语言需从其基础元素开始&#xff0c;Go语言的学习同样始于对…

【qt】windows下qt连接数据库

1.新建数据库 create database mydatabase;2.新建表结构&#xff0c;并插入数据 3.qt下连接数据库 1.连接数据库&#xff0c;需要加sql 2.添加QsqlDatabase头文件&#xff0c;使用提示句柄&#xff0c;头文件QMessageBox 3.连接数据库 4.界面设计 5.插入实现 注意这里如果…

盛水最多的容器问题

目录 一题目概述&#xff1a; 二思路理解&#xff1a; 三解答代码&#xff1a; 一题目概述&#xff1a; leetcode链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 二思路理解&#xff1a; 首先这道题虽然看起来简单&#xff0c;很难不让人想到直接暴力破解它&a…

【操作系统】12.文件系统是怎么管理的?

2.文件系统是怎么管理的&#xff1f; 2.1 文件系统的实现 2.1.1 文件系统层次结构 用户调用接口 文件目录系统 存取控制验证模块 逻辑文件系统与文件信息缓冲区 物理文件系统 辅助分配模块 设备管理程序模块 2.1.2 目录实现 线性列表 哈希表 2.1.3 文件实现 文件分配方式 连续…

Unity射击游戏开发教程:(32)控制子弹射速

显示发射速度从较慢到较快的变化 这是一篇关于如何实现射速以防止玩家乱按射击按钮的快速文章。 通常做法 说到要控制子弹的射速,可以通过以下几种方法: 通过设置子弹的发射间隔时间来控制射速。在每次子弹发射后,设置一个时间延迟,确保下一枚子弹不能立即发射。 利用计时…

Redis下载安装使用教程图文教程(超详细)

《网络安全自学教程》 Redis下载安装使用 1、下载安装2、基础配置2.1、远程连接2、保护模式3、默认密码4、后台运行4.1 验证服务是否启动4.2 停止服务 1、下载安装 1&#xff09;到Redis中文网 https://www.redis.com.cn/download.html 下载Redis安装包 2&#xff09;Redis的安…

市场动荡!宝马「赶超」特斯拉?华为打响高阶智驾「价格战」

新能源汽车市场正在进入动荡期。 本周&#xff0c;欧洲市场传来重磅消息&#xff0c;宝马在欧洲的电动汽车销量首次超过特斯拉。根据JATO Dynamics的数据&#xff0c;7月宝马在欧洲本土市场销售了14,869辆电动汽车&#xff0c;以308辆的微弱优势首次超过特斯拉。 数据显示&…

“蓝屏事件”阴魂不散,微软安全更新导致 Linux 系统无法启动即解决方案

最近&#xff0c;众多Linux用户报告称他们的设备在尝试启动时&#xff0c;收到了一条神秘的错误消息&#xff1a;“系统出了严重问题。”这起事件的罪魁祸首是微软在月度安全更新中发布的一个补丁&#xff0c;用于修复一个存在已久的GRUB漏洞。 这次更新却导致了Linux和Windows…

Adobe InDesign(ID)专业的排版设计软件win/mac软件下载安装和快捷键的使用

一、Adobe InDesign软件概述 1.1 软件简介 Adobe InDesign是Adobe Systems公司开发的一款面向印刷和数字媒体出版物的专业排版设计软件。它广泛应用于书籍、杂志、报纸、宣传册、海报、广告、电子书等多种出版物的设计与制作中。InDesign以其强大的排版功能、灵活的页面布局工…

7 款最佳软件,可恢复从回收站中删除的文件

您是否曾经从回收站中删除了文件并想要恢复它们&#xff1f;这似乎是不可能的。 但是&#xff0c;从技术上讲&#xff0c;永久删除的文件不会从您的硬盘驱动器存储中删除&#xff0c;而是更改为无法识别的数据并被您的新文件覆盖。 这使您能够从系统中恢复永久删除的文件。 …