返回顶部
首页 > 资讯 > 精选 >Spring cloud中限流的方式有哪些
  • 760
分享到

Spring cloud中限流的方式有哪些

2023-06-15 10:06:21 760人浏览 安东尼
摘要

这篇文章主要介绍了spring cloud中限流的方式有哪些,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。在频繁的网络请求时,服务有时候也会受到很大的压力,尤其是那种网络攻击

这篇文章主要介绍了spring cloud中限流的方式有哪些,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

在频繁的网络请求时,服务有时候也会受到很大的压力,尤其是那种网络攻击,非法的。这样的情形有时候需要作一些限制。例如:限制对方的请求,这种限制可以有几个依据:请求IP、用户唯一标识、请求的接口地址等等。

当前限流的方式也很多:spring cloud 中在网关本身自带限流的一些功能,基于 redis 来做的。同时,阿里也开源了一款:限流神器 Sentinel。今天我们主要围绕这两块来实战微服务的限流机制。

首先讲 Spring cloud 原生的限流功能,因为限流可以是对每个服务进行限流,也可以对于网关统一作限流处理。

一、实战基于 Spring cloud Gateway 的限流

pom.xml引入依赖:

<dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-data-Redis-Reactive</artifactId>    </dependency>

其基础是基于redis,所以:

spring:  application:    name: gateway-service  redis: #redis相关配置    database: 8    host: 10.12.15.5    port: 6379    passWord: 123456 #有密码时设置    jedis:      pool:        max-active: 8        max-idle: 8        min-idle: 0    timeout: 10000ms

接下来需要注入限流策略的 bean:

@Primary  @Bean(value = "ipKeyResolver")  KeyResolver ipKeyResolver() {      return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());      //return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());      //return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());  }   @Bean(value = "apiKeyResolver")  KeyResolver apiKeyResolver() {    return exchange -> Mono.just(exchange.getRequest().getPath().value());  }    @Bean(value = "userKeyResolver")  KeyResolver userKeyResolver() {    return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("userId"));  }

这里引入ipKeyResolver、apiKeyResolver、userKeyResolver三种策略,可以利用注解 @Primary 来决定其中一个被使用。

注入bean后,需要在配置中备用:

spring:  application:    name: gateway-service  redis: #redis相关配置    database: 8    host: 10.12.15.5    port: 6379    password: 123456 #有密码时设置    jedis:      pool:        max-active: 8        max-idle: 8        min-idle: 0    timeout: 10000ms

后面是限流的主要配置:

spring  cloud:    gateway:      routes: #路由配置:参数为一个List      - id: cas-server #唯一标识        uri: lb://cas-server-service #转发的地址,写服务名称        order: -1        predicates:        - Path=/cas-server/** #判断匹配条件,即地址带有/ribbon/**的请求,会转发至lb:cas-server-service        filters:        - StripPrefix=1 #去掉Path前缀,参数为1代表去掉/ribbon        - name: RequestRateLimiter #基于redis的Gateway的自身限流          args:            redis-rate-limiter.replenishRate: 1  # 允许用户每秒处理多少个请求            redis-rate-limiter.burstCapacity: 3  # 令牌桶的容量,允许在一秒钟内完成的最大请求数            key-resolver: "#{@ipKeyResolver}" #SPEL表达式取的对应的bean      - id: admin-WEB        uri: lb://admin-web-service        order: -1        predicates:        - Path=/admin-web/**        filters:        - StripPrefix=1        - name: RequestRateLimiter          args:            redis-rate-limiter.replenishRate: 1  # 允许用户每秒处理多少个请求            redis-rate-limiter.burstCapacity: 3  # 令牌桶的容量,允许在一秒钟内完成的最大请求数            key-resolver: "#{@ipKeyResolver}" #SPEL表达式取的对应的bean

这里是在原有的路由基础上加入 RequestRateLimiter限流过滤器,包括三个参数:

- name: RequestRateLimiter #基于redis的Gateway的自身限流          args:            redis-rate-limiter.replenishRate: 3  #允许用户每秒处理多少个请求            redis-rate-limiter.burstCapacity: 5  #令牌桶的容量,允许在一秒钟内完成的最大请求数            key-resolver: "#{@ipKeyResolver}" #SPEL表达式取的对应的bean
  • 其中 replenishRate,其含义表示允许每秒处理请求数;

  • burstCapacity 表示允许在一秒内处理的最大请求数;

  • key-resolver 这里采用请求 IP 限流,利用SPEL 表达式取对应的 bean

