Spring Alibaba Sentinel实现集群限流demo
1.背景
1.什么是单机限流?
小伙伴们或许遇到过下图这样的限流配置
又或者是这样的Nacos动态配置限流规则:
以上这些是什么限流?没错,就是单机限流,那么单机限流有什么弊端呢?
假设我们集群部署3台机器(NodeA/NodeB/NodeC),在某时刻,同时有25个请求进来,假设NodeA收到12个请求,NodeB 8个,NodeC 5个,并且每个单机限流qps=10,那么这个时候,NodeA将会触发限流,有两个请求BLOCK掉,这是由于可能发生的流量不均导致NodeA节点流量过高导致限流,这是因为每个机器都是自己管自己,有没有一种方法能够统筹调度呢?这就得提到集群限流了
2.什么是集群限流
集群限流就是,弄一台Token Server,每个客户端机器作为Token Client,有请求进来,Token Client就会向Token Server拿令牌,拿到令牌则不限流,反正则限流。其中Token Server可以作为独立运行的项目,也可以内嵌式内嵌至每个节点中(需将其中一台机器设置为Token Server,如果Token Server节点所在机器宕机,可以将其他Client节点设置成server,sentinel有相关api提供该操作)
例如上面的例子,集群内有3个节点,如果每个节点能承受10的请求,那么加起来就是3x10=30个请求。也就是说只要qps不超过30个请求都不会触发限流。
2.sentinel实现集群限流
1. 以spring-boot项目构建 sentinel-token-server
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion> <groupId>com.lee.sentinel.tokenserver</groupId><artifactId>sentinel-token-server</artifactId><version>0.0.1-SNAPSHOT</version><name>sentinel-token-server</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version><spring-boot.version>2.3.7.RELEASE</spring-boot.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><exclusions><exclusion><groupId>com.alibaba.spring</groupId><artifactId>spring-context-support</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId> </dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--slf4j--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId></dependency> <!--nacos配置中心--><dependency><groupId>com.alibaba.boot</groupId><artifactId>nacos-config-spring-boot-starter</artifactId><version>0.2.12</version><!--由于jar包冲突,此处排除冲突jar,重新导入高版本jar--><!--nacos-spring-context-1.1.1.jar需要比spring-context-support-1.0.8.jar更高版本的jar--><exclusions><exclusion><groupId>com.alibaba.spring</groupId><artifactId>spring-context-support</artifactId></exclusion></exclusions></dependency><!--重新引入jar包--><dependency><groupId>com.alibaba.spring</groupId><artifactId>spring-context-support</artifactId><version>1.0.11</version></dependency><!--sentinel-cluster--><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-cluster-server-default</artifactId><version>1.8.5</version></dependency> <!--sentinel dashboard--><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-transport-simple-http</artifactId><version>1.8.5</version></dependency><!--sentinel dashboard -> nacos 配置动态感知--><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId><version>1.8.5</version></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
application.properties
server.port=9009
#应用名称
spring.application.name=sentinel-token-server
#nacos config center
nacos.config.server-addr=192.168.1.105:8848
ClusterServer启动类
import java.util.HashSet;
import java.util.Set;import com.alibaba.csp.sentinel.cluster.server.ClusterTokenServer;
import com.alibaba.csp.sentinel.cluster.server.SentinelDefaultTokenServer;
import com.alibaba.csp.sentinel.cluster.server.config.ClusterServerConfigManager;
import com.alibaba.csp.sentinel.cluster.server.config.ServerTransportConfig;public class ClusterServer {private static final int TOKEN_SERVER_PORT = 7777;private static final int IDLE_SECONDS = 600;public static void main(String[] args) throws Exception {ClusterTokenServer tokenServer = new SentinelDefaultTokenServer();ServerTransportConfig serverConfig = new ServerTransportConfig(TOKEN_SERVER_PORT, IDLE_SECONDS); ClusterServerConfigManager.loadGlobalTransportConfig( serverConfig ); //可以设置多个namespaceSet<String> namespaceSet = new HashSet<String>();namespaceSet.add("user-service"); //dataId=user-service-flow-rulesClusterServerConfigManager.loadServerNamespaceSet( namespaceSet ); tokenServer.start();}
}
SpringBoot启动类:
基于spring-boot SPI机制初始化限流规则:
ClusterTokenInitFunc:从
import java.util.List;import com.alibaba.csp.sentinel.cluster.flow.rule.ClusterFlowRuleManager;
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;
import com.alibaba.csp.sentinel.init.InitFunc;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;public class ClusterTokenInitFunc implements InitFunc {private String remoteAddress = "192.168.1.105:8848";// nacos配置中心地址private String groupId = "SENTINEL_GROUP";private String dataId_postfix = "-flow-rules";@Overridepublic void init() throws Exception {// TODO Auto-generated method stubloadFlowRuleByNacos();}private void loadFlowRuleByNacos() {// TODO Auto-generated method stub// 从Nacos上获取配置进行加载ClusterFlowRuleManager.setPropertySupplier(namespace -> {// namespace在ClusterServer.java中已配置String dataId = namespace + dataId_postfix; // user-service-flow-rules、 coupon-service-flow-rulesReadableDataSource<String, List<FlowRule>> readableDataSource = new NacosDataSource<>(remoteAddress,groupId, dataId, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {}));return readableDataSource.getProperty();});}}
其中,我的Nacos配置(dataId=user-service-flow-rules)设置如下:
[{"resource":"com.lee.demo.dubbo.demo.user.ISentinelService","grade":1,"count":2,"clusterMode":true,"clusterConfig":{"flowId":"1001","thresholdType":1,"fallbackToLocalWhenFail":true}},{"resource":"com.lee.demo.dubbo.demo.user.IHelloService","grade":1,"count":30,"clusterMode":true,"clusterConfig":{"flowId":"1002","thresholdType":1,"fallbackToLocalWhenFail":true}}
]
至此sentinel-token-server搭建完成,启动服务
2. 配置客户端Token Client
导包
<!--nacos配置中心--><dependency><groupId>com.alibaba.boot</groupId><artifactId>nacos-config-spring-boot-starter</artifactId><version>0.2.12</version><!--由于jar包冲突,此处排除冲突jar,重新导入高版本jar--><!--nacos-spring-context-1.1.1.jar需要比spring-context-support-1.0.8.jar更高版本的jar--><exclusions><exclusion><groupId>com.alibaba.spring</groupId><artifactId>spring-context-support</artifactId></exclusion></exclusions></dependency><!--重新引入jar包--><dependency><groupId>com.alibaba.spring</groupId><artifactId>spring-context-support</artifactId><version>1.0.11</version></dependency><!--sentinel-dubbo-adapter --><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-apache-dubbo-adapter</artifactId><version>1.8.5</version></dependency><!--sentinel dashboard--><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-transport-simple-http</artifactId><version>1.8.5</version></dependency><!--sentinel dashboard -> nacos 配置动态感知--><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId><version>1.8.5</version></dependency><!--sentinel-token-cluster--><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-cluster-client-default</artifactId><version>1.8.5</version></dependency>
加载集群流控规则:
ClusterFlowRuleInitFunc.java
import java.util.List;import com.alibaba.csp.sentinel.cluster.ClusterStateManager;
import com.alibaba.csp.sentinel.cluster.client.config.ClusterClientAssignConfig;
import com.alibaba.csp.sentinel.cluster.client.config.ClusterClientConfig;
import com.alibaba.csp.sentinel.cluster.client.config.ClusterClientConfigManager;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;
import com.alibaba.csp.sentinel.init.InitFunc;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;public class ClusterFlowRuleInitFunc implements InitFunc{private static final String CLUSTER_SERVER_HOST = "localhost";private static final int CLUSTER_SERVER_PORT = 7777;private static final int REQUEST_TIME_OUT = 20000;private static final String remoteAddress = "192.168.1.105:8848";private static final String groupId = "SENTINEL_GROUP"; private static final String FLOW_POSTFIX="-flow-rules";private static final String APP_NAME="user-service";@Overridepublic void init() throws Exception {// TODO Auto-generated method stub//声明为Token ClientClusterStateManager.applyState(ClusterStateManager.CLUSTER_CLIENT);//加载集群限流Token Server loadClusterClientConfig(); //加载单机限流规则(如果Token Server不可用,退化到单机限流)initFlowRulesWithDatasource(); }/*** 集群限流规则* */private void loadClusterClientConfig() {ClusterClientAssignConfig assignConfig = new ClusterClientAssignConfig();assignConfig.setServerHost(CLUSTER_SERVER_HOST);assignConfig.setServerPort(CLUSTER_SERVER_PORT);ClusterClientConfigManager.applyNewAssignConfig(assignConfig);ClusterClientConfig clientConfig = new ClusterClientConfig();clientConfig.setRequestTimeout(REQUEST_TIME_OUT);ClusterClientConfigManager.applyNewConfig(clientConfig);}/*** 单机限流规则* */private void initFlowRulesWithDatasource() { String dataId = APP_NAME + FLOW_POSTFIX;
// ReadableDataSource<String, List<FlowRule>> readableDataSource = new NacosDataSource<>(
// remoteAddress, groupId, dataId
// ,source->JSON.parseObject(source,new TypeReference<List<FlowRule>>() {}));ReadableDataSource<String, List<FlowRule>> readableDataSource = new NacosDataSource<>(remoteAddress, groupId, dataId, new Converter<String, List<FlowRule>>() { @Overridepublic List<FlowRule> convert(String source) {// TODO Auto-generated method stubSystem.out.println("source:"+source); List<FlowRule> rules = JSON.parseObject(source,new TypeReference<List<FlowRule>>() {}); return rules;}}); FlowRuleManager.register2Property(readableDataSource.getProperty());} }
Controller:
至此,Token Client配置完成。
接下来启动3个客户端,模拟集群:
Sentinel-Dashboard上可以看到user-service有三台集群机器:
使用jmeter压测工具进行压测:
压测结果如下,可以看到com.lee.demo.dubbo.demo.user.ISentinelService.testSentinel() 接口的qps一直不会超过6个请求,这个峰值是怎么计算的来的呢?因为我上面提到的Nacos集群限流配置dataId=user-service-flow-rules中配置com.lee.demo.dubbo.demo.user.ISentinelService的qps=2,而我们总共有3台机器,因此集群限流max qps:2x3=6
至此,sentinel上线集群限流demo已完成,如有疑问请在评论区评论。
相关文章:

Spring Alibaba Sentinel实现集群限流demo
1.背景 1.什么是单机限流? 小伙伴们或许遇到过下图这样的限流配置 又或者是这样的Nacos动态配置限流规则: 以上这些是什么限流?没错,就是单机限流,那么单机限流有什么弊端呢? 假设我们集群部署3台机器&a…...
102、SOA、分布式、微服务之间有什么关系和区别?
SOA、分布式、微服务之间有什么关系和区别? 分布式架构是指将单体架构中的各个部分拆分,然后部署到不同的机器或进程中去,SOA和微服务基本上都是分布式架构师SOA是一种面向服务的架构,系统的所有服务都注册在总线上,当调用服务时…...

Ubuntu 20.04下的录屏与视频剪辑软件
ubuntu20.04下的录屏与视频剪辑 一、录屏软件SimpleScreenRecorder安装与使用 1、安装 2、设置录制窗口参数 3、开始录制 二、视频剪辑软件kdenlive的安装 1、安装 2、启动 一、录屏软件SimpleScreenRecorder安装与使用 1、安装 (1)直接在终端输入以下命…...
面试题 -- iOS数据存储
文章目录 一、如果后期需要增加数据库中的字段怎么实现,如果不使用CoreData呢?二、SQLite 数据存储是怎么用?三、简单描述下客户端的缓存机制?四、实现过多线程的Core Data 么?NSPersistentStoreCoordinator࿰…...
spring复习:(51)environment、systemProperties、systemEnvironment三个bean是在哪里被添加到容器的?
一、主类: package cn.edu.tju.study.service.anno;import cn.edu.tju.study.service.anno.config.MyConfig; import cn.edu.tju.study.service.anno.domain.Person; import com.sun.javafx.runtime.SystemProperties; import org.springframework.context.annotat…...

element ui 上传控件携带参数到后端
1.携带固定参数: 2.携带不固定参数: <el-row> <el-col :span"24"> <el-upload :multiple"false" :show-file-list"false" :on-success"f_h…...
scrapy分布式+指纹去重原理
1,指纹去重原理存在于 scrapy.util.requests 里面 需要安装的包 pip install scrapy-redis-cluster # 安装模块 pip install scrapy-redis-cluster0.4 # 安装模块时指定版本 pip install --upgrade scrapy-redis-cluster # 升级模块版本 2,setting配置 …...

FileHub使用教程:Github Token获取步骤,使用快人一步
FileHub介绍 filehub是我开发的一个免费文件存储软件,可存万物。软件仓库:GitHub - Sjj1024/s-hub: 一个使用github作为资源存储的软件 软件下载地址:。有问题可以留言或者提Issue, 使用第一步:获取Github Token 使…...

嵌入式开发:单片机嵌入式Linux学习路径
SOC(System on a Chip)的本质区别在于架构和功能。低端SOC如基于Cortex-M架构的芯片,如STM32和NXP LPC1xxx系列,不具备MMU(Memory Management Unit),适用于轻量级实时操作系统如uCOS和FreeRTOS。…...
Libvirt的virsh工具常用命令
在使用Libvirt的virsh工具时,以下是常见的一些命令: 连接到Hypervisor: virsh -c <URI>:连接到指定的Hypervisor,例如 virsh -c qemu:///system 连接到本地的QEMU/KVM Hypervisor。 虚拟机管理: list…...
高斯消元解异或方程组写法
高斯约旦消元解异或方程组 for(int j1;j<n;j){for(int ij1;i<n;i)if(a[i][j]){swap(a[i],a[j]);break;}if(!a[i][i]){if(a[i][n1])//no...else ...//mul}for(int i1;i<n;i)if(i!j&&a[i][j])for(int kj;k<n1;k)a[i][k]^a[j][k];}正常高斯消元法 int r1;for…...

前端 mock 数据的几种方式
目录 接口demo Better-mock just mock koa webpack Charles 总结 具体需求开发前,后端往往只提供接口文档,对于前端,最简单的方式就是把想要的数据写死在代码里进行开发,但这样的坏处就是和后端联调前还需要再把写死的数据…...
【GO】go语言入门实战 —— 猜数字游戏
文章目录 程序介绍设置随机数读取用户输入实现判断逻辑实现游戏循环完整代码 程序介绍 首先生成一个介于1~100之间的随机数,然后提示玩家输入数字,并告诉玩家是猜对了还是猜错了,如果对了程序就结束,如果错了就提醒玩家是大了还是…...

opencv-25 图像几何变换04- 透视 cv2.warpPerspective()
什么是透视? 透视是一种几何学概念,用于描述在三维空间中观察物体时,由于视角的不同而产生的变形效果。在现实世界中,当我们从不同的角度或位置观察物体时,它们会呈现出不同的形状和大小。这种现象被称为透视效果。 透…...

视频讲解Codeforces Round 887 (Div. 2)(A--C)
文章目录 A. Desorting1、板书2、代码 B. Fibonaccharsis1、板书2、代码 C. Ntarsis Set1、板书2、代码 视频讲解Codeforces Round 887 (Div. 2)(A–C) A. Desorting 1、板书 2、代码 #include<bits/stdc.h> #define endl \n #define INF 0x3f…...

【团队协作开发】将Gitee项目导入到本地IDEA中出现根目录不完整的问题解决(已解决)
前言:在团队协作开发过程中,通常我们的Gitee完整项目中会包含很多内容:后端代码、前端代码、项目结构图、项目文档等一系列资产。 将Gitee项目导入到本地IDEA中,通常会出现根目录不完整的问题。这是因为项目里面包含了后端代码、前…...
vue-pdf 单列显示多个pdf页面
<template><div><pdfv-for"i in numPages":key"i":src"src":page"i"style"display: inline-block; width: 100%"></pdf> <!-- 宽度设置100% 一行只展示一页 --></div> </template&g…...

2023年FPGA好就业吗?
FPGA岗位有哪些? 从芯片设计流程来看,FPGA岗位可以分四类 产品开发期:FPGA系统架构师 芯片设计期:数字IC设计工程师、FPGA开发工程师 芯片流片期:FPGA验证工程师 产品维护期:FAE工程师 从行业上来说&#x…...
【业务功能篇52】Springboot+mybatis mysql开启批量执行sql参数 allowMultiQueries=true
allowMultiQueriestrue参数的作用: 可以在sql语句后携带分号,实现多语句执行。可以执行批处理,同时发出多个SQL语句。 在application-xxx.xml配置文件中,配置数据库的信息 spring:datasource:dynamic:primary: mysqldb # 默认数…...

StableDiffusion 换脸实现
先看效果: 想要换的脸: 想要把脸放到的目标图片: 实现方案: StableDiffusionroop(本次实验基于roopV0.02版本) 1/安装SD,模型选择 DreamShaper,Sampler使用 Euler a 2/安装roop插件 roop插…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...

1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...