简介:
关于sentinel的一些基本概念以及使用代码方式实现流控规则,异常处理。
sentinel基本介绍和相关概念
sentinel是面向分布式服务架构的高可用防护,流量治理组件组价。
作用:以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。
主要是保障微服务架构中服务的可用性的。
服务有可能因为各种原因而挂掉,比如流量激增,依赖的服务挂了,异常没有处理,缺乏容错机制,消息积压,慢SQL,第三方服务不响应等,而引起服务雪崩。
服务雪崩:服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过程,最终导致整个系统不可用。
常见的容错机制:
- 服务熔断
- 服务降级
- 限流
- 超时机制
- 隔离
sentinel就是提供了很多的容错机制来保障系统可用性的一个组件。
sentinel的使用
sentinel可以通过Java代码或控制台来使用,代码的话更灵活,控制台的话更友好简单。
通过Java代码的方式
通过使用sentinel的代码的方式实现流控规则和异常处理。
项目目录
pom.xml文件
<?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">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sentinelTest</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--sentinel核心库-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.18</version>
</dependency>
<!--@SentinelResource的依赖-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>1.8.0</version>
</dependency>
</dependencies>
</project>
application.yaml文件
server:
port: 8060
SentinelApplication
package com;
import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class SentinelApplication {
public static void main(String[] args) {
SpringApplication.run(SentinelApplication.class,args);
}
//要使用@sentinelResource注解,得加这个bean
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
}
Message
@Data
public class Message {
private final String message;
}
SentinelController
所有的规则都是针对资源(即接口)起作用的。
package com.controller;
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 com.pojo.Message;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
@RestController
@Slf4j
public class SentinelController {
private static final String Message = "message";
@PostConstruct
//这个注解是spring的注解,表示spring在加载这个类(SentinelController )的时候,会自动调用这个方法
private static void initFlowRules(){
//这个规则是个数组,表示可以同时对多个接口设规则
List<FlowRule> rules = new ArrayList<>();
//flowrule表示流控规则的对象
FlowRule rule = new FlowRule();
//这个规则是对哪个资源(接口)起作用
rule.setResource(Message);
//流控规则是QPS,QPS是每秒的访问数
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
//表示QPS的次数大于1,则控流
rule.setCount(1);
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
@RequestMapping("/message")
/*value的值是定义资源的名字。fallback是指定这个接口出现异常时的处理方
法。blockHandler是指定流控规则其作用后执行的方法。*/
@SentinelResource(value = Message, fallback = "fallbackHandleForMehtod",blockHandler = "blockHandlerForMethod")
public Message getUser(String id) {
int a=1/0;
return new Message("too dark!!!");
}
/*接口出现异常的处理方法,blockHandlerForMethod方法的优先级要高于fallbackHandleForMehtod方法,也即降级方法的优先级高于异常处理方法*/
public Message fallbackHandleForMehtod(String id, Throwable e) {
e.printStackTrace();
return new Message("异常处理");
}
/*流控降级后的方法,一般默认是和资源写在同一个类中,如果写在其他类中,要在
@sentinelResource注解中使用属性blockHandlerClass指定类,并且方法要
static修饰。这个方法的返回值要和资源接口的返回值相同,参数也要包含资源接
口的参数*/
public Message blockHandlerForMethod(String id, BlockException ex) {
ex.printStackTrace();
return new Message("流控处理");
}
}
访问:http://localhost:8060/message
走的是fallback方法,如果在一秒钟以内点两次刷新
走的就是流控处理。QPS大于1,触发了blockHandler方法,并且这个方法的优先级比fallback方法高。
设置熔断降级规则
在上面的SentinelController类中加上:
@PostConstruct
public void initDegradeRule(){
List<DegradeRule> degradeRules = new ArrayList<>();
DegradeRule degradeRule = new DegradeRule();
//这个规则是对哪个资源(接口)起作用
degradeRule.setResource("degrade");
//熔断规则是异常数
degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
//异常数大于2的时候出发熔断
degradeRule.setCount(2);
//请求数至少要大于2
degradeRule.setMinRequestAmount(2);
//在一分钟以内
degradeRule.setStatIntervalMs(60*1000);
/*触发了熔断10秒后,变为半开状态,请求会到达接口,如果第一次请求还是报错,那么又变为熔断,即之后的10秒请求会到熔断的降级方法中去。*/
degradeRule.setTimeWindow(10);
degradeRules.add(degradeRule);
DegradeRuleManager.loadRules(degradeRules);
}
@RequestMapping("/degrade")
@SentinelResource(value = "degrade",entryType = EntryType.IN,
blockHandler = "blockHandlerForFb")
public Message degrade(String id) throws InterruptedException {
throw new RuntimeException("抛出异常");
}
public Message blockHandlerForFb(String id, BlockException ex) {
return new Message("熔断处理");
}
访问地址:http://localhost:8060/degrade
一分钟内点击三次刷新,就会触发降级方法。
补充
流控规则一般设置在服务的提供方,降级规则一般设置在服务消费方
常用的规则有:流量控制规则、熔断降级规则、系统保护规则、来源访问控制规则 和 热点参数规则。
还有更多的规则,可以看:官方文档