写一个小脚本来压测一下:

for i in $(seq 1 30000); do echo $(expr $i \\* 3 + 1);curl -i -H "Accept: application/JSON" -H "Authorization:bearer b064d95b-af3f-4053-a980-377c63ab3413" -X GET Http://10.10.15.5:5556/order-service/api/order/getUserInfo;donefor i in $(seq 1 30000); do echo $(expr $i \\* 3 + 1);curl -i -H "Accept: application/json" -H "Authorization:bearer b064d95b-af3f-4053-a980-377c63ab3413" -X GET http://10.10.15.5:5556/admin-web/api/user/getCurrentUser;done

上面两个脚本分别对2个服务进行压测,打印结果:

{"message":{"status":200,"code":0,"message":"success"},"data":"{\"message\":{\"status\":200,\"code\":0,\"message\":\"get user success\"},\"data\":{\"id\":23,\"isAdmin\":1,\"userId\":\"fbb18810-e980-428c-932f-848f3b9e7c84\",\"userType\":\"super_admin\",\"username\":\"admin\",\"realName\":\"super_admin\",\"password\":\"$2a$10$89AqlYKlnsTpNmWcCMvgluRFQ/6MLK1k/nkBpz.Lw6Exh.WMQFH6W\",\"phone\":null,\"email\":null,\"createBy\":\"admin\",\"createTime\":1573119753172,\"updateBy\":\"admin\",\"updateTime\":1573119753172,\"loginTime\":null,\"expireTime\":null,\"remarks\":\"super_admin\",\"delFlag\":0,\"loginType\":null}}"}ex

在用测试工具jmeter在同一秒内多次请求后:

HTTP/1.1 429 Too Many RequestsX-RateLimit-Remaining: 0X-RateLimit-Burst-Capacity: 3X-RateLimit-Replenish-Rate: 1content-length: 0expr: syntax errorHTTP/1.1 429 Too Many RequestsX-RateLimit-Remaining: 0X-RateLimit-Burst-Capacity: 3X-RateLimit-Replenish-Rate: 1content-length: 0expr: syntax error

从上面可以看到,执行后,会出现调用失败的情况,状态变为429 (Too Many Requests) 。

二、基于阿里开源限流神器:Sentinel

首先引入依赖:

<!--基于 阿里的sentinel作限流 -->    <dependency>          <groupId>com.alibaba.cloud</groupId>          <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>    </dependency>

在配置文件 application.yaml 文件中配置,需要新增2个配置:

spring:  application:    name: admin-web  cloud:    kubernetes:      discovery:        all-namespaces: true    sentinel:      eager: true #取消Sentinel控制台的懒加载      transport:        dashboard: 10.12.15.2:8080 #sentinel的Dashboard地址        port: 8719 #是sentinel应用端和控制台通信端口        heartbeat-interval-ms: 500 #心跳时间      scg:        fallback: #scg.fallback为sentinel限流后的响应配置          mode: response          response-status: 455          response-body: 已被限流

其中,这里面配置了一个服务:spring.cloud.sentinel.transport.dashboard,配置的是 sentinel 的 Dashboard 地址。同时 spring.cloud.sentinel.transport.port 这个端口配置会在应用对应的机器上启动一个Http Server,该 Server 会与 Sentinel 控制台做交互。

Sentinel 默认为所有的 HTTP 服务提供限流埋点,上面配置完成后自动完成所有埋点,只需要控制配置限流规则即可。
这里我们讲下通过注解来给指定接口函数加上限流埋点,写一个RestController,在接口函数上加上注解

