官网:https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D
总结:1.Semaphone信号量限流 2.在spring cloud +RateLimite
你可以发现没有一个框架是直接限流的,Sentinel哨兵框架很棒
它包括限流,熔断,统计等等功能
原理我看不下那个源码,个人能力有限,打扰了,网址:https://github.com/alibaba/Sentinel/wiki/Sentinel%E5%B7%A5%E4%BD%9C%E4%B8%BB%E6%B5%81%E7%A8%8B
大概意思是:所有的资源对应一个资源名称以及Entry,然后会附带很多插槽,包括限流,熔断...我的理解是通过这个资源名称,来适配这些资源,对他们进行限流等等操作
https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6
pom.xml
com.alibaba.csp
sentinel-annotation-aspectj
1.4.1
demo
public static void main(String[] args) {
instanceFlowRules();
Entry entry = null;
try {
entry = SphU.entry("HelloWorld");
System.out.println("HelloWorld");
} catch (BlockException e) {
System.out.println("block...");
} finally {
if(entry!=null){
entry.exit();
}
}
}
private static void instanceFlowRules() {
List list = new ArrayList<>();
FlowRule flowRule = new FlowRule();
flowRule.setResource("HelloWorld");
//20qps
flowRule.setCount(20);
flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
list.add(flowRule);
FlowRuleManager.loadRules(list);
}
如何测试效果?
@ResponseBody
@RequestMapping(value = "test1")
public void b() {
Entry entry = null;
try {
entry = SphU.entry("HelloWorld");
System.out.println("HelloWorld");
} catch (BlockException e) {
System.out.println("block...");
} finally {
if(entry!=null){
entry.exit();
}
}
}
使用apache ab工具,ab -c 100 -n 1000 http://localhost:8080/test1
可以看到会出现blocking...
因为超出阈值的时候,统一抛出BlockExection
https://github.com/alibaba/Sentinel/wiki/%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7
官方demohttps://github.com/alibaba/Sentinel/blob/master/sentinel-demo/sentinel-demo-basic/src/main/java/com/alibaba/csp/sentinel/demo/degrade/RtDegradeDemo.java
对应的是DegradeRule
private static void initDegradeRule() {
List rules = new ArrayList();
DegradeRule rule = new DegradeRule();
rule.setResource(KEY);
// set threshold rt, 10 ms
rule.setCount(10);
rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
rule.setTimeWindow(10);
rules.add(rule);
DegradeRuleManager.loadRules(rules);
}
https://github.com/alibaba/Sentinel/wiki/%E6%B3%A8%E8%A7%A3%E6%94%AF%E6%8C%81
参数:
value
: 资源名称,必需项(不能为空)entryType
: 入口类型,可选项(默认为 EntryType.OUT
)blockHandler
/ blockHandlerClass
: blockHandler
对应处理 BlockException
的函数名称,可选项。若未配置,则将 BlockException
直接抛出。blockHandler 函数访问范围需要是 public
,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException
。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass
为对应的类的 Class
对象,注意对应的函数必需为 static 函数,否则无法解析。fallback
: fallback 函数名称,可选项,仅针对降级功能生效(DegradeException
)。fallback 函数的访问范围需要是 public
,参数类型和返回类型都需要与原方法相匹配,并且需要和原方法在同一个类中。业务异常不会进入 fallback 逻辑。
个人demo
@Configuration
public class AopConfiguration {
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
}
实例化注解
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.stereotype.Service;
@Service
public class AServer {
@SentinelResource(value = "test", blockHandler = "exceptionHandler")
public void HelloWorld() {
System.out.println("调用get()");
}
public void exceptionHandler(BlockException e) {
e.printStackTrace();
System.out.println("出错!!!");
}
}
value资源名称,blockHandler发生BlockExection时进行服务降级
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.ArrayList;
import java.util.List;
@Controller
public class AController {
@Autowired
AServer aServer;
@ResponseBody
@RequestMapping(value = "test")
public void a() {
System.out.println("Hello");
aServer.HelloWorld();
}
@ResponseBody
@RequestMapping(value = "test1")
public void b() {
Entry entry = null;
try {
entry = SphU.entry("HelloWorld");
System.out.println("HelloWorld");
} catch (BlockException e) {
System.out.println("block...");
} finally {
if(entry!=null){
entry.exit();
}
}
}
public static void main(String[] args) {
//instanceFlowRules();
Entry entry = null;
try {
entry = SphU.entry("HelloWorld");
System.out.println("HelloWorld");
} catch (BlockException e) {
System.out.println("block...");
} finally {
if(entry!=null){
entry.exit();
}
}
}
private static void instanceFlowRules() {
List list = new ArrayList<>();
FlowRule flowRule = new FlowRule();
flowRule.setResource("HelloWorld");
flowRule.setCount(20);
flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
list.add(flowRule);
FlowRuleManager.loadRules(list);
}
}
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
instanceFlowRules();
SpringApplication.run(DemoApplication.class, args);
}
private static void instanceFlowRules() {
List list = new ArrayList<>();
FlowRule flowRule = new FlowRule();
flowRule.setResource("test");
flowRule.setCount(20);
flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
list.add(flowRule);
FlowRuleManager.loadRules(list);
}
}
启动类配置限流,对test资源限流
ab工具访问http://localhost:8080/test
输出;
出错!!!
Hello
com.alibaba.csp.sentinel.slots.block.flow.FlowException
出错!!!
Hello
com.alibaba.csp.sentinel.slots.block.flow.FlowException
出错!!!