Alibaba Sentinel 是一个灵活的系统负载控制框架,经过控制接口和方法的调用来保证系统负载不会过大,维持正常响应速度。java
该项目的地址是 https://github.com/alibaba/Se... 。可是阿里的文档一向看起来一头雾水,因此本文介绍如何用一个最简单的项目来上手。若是你熟悉 Spring Boot,那么几分钟就能够搞定。python
首先建立一个空的 Maven 项目,加上 Spring Boot 的依赖。pom.xml
看起来是下面的样子,你能够直接拿来用:git
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.demo</groupId> <artifactId>sentinel-test</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.1.3.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>
这里没有将 Spring Boot 做为 parent 项目,而是使用 <dependencyManagement>
,但效果是同样的。github
在 pom.xml
中,首先添加 Spring Boot 依赖:spring
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency>
而后添加 Sentinel。在这个例子当中,咱们将用 注解 来实现负载控制,因此添加 sentinel-annotation-aspectj
依赖:apache
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-annotation-aspectj</artifactId> <version>1.5.1</version> </dependency>
添加了这两个依赖就 OK 了。框架
Spring Boot 项目须要一个 main() 方法来启动,咱们命名这个类为 com.demo.SentinelTestApplication
,其内容以下:maven
@SpringBootApplication public class SentinelTestApplication { public static void main(String[] args) throws Exception { SpringApplication.run(SentinelTestApplication.class, args); } }
目前这个类尚未具体的内容,但咱们应该先运行一下,确保前面作的事情没有出错,而后再添加内容。spring-boot
咱们在 com.demo
包下建立一个名为 DemoService 的类,这个类包含一个须要作访问控制的 call()
方法:测试
@Service public class DemoService { private int counter; @SentinelResource(value = "DemoService.call", blockHandler = "callBlocked") public void call() { System.out.println("Hello (" + ++counter + ")"); } public void callBlocked(BlockException ex) { System.err.println("Blocked (" + ++counter + ") : " + ex.toString()); } }
所谓访问控制就是当某个方法调用过于频繁时,拒绝掉一部分调用。什么才叫过于频繁,咱们能够经过自定义控制规则的方式来告诉 Sentinel。定义控制规则的部分放在后面介绍,咱们如今先关注业务自己,也就是 DemoService
类。
这个类包含两个方法,其中 call()
方法是主角,正常的业务会调用这个方法;而 callBlocked()
则会在 call()
方法被拒绝掉时调用。
call()
方法上面的 @SentinelResource
注解标明了该方法是须要进行访问控制的。Sentinel 将须要进行访问控制的方法都称做资源。这个注解有两个属性,value
属性表示该资源的名称,咱们经过名称为不一样的资源制定不一样的控制规则。blockHandler
属性表示方法被拒绝时应该调用哪一个替代方法,这个替代方法必须在同一个类当中,且参数列表要在原方法参数列表的基础上再添加一个 BlockException
类型的参数。
Sentinel 将控制规则包装为 com.alibaba.csp.sentinel.slots.block.flow.FlowRule
类。它包含下面几个属性:
resource
: 该规则针对哪一个资源;grade
: 从哪一个方面进行度量,如该方法的每秒调用次数,或同时调用该方法的线程数等等。count
: 度量阈值。超过这个阈值则会拒绝调用该方法。strategy
: 多个规则之间的搭配策略,具体参考这里。下面咱们在 SentinelTestApplication
类里面添加一个建立规则的方法,同时在 main()
方法里面初始化它:
private static void initRules() throws Exception { FlowRule rule1 = new FlowRule(); rule1.setResource("DemoService.call"); rule1.setGrade(RuleConstant.FLOW_GRADE_QPS); rule1.setCount(5); // 每秒调用最大次数为 5 次 List<FlowRule> rules = new ArrayList<>(); rules.add(rule1); // 将控制规则载入到 Sentinel com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager.loadRules(rules); } public static void main(String[] args) throws Exception { initRules(); // Sentinel 载入规则不必定非要在 Spring 初始化以前,在这以后也能够。 SpringApplication.run(SentinelTestApplication.class, args); }
这样 Sentinel 的规则就设置完毕。
Spring 提供 AOP 机制来实现方法调用的拦截,这是 Sentinel 实现控制规则的原理。Sentinel 提供 com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect
类,咱们要在 Spring 容器中加入这个 bean 才能让 @SentinelResource
注解起做用。咱们须要在 SentinelTestApplication
类里面添加下面的代码:
@Bean public SentinelResourceAspect sentinelResourceAspect() { return new SentinelResourceAspect(); }
固然,在实际项目里面这一步能够放到自动配置当中。
最后咱们写一个方法来测试控制规则是否起做用,一样是在 SentinelTestApplication
类里面:
@Autowired private DemoService demoService; @PostConstruct public void run() { for (int i = 0; i < 10; i++) { demoService.call(); } }
实际运行 main()
方法时,你将会看到这样的输出:
Hello (1) Hello (2) Hello (3) Hello (4) Hello (5) Blocked (6) : com.alibaba.csp.sentinel.slots.block.flow.FlowException Blocked (7) : com.alibaba.csp.sentinel.slots.block.flow.FlowException Blocked (8) : com.alibaba.csp.sentinel.slots.block.flow.FlowException Blocked (9) : com.alibaba.csp.sentinel.slots.block.flow.FlowException Blocked (10) : com.alibaba.csp.sentinel.slots.block.flow.FlowException
经过这个例子,你应该大概了解 Sentinel 运做的机制了。在这个基础上,Sentinel 还能实现控制规则的实时修改、远程配置、状态监控等等,它是个很是强大的框架。