随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
流量控制规则 (FlowRule) 流量规则的定义
重要属性:
Field说明 默认值
resource资源名,资源名是限流规则的作用对象
count限流阈值
grade限流阈值类型,QPS 或线程数模式 QPS 模式
limitApp流控针对的调用来源 default,代表不区分调用来源
strategy判断的根据是资源自身,还是根据其它关联资源 (refResource),还是根据链路入口根据资源本身
controlBehavior流控效果(直接拒绝 / 排队等待 / 慢启动模式) 直接拒绝
同一个资源可以同时有多个限流规则。
资源,可以是任何东西,服务,服务里的方法,甚至是一段代码。使用 Sentinel 来进行资源保护,主要分为几个步骤:
定义资源
定义规则
检验规则是否生效
先把可能需要保护的资源定义好,之后再配置规则。也可以理解为,只要有了资源,我们就可以在任何时候灵活地定义各种流量控制规则。在编码的时候,只需要考虑这个代码是否需要保护,如果需要保护,就将之定义为一个资源。
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 , 并且处理方法必须是静态方法。
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