1、简单介绍
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
流量控制规则 (FlowRule) 流量规则的定义
重要属性:
Field | 说明 | 默认值 |
---|---|---|
resource | 资源名,资源名是限流规则的作用对象 | |
count | 限流阈值 | |
grade | 限流阈值类型,QPS 或线程数模式 | QPS 模式 |
limitApp | 流控针对的调用来源 | default ,代表不区分调用来源 |
strategy | 判断的根据是资源自身,还是根据其它关联资源 (refResource ),还是根据链路入口 | 根据资源本身 |
controlBehavior | 流控效果(直接拒绝 / 排队等待 / 慢启动模式) | 直接拒绝 |
同一个资源可以同时有多个限流规则。
资源,可以是任何东西,服务,服务里的方法,甚至是一段代码。使用 Sentinel 来进行资源保护,主要分为几个步骤:
- 定义资源
- 定义规则
- 检验规则是否生效
先把可能需要保护的资源定义好,之后再配置规则。也可以理解为,只要有了资源,我们就可以在任何时候灵活地定义各种流量控制规则。在编码的时候,只需要考虑这个代码是否需要保护,如果需要保护,就将之定义为一个资源。
2、导入依赖,参数配置、定义资源
1、导入依赖
<!-- spring-cloud-starter-alibaba-sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>1.6.3</version>
</dependency>
import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AopConfiguration {
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
}
2、参数配置
spring.application.name: SpringBootWeb
#server
server.port=80
server.servlet.context-path=/#sentinel控制台
spring.cloud.sentinel.transport.dashboard=localhost:8080
spring.cloud.sentinel.eager=true#sentinel数据源连接nacos ds1为数据源的名称,可以随便写
spring.cloud.sentinel.datasource.ds1.nacos.server-addr=localhost:8848
spring.cloud.sentinel.datasource.ds1.nacos.dataId=${spring.application.name}-sentinel
spring.cloud.sentinel.datasource.ds1.nacos.groupId=DEFAULT_GROUP
spring.cloud.sentinel.datasource.ds1.nacos.ruleType=flow
3、定义资源
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
@RestController
public class HelloController {
@Autowired
private HelloService helloService ;
@RequestMapping("/helloworld")
public String helloworld() {
return helloService.helloworld() ;
}
@RequestMapping("/helloworld2/{name}")
public String helloworld2(@PathVariable("name") String name) {
return helloService.helloworld2(name) ;
}
}
import org.springframework.stereotype.Service;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
@Service
public class HelloService {
@SentinelResource(value="helloworld1",blockHandlerClass=ExceptionUtil.class,blockHandler="handleException1")
public String helloworld() {
return "hello Sentinel111 !";
}
@SentinelResource(value="helloworld2",blockHandlerClass=ExceptionUtil.class,blockHandler="handleException2")
public String helloworld2(String name) {
return "hello Sentinel222 !" + name;
}
}
import com.alibaba.csp.sentinel.slots.block.BlockException;
public class ExceptionUtil {
public static String handleException1(BlockException ex) {
System.out.println("Oops: " + ex.getClass().getCanonicalName());
return "系统限流了111....";
}
public static String handleException2(String name, BlockException ex) {
System.out.println("Oops: " + ex.getClass().getCanonicalName());
return "系统限流了222....";
}
}
@SentinelResource(value="helloworld1",blockHandlerClass=ExceptionUtil.class,blockHandler="handleException1")
value定义资源名称, blockHandlerClass阻塞处理类, blockHandler阻塞处理方法。
// Handler method that handles BlockException when blocked.
// The method parameter list should match original method, with the last additional
// parameter with type BlockException. The return type should be same as the original method.
// The block handler method should be located in the same class with original method by default.
// If you want to use method in other classes, you can set the blockHandlerClass
// with corresponding Class (Note the method in other classes must be static).ExceptionUtil类中创建处理BlockException的方法,,当阻塞的时候来处理BlockException 。 方法参数类别需要和原方法一致,在最后加上一个BlockException类型的参数;返回结果和原方法一致。 处理BlockException的方法默认在原方法相同类中。也可以指定在其他类中,就需要在方法上设置blockHandlerClass , 并且处理方法必须是静态方法。
3、定义规则
1、启动nacos后台,添加限流配置 ,dataId 和 group 需要和application.properties中一致。
[
{
"resource": "helloworld1",
"limitApp": "default",
"grade": 1,
"count": 3,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
},
{
"resource": "helloworld2",
"limitApp": "default",
"grade": 1,
"count": 2,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
2、启动sentinel后台
访问测试:
![]() | ![]() |
![]() | ![]() |
参考github上官方文档和相关demo:https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D