SpringCloud Alibaba微服务实战十二 - 网关限流

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: SpringCloud Alibaba微服务实战十二 - 网关限流

导读:通过前面的章节我们在微服务层做了限流,并且集成了SpringCloud Gateway,本章主要内容是将限流功能从微服务迁移到网关层。


SpringCloud Gateway 原生限流


Springcloud Gateway 原生限流主要基于过滤器实现,我们可以直接使用内置的过滤器RequestRateLimiterGatewayFilterFactory,目前RequestRateLimiterGatewayFilterFactory的实现依赖于 Redis,所以我们还要引入spring-boot-starter-data-redis-reactive


POM依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifatId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>


限流配置

spring:
  cloud:
    gateway:
      routes:
      - id:account-service
        uri:lb://account-service
        order:10000
        predicates:
        -Path=/account-service/**
        filters:
        - name:RequestRateLimiter
          args:
            redis-rate-limiter.replenishRate:1
            redis-rate-limiter.burstCapacity:3
            key-resolver:"#{@ipKeyResolver}"

主要是配置三个主要参数:

  • redis-rate-limiter.replenishRate :
    允许用户每秒处理多少个请求
  • redis-rate-limiter.burstCapacity :
    令牌桶的容量,允许在一秒钟内完成的最大请求数
  • key-resolver :
    用于限流的键的解析器的 Bean 对象的名字。它使用 SpEL 表达式根据#{@beanName}从 Spring 容器中获取 Bean 对象。

配置Bean

/**
* 自定义限流标志的key,多个维度可以从这里入手
* exchange对象中获取服务ID、请求信息,用户信息等
*/
@Bean
KeyResolver ipKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}


Sentinel 限流


我们之前的章节已经讲过Sentinel的使用方法,如果有不清楚的可以翻看之前的章节,这里主要说一下与SpringCloud gateway的整合。

Sentinel从 1.6.0 版本开始提供了 Spring Cloud Gateway 的适配模块,可以提供两种资源维度的限流:

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

下面是我们的整合步骤


POM依赖

<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
  <groupId>com.alibaba.csp</groupId>
  <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

由于需要使用 nacos作为sentinel的配置中心,所以也引入了sentinel-datasource-nacos


Bootstrap配置

...
spring:
  cloud:
    sentinel:
      transport:
        dashboard:10.0.10.48:8858
      eager:true
      datasource:
        ds:
          nacos:
            server-addr:10.0.10.48:8848
            data-id:gateway-sentinel-flow
            group-id:DEFAULT_GROUP
            rule-type:gw-flow
...

这里主要是sentinel的相关配置,从nacos配置中心获取 gateway-sentinel-flow 配置文件,限流类型是网关类型gw-flow。


限流配置

在nacos配置管理public页面建立 data-idgateway-sentinel-flow 的配置文件(json格式),给account-serviceproduct-service添加限流规则。

[
  {
    "resource": "account-service",
    "count": 5,
    "grade": 1,
    "paramItem": {
        "parseStrategy": 0
    }
  },
  {
    "resource": "product-service",
    "count": 2,
    "grade": 1,
    "paramItem": {
        "parseStrategy": 0
    }
  }
]

配置完成以后启动网关项目,登录sentinel控制台,查看限流规则:

配置说明:

以客户端IP作为限流因子
public static final int PARAM_PARSE_STRATEGY_CLIENT_IP = 0;
以客户端HOST作为限流因子
public static final int PARAM_PARSE_STRATEGY_HOST = 1;
以客户端HEADER参数作为限流因子
public static final int PARAM_PARSE_STRATEGY_HEADER = 2;
以客户端请求参数作为限流因子
public static final int PARAM_PARSE_STRATEGY_URL_PARAM = 3;
以客户端请求Cookie作为限流因子
public static final int PARAM_PARSE_STRATEGY_COOKIE = 4;


限流测试

多次通过网关访问account-service服务进行测试 http://localhost:8090/account/getByCode/javadaily 查看限流效果:


自定义响应异常

SpringCloud-gateway限流异常默认的实现逻辑为SentinelGatewayBlockExceptionHandler,可以查看源码发现异常响应的关键代码如下

由于服务后端都是返回JSON的响应格式,所以我们需要修改原异常响应,将其修改成ResultData类的响应格式。要实现这个功能只需要写个新的异常处理器然后在SpringCloud GateWay配置类中注入新的异常处理器即可。

  • 自定义异常处理器CustomGatewayBlockExceptionHandler
publicclass CustomGatewayBlockExceptionHandler implements WebExceptionHandler {
  ...
    /**
     * 重写限流响应,改造成JSON格式的响应数据
     * @author javadaily
     * @date 2020/1/20 15:03
     */
    private Mono<Void> writeResponse(ServerResponse response, ServerWebExchange exchange) {
        ServerHttpResponse serverHttpResponse = exchange.getResponse();
        serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        ResultData<Object> resultData = ResultData.fail(ReturnCode.RC200.getCode(), ReturnCode.RC200.getMessage());
        String resultString = JSON.toJSONString(resultData);
        DataBuffer buffer = serverHttpResponse.bufferFactory().wrap(resultString.getBytes());
        return serverHttpResponse.writeWith(Mono.just(buffer));
    }
    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        if (exchange.getResponse().isCommitted()) {
            return Mono.error(ex);
        } else {
            return !BlockException.isBlockException(ex) ? Mono.error(ex) : this.handleBlockedRequest(exchange, ex).flatMap((response) -> this.writeResponse(response, exchange));
        }
    }
   ...
}