@SentinelResource:@GetMapping(value = "/getToken")@SentinelResource("getToken")public Response<Object> getToken(Authentication authentication){    //Authentication authentication = SecurityContextHolder.getContext().getAuthentication();    authentication.getCredentials();    OAuth3AuthenticationDetails details = (OAuth3AuthenticationDetails)authentication.getDetails();    String token = details.getTokenValue();    return Response.ok(200, 0, "get token success", token);}

以上代码部分完成了,接下来先安装SentinelDashBoard,Sentinel DashBoard下载地址:GitHub.com/alibaba/Sentinel/releases。

下载完成后,命令启动:

java -jar sentinel-dashboard-1.6.2.jar

默认启动端口为8080,访问 IP:8080,就可以显示 Sentinel 的登录界面,用户名与密码均为sentinel。登录 Dashboard 成功后,多次访问接口"/getToken",可以在 Dashboard 看到相应数据,这里不展示了。接下来可以设置接口的限流功能,在 “+流控” 按钮点击打开设置界面,设置阈值类型为 qps,单机阈值为5。

浏览器重复请求 http://10.10.15.5:5556/admin-web/api/user/getToken 如果超过阀值就会出现如下界面信息:
Blocked by Sentinel (flow limiting)

此时,就看到Sentinel 限流起作用了,可以加上 spring.cloud.sentinel.scg.fallback 为sentinel 限流后的响应配置,亦可自定义限流异常信息:

@GetMapping(value = "/getToken")@SentinelResource(value = "getToken", blockHandler = "handleSentinelException", blockHandlerClass = {MySentinelException.class}))public Response<Object> getToken(Authentication authentication){    //Authentication authentication = SecurityContextHolder.getContext().getAuthentication();    authentication.getCredentials();    OAuth3AuthenticationDetails details = (OAuth3AuthenticationDetails)authentication.getDetails();    String token = details.getTokenValue();    return Response.ok(200, 0, "get token success", token);}public class MySentinelException {    public static Response<Object> handleSentinelException(BlockException e) {        Map<String,Object> map=new HashMap<>();        logger.info("Oops: " + ex.getClass().getCanonicalName());        return Response.ok(200, -8, "通过注解 @SentinelResource 配置限流埋点并自定义限流后的处理逻辑", null);    }}

这里讲下注解 @SentinelResource 包含以下属性:

  • value:资源名称,必需项;

  • entryType:入口类型,可选项(默认为 EntryType.OUT);

  • blockHandler:blockHandlerClass中对应的异常处理方法名,参数类型和返回值必须和原方法一致;

  • blockHandlerClass:自定义限流逻辑处理类

Sentinel 限流逻辑处理完毕了,但每次服务重启后,之前配置的限流规则就会被清空。因为是内存形式的规则对象。所以下面就讲下用 Sentinel 的一个特性 ReadableDataSource 获取文件、数据库或者配置中心设置限流规则,目前支持 Apollo、Nacos、ZK 配置来管理。

首先回忆一下,一条限流规则主要由下面几个因素组成:

  • resource:资源名,即限流规则的作用对象,即为注解 @SentinelResource 的value;

  • count:限流阈值;grade:限流阈值类型(QPS 或并发线程数);

  • limitApp:流控针对的调用来源,若为 default 则不区分调用来源;

  • strategy:基于调用关系的限流策略;

  • controlBehavior:流量控制效果(直接拒绝、排队等待、匀速器模式)

理解了意思,接下来通过文件来配置:

#通过文件读取限流规则spring.cloud.sentinel.datasource.ds1.file.file=classpath:flowrule.jsonspring.cloud.sentinel.datasource.ds1.file.data-type=jsonspring.cloud.sentinel.datasource.ds1.file.rule-type=flow

在resources新建一个文件,比如 flowrule.json 添加限流规则:

[  {    "resource": "getToken",    "count": 1,    "controlBehavior": 0,    "grade": 1,    "limitApp": "default",    "strategy": 0  },  {    "resource": "resource",    "count": 1,    "controlBehavior": 0,    "grade": 1,    "limitApp": "default",    "strategy": 0  }]

重新启动项目,出现如下日志说明成功:

DataSource ds1-sentinel-file-datasource start to loadConfigDataSource ds1-sentinel-file-datasource load 2 FlowRule

如果采用 Nacos 作为配置获取限流规则,可在文件中加如下配置:

spring:  application:    name: order-service  cloud:    nacos:      config:        server-addr: 10.10.15.5:8848      discovery:        server-addr: 10.10.15.5:8848    sentinel:      eager: true      transport:        dashboard: 10.10.15.5:8080      datasource:        ds1:          nacos:            server-addr: 10.10.15.5:8848            dataId: ${spring.application.name}-flow-rules            data-type: json            rule-type: flow

感谢你能够认真阅读完这篇文章,希望小编分享的“Spring cloud中限流的方式有哪些”这篇文章对大家有帮助,同时也希望大家多多支持编程网,关注编程网精选频道,更多相关知识等着你来学习!

--结束END--

本文标题: Spring cloud中限流的方式有哪些

本文链接: https://lsjlt.com/news/279711.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Spring cloud中限流的方式有哪些
    这篇文章主要介绍了Spring cloud中限流的方式有哪些,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。在频繁的网络请求时,服务有时候也会受到很大的压力,尤其是那种网络攻击...
    99+
    2023-06-15
  • Spring cloud 限流的多种方式
    目录一、实战基于 Spring cloud Gateway 的限流 二、基于阿里开源限流神器:Sentinel 在频繁的网络请求时,服务有时候也会受到很大的压力,尤其是那种网络攻击,...
    99+
    2024-04-02
  • Spring Cloud中有哪些组件
    这篇文章主要介绍了Spring Cloud中有哪些组件,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Spring Cloud七大组件:1、Eureka组件,描述了服务如何进行...
    99+
    2023-06-14
  • redis实现限流的方式有哪些
    Redis实现限流的方式有以下几种:1. 固定窗口算法:对请求进行计数,在固定的时间窗口内,如果请求数超过阈值,则拒绝请求。2. 滑...
    99+
    2023-09-14
    redis
  • 浅析Spring Cloud Gateway中的令牌桶限流算法
    目录前言回顾限流算法计数器/时间窗口法漏桶法令牌桶法主要逻辑分析 前言 在一个分布式高并发的系统设计中,限流是一个不可忽视的功能点。如果不对系统进行有效的流量访问限制,在双十一和抢票...
    99+
    2024-04-02
  • sentinel 整合spring cloud限流的过程解析
    spring cloud基于http进行服务调用,大致过程如下: 服务提供端:提供http接口,并向服务中心注册服务信息服务消费端:将服务端的http接口作为本地服务,从注册中心读取...
    99+
    2024-04-02
  • Spring Cloud基础知识有哪些
    本篇内容介绍了“Spring Cloud基础知识有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Spring Cloud 之“出身名门望...
    99+
    2023-06-19
  • Spring Cloud组成部分有哪些
    这篇文章主要介绍“Spring Cloud组成部分有哪些”,在日常操作中,相信很多人在Spring Cloud组成部分有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Spring Cloud组成部分有哪些...
    99+
    2023-06-02
  • Spring Cloud集成项目有哪些
    这篇文章主要讲解了“Spring Cloud集成项目有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring Cloud集成项目有哪些”吧!Spring Cloud Config配置...
    99+
    2023-06-05
  • Spring Cloud相关项目有哪些
    小编给大家分享一下Spring Cloud相关项目有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Spring Cloud Config配置管理工具包,让你可...
    99+
    2023-06-05
  • Spring Cloud常见问题有哪些
    本篇内容介绍了“Spring Cloud常见问题有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、Eureka常见问题Eureka 注...
    99+
    2023-06-05
  • Spring Cloud Alibaba之Sentinel实现熔断限流功能的方法
    这篇文章主要介绍Spring Cloud Alibaba之Sentinel实现熔断限流功能的方法,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!sentinel简介这个在阿里云有企业级的商用版本 应用高可用服务 AHA...
    99+
    2023-06-14
  • Spring Cloud Stream的使用细节有哪些
    Spring Cloud Stream的使用细节有哪些,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。上我们就来看看Spring Cloud Stream的一些使用细节。自定义消...
    99+
    2023-06-19
  • Spring Cloud OpenFeign优化的技巧有哪些
    这篇文章主要介绍了Spring Cloud OpenFeign优化的技巧有哪些的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Spring Cloud OpenFeign优...
    99+
    2023-06-30
  • spring的注入方式有哪些
    Spring的注入方式有三种:1. 构造器注入(Constructor Injection):通过构造方法来注入依赖对象。2. Se...
    99+
    2023-09-27
    spring
  • spring配置的方式有哪些
    在Spring框架中,配置的方式有以下几种: XML配置:使用XML文件来配置Spring的各种组件、依赖关系和属性等。XML文...
    99+
    2023-10-25
    spring
  • spring 的配置方式有哪些
    这篇文章将为大家详细讲解有关spring 的配置方式有哪些,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。就目前来说spring的配置方式一般为两种:JAVA配置和注解配置//注解配置:@Se...
    99+
    2023-05-31
    spring
  • Spring的配置方式有哪些
    Spring的配置方式有以下几种:1. XML配置:使用XML文件配置Spring的各种组件,包括Bean的定义、依赖关系、AOP等...
    99+
    2023-08-15
    Spring
  • Redis限流的实现方法有哪些
    本篇内容主要讲解“Redis限流的实现方法有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Redis限流的实现方法有哪些”吧!一、简单的限流基本原理当系统处理能力有限,如何组织计划外的请求对...
    99+
    2023-06-22
  • Spring Cloud Alibaba核心组件有哪些
    这篇文章主要讲解了“Spring Cloud Alibaba核心组件有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring Cloud Alibaba核心组件有哪些”吧!Java语...
    99+
    2023-06-03
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作