sentinel 热点限流
官网:https://sentinelguard.io/zh-cn/docs/parameter-flow-control.html
热点限流
sentinel使用lru算法统计最近最常使用的热点参数,结合令牌桶算法进行限流
# 热点数据限流:统计热点参数,根据配置的限流阈值与模式,对包含热点参数的资源进行限流
参数为商品id,统计一段时间内最常购买的商品ID并进行限制
参数为用户id,针对一段时间内频繁访问的用户ID进行限制
***********
基本使用
相关依赖
<!-- spring-cloud-alibaba-starter-sentinel中有该依赖 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-parameter-flow-control</artifactId>
<version>x.y.z</version>
</dependency>
ParamFlowRule
public class ParamFlowRule extends AbstractRule {
private int grade = 1; //限流模式:QPS(默认)、并发线程数
private Integer paramIdx; //热点参数索引
private double count; //限流阈值
private int controlBehavior = 0; //流控行为:快速失败(默认)、匀速排队模式
private int maxQueueingTimeMs = 0; //匀速排队模式时排队等待时间
private int burstCount = 0; //处理突发流量
private long durationInSec = 1L; //限流窗口时长,默认1s
private List<ParamFlowItem> paramFlowItemList = new ArrayList();
//针对指定的参数值单独设置限流阈值,不受count影响
//仅支持基本类型和字符串类型
private Map<Object, Integer> hotItems = new HashMap();
private boolean clusterMode = false; //是否为集群模式,集群模式传入的参数只支持基本类型和字符串类型
private ParamFlowClusterConfig clusterConfig; //集群限流配置
public ParamFlowRule() {
}
public ParamFlowRule(String resourceName) {
this.setResource(resourceName);
}
AbstractRule
public abstract class AbstractRule implements Rule {
private String resource; //需要限流的资源名称
private String limitApp; //特定资源、default(不限资源)、other
public AbstractRule() {
}
ParamFlowClusterConfig
public class ParamFlowClusterConfig {
private Long flowId; //热点参数集群流控id,需保证全局唯一
private int thresholdType = 0; //阀值模式:0(单机均摊)、1(全局模式)
private boolean fallbackToLocalWhenFail = false; //client连接失败或通信失败时,是否退化到本地的限流模式
private int sampleCount = 10; //窗口数量
private int windowIntervalMs = 1000; //窗口统计时长,默认1s
public ParamFlowClusterConfig() {
}
设置热点参数规则
private static void initParamFlowRules() {
// QPS mode, threshold is 5 for every frequent "hot spot" parameter in index 0 (the first arg).
ParamFlowRule rule = new ParamFlowRule(RESOURCE_KEY)
.setParamIdx(0)
.setGrade(RuleConstant.FLOW_GRADE_QPS)
//.setDurationInSec(3)
//.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)
//.setMaxQueueingTimeMs(600)
.setCount(5);
// We can set threshold count for specific parameter value individually.
// Here we add an exception item. That means: QPS threshold of entries with parameter `PARAM_B` (type: int)
// in index 0 will be 10, rather than the global threshold (5).
ParamFlowItem item = new ParamFlowItem().setObject(String.valueOf(PARAM_B))
.setClassType(int.class.getName())
.setCount(10);
rule.setParamFlowItemList(Collections.singletonList(item));
ParamFlowRuleManager.loadRules(Collections.singletonList(rule));
}
使用示例
***********
相关依赖
<!-- 服务注册与发现 -->
<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-dubbo</artifactId>
</dependency>
<!-- sentinel dubbo适配器 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-apache-dubbo-adapter</artifactId>
<version>1.8.0</version>
</dependency>
<!-- dubbo应用向控制台传输数据 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.8.0</version>
</dependency>
<!-- 热点限流 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-parameter-flow-control</artifactId>
<version>1.8.0</version>
</dependency>
***********
服务端
application.yml
spring:
application:
name: nacos-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848
dubbo:
protocol:
name: dubbo
port: -1
HelloService
public interface HelloService {
String hello(String name);
}
HelloServiceImpl
@DubboService
public class HelloServiceImpl implements HelloService {
@Override
public String hello(String name) {
return "hello " + name;
}
}
DemoApplication
@EnableDubbo
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
***********
消费端
application.yml
spring:
application:
name: nacos-consuemr
cloud:
nacos:
discovery:
server-addr: localhost:8848
dubbo:
protocol:
name: dubbo
port: -1
server:
port: 8081
HelloService
public interface HelloService {
String hello(String name);
}
HelloController
@RestController
public class HelloController {
@DubboReference
private HelloService helloService;
@RequestMapping("/hello")
public String hello(){
System.out.println(helloService.hello("瓜田李下"));
return "success";
}
}
***********
本地限流配置
CustomParamFlowRule
public class CustomParamFlowRule implements InitFunc {
@Override
public void init() throws Exception {
ParamFlowRule paramFlowRule = new ParamFlowRule("com.example.demo.service.HelloService:hello(java.lang.String)");
paramFlowRule.setParamIdx(0)
.setGrade(RuleConstant.FLOW_GRADE_QPS)
.setCount(2);
ParamFlowItem paramFlowItem = new ParamFlowItem();
paramFlowItem.setObject("瓜田李下") //name=瓜田李下的限流阀值是4
//name为其他值的限流阀值是2
.setClassType(String.class.getName())
.setCount(4);
paramFlowRule.setParamFlowItemList(Collections.singletonList(paramFlowItem));
ParamFlowRuleManager.loadRules(Collections.singletonList(paramFlowRule));
}
}
META-INF/services/com.alibaba.csp.sentinel.init.InitFunc
com.example.demo.config.CustomParamFlowRule
jmeter测试
***********
控制台限流配置
控制台启动
java -Dserver.port=8000 -Dcsp.sentinel.dashboard.server=localhost:8000 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
参数说明:
-Dserver.port=8080:指定控制台启动端口
-Dcsp.sentinel.dashboard.server:指定控制台地址和端口
-Dproject.name=sentinel-dashboard:指定控制台项目名称
服务端启动
-Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8000 -Dproject.name=nacos-provider
消费端启动
-Dserver.port=8081 -Dcsp.sentinel.dashboard.server=localhost:8000 -Dproject.name=nacos-consumer
sentinel 控制台:localhost:8000
jmeter 测试