大家可以直接复制 SentinelGatewayBlockExceptionHandler 类,然后修改 writeResponse方法接口

  • 修改Gateway配置类,注入CustomGatewayBlockExceptionHandler
@Configuration
publicclass GatewayConfiguration {
  ...
    /**
     * 注入自定义网关异常
     */
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public CustomGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        // Register the custom block exception handler .
        returnnew CustomGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }
  ...
}
  • 在bootstrap.yml文件中新增配置
spring:
  main:
    allow-bean-definition-overriding:true
  • 重新测试,限流响应结果如下
{
  "message": "服务开启限流保护,请稍后再试!",
  "status": 200,
  "success": false,
  "timestamp": 1579509123946
}


限流不生效

各位在使用过程中如果发现网关层限流不生效,可以以debug模式启动网关服务,然后对网关过滤器 SentinelGatewayFilter 中的filter方法进行调试,我发现sentinel获取到的网关id并不是我们配置的account-service,而是加了CompositeDiscoveryClient_前缀,如下图所示:

所以我们需要修改 gateway-sentinel-flow  的配置,给我们的resource 也加上前缀,修改完的配置如下:

[{
  "resource": "CompositeDiscoveryClient_account-service",
  "count": 5,
  "grade": 1,
  "paramItem": {
    "parseStrategy": 0
  }
}, {
  "resource": "CompositeDiscoveryClient_product-service",
  "count": 2,
  "grade": 1,
  "paramItem": {
    "parseStrategy": 0
  }
}]

通过使用jemter对接口进行测试,发现网关能正常限流

经过以上几步,我们可以将后端微服务层的限流配置去掉,让网关层承担限流的功能。

好了,各位朋友们,本期的内容到此就全部结束啦,能看到这里的同学都是优秀的同学,下一个升职加薪的就是你了!

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
2月前
|
SpringCloudAlibaba API 开发者
新版-SpringCloud+SpringCloud Alibaba
新版-SpringCloud+SpringCloud Alibaba
|
19天前
|
运维 NoSQL Java
后端架构演进:微服务架构的优缺点与实战案例分析
【10月更文挑战第28天】本文探讨了微服务架构与单体架构的优缺点,并通过实战案例分析了微服务架构在实际应用中的表现。微服务架构具有高内聚、低耦合、独立部署等优势,但也面临分布式系统的复杂性和较高的运维成本。通过某电商平台的实际案例,展示了微服务架构在提升系统性能和团队协作效率方面的显著效果,同时也指出了其带来的挑战。
57 4
|
1月前
|
JSON SpringCloudAlibaba Java
Springcloud Alibaba + jdk17+nacos 项目实践
本文基于 `Springcloud Alibaba + JDK17 + Nacos2.x` 介绍了一个微服务项目的搭建过程,包括项目依赖、配置文件、开发实践中的新特性(如文本块、NPE增强、模式匹配)以及常见的问题和解决方案。通过本文,读者可以了解如何高效地搭建和开发微服务项目,并解决一些常见的开发难题。项目代码已上传至 Gitee,欢迎交流学习。
132 1
Springcloud Alibaba + jdk17+nacos 项目实践
|
1月前
|
Dubbo Java 应用服务中间件
Dubbo学习圣经:从入门到精通 Dubbo3.0 + SpringCloud Alibaba 微服务基础框架
尼恩团队的15大技术圣经,旨在帮助开发者系统化、体系化地掌握核心技术,提升技术实力,从而在面试和工作中脱颖而出。本文介绍了如何使用Dubbo3.0与Spring Cloud Gateway进行整合,解决传统Dubbo架构缺乏HTTP入口的问题,实现高性能的微服务网关。
|
2月前
|
负载均衡 Java 网络架构
实现微服务网关:Zuul与Spring Cloud Gateway的比较分析
实现微服务网关:Zuul与Spring Cloud Gateway的比较分析
108 5
|
2月前
|
运维 持续交付 API
深入理解并实践微服务架构:从理论到实战
深入理解并实践微服务架构:从理论到实战
137 3
|
2月前
|
人工智能 前端开发 Java
Spring Cloud Alibaba AI,阿里AI这不得玩一下
🏀闪亮主角: 大家好,我是JavaDog程序狗。今天分享Spring Cloud Alibaba AI,基于Spring AI并提供阿里云通义大模型的Java AI应用。本狗用SpringBoot+uniapp+uview2对接Spring Cloud Alibaba AI,带你打造聊天小AI。 📘故事背景: 🎁获取源码: 关注公众号“JavaDog程序狗”,发送“alibaba-ai”即可获取源码。 🎯主要目标:
95 0
|
13天前
|
设计模式 Java API
微服务架构演变与架构设计深度解析
【11月更文挑战第14天】在当今的IT行业中,微服务架构已经成为构建大型、复杂系统的重要范式。本文将从微服务架构的背景、业务场景、功能点、底层原理、实战、设计模式等多个方面进行深度解析,并结合京东电商的案例,探讨微服务架构在实际应用中的实施与效果。
57 6
|
13天前
|
设计模式 Java API
微服务架构演变与架构设计深度解析
【11月更文挑战第14天】在当今的IT行业中,微服务架构已经成为构建大型、复杂系统的重要范式。本文将从微服务架构的背景、业务场景、功能点、底层原理、实战、设计模式等多个方面进行深度解析,并结合京东电商的案例,探讨微服务架构在实际应用中的实施与效果。
29 1
|
2月前
|
安全 应用服务中间件 API
微服务分布式系统架构之zookeeper与dubbo-2
微服务分布式系统架构之zookeeper与dubbo-2
下一篇
无影云桌面