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插…...

接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...

label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...

EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...

SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...

Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...

接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...