sentinel组件学习
sentinel学习
- 服务雪崩
服务雪崩效应:因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过程。
sentinel容错机制
常见的容错机制有超时机制、服务限流、隔离、服务熔断
- 超时机制
在不做任何处理的情况下,服务提供者不可用回导致消费者请求线程强制等待,而造成系统资源耗尽。加入超时机制,一旦超时,就释放资源。由于释放资源较快,一定程度上可以抑制资源耗尽的问题。 - 服务限流
某个服务达到QPS设定最大值则抛异常。 - 服务熔断
- 服务降级
有服务熔断,必然要有服务降级。
所谓降级,就是当某个服务熔断之后,服务将不再被调用,此时客户端可以自己准备一个本地的fellback(回退),回调,返回一个缺省值。例如:(备用接口/缓存/mock数据),这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强,当然这也要看适合的业务场景。(服务熔断之后进入客户端降级方法)
使用代码方式进行QPS流控-流控规则初体验
- 引入sentinel相关包
xml
<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>
</dependency>
<!--sentinel注解方式-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!--sentinel整合dashbaord控制台-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.8.0</version>
</dependency>
</dependencies>
- 代码实现
java
package com.sentinel.controller;
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer;
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 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;
/**
* @author : zhouzhiqiang
* @date : 2024/6/5 23:25
* @description :
*/
@Slf4j
@RestController
@RequestMapping("/hello")
public class HelloController {
private static final String RESOURCE_NAME="hello";
private static final String USER_RESOURCE_NAME="user";
private static final String DEGRADE_RESOURCE_NAME="degrade";
@RequestMapping("/helloSentinel")
public String hello(){
Entry entry=null;
try {
entry= SphU.entry(RESOURCE_NAME);
String str="hello world";
log.info("======="+str+"=======");
return str;
} catch (BlockException e) {
log.info("block");
return "被限流了!";
}catch (Exception e){
Tracer.traceEntry(e,entry);
}finally {
if (entry != null) {
entry.exit();
}
}
return null;
}
@PostConstruct
public static void initFlowRules(){
//流控规则
List<FlowRule> rules=new ArrayList<>();
//流控
FlowRule rule = new FlowRule();
//为哪个资源进行流量控制
rule.setResource(RESOURCE_NAME);
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(1);
rules.add(rule);
//加载流控规则
FlowRuleManager.loadRules(rules);
}
}
使用@SentinelResource注解进行流控
要使用这个注解需要引入相关包和配置SentinelResourceAspect的bean
- 引入包
xml
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>1.8.0</version>
</dependency>
- 配置bean
java
@Bean
public SentinelResourceAspect sentinelResourceAspect(){
return new SentinelResourceAspect();
}
- 使用注解方式
value:定义资源(接口名称)
blockHandler :设置流控降级后的处理方法,默认该方法,必须声明在一个类中
fallback:接口中出现异常了,就可以交给fellback指定的处理方法
java
@PostConstruct
public static void initFlowRules(){
//流控规则
List<FlowRule> rules=new ArrayList<>();
//流控
FlowRule rule = new FlowRule();
//为哪个资源进行流量控制
rule.setResource(USER_RESOURCE_NAME);
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(1);
rules.add(rule);
//加载流控规则
FlowRuleManager.loadRules(rules);
}
@RequestMapping("/user")
@SentinelResource(value = USER_RESOURCE_NAME,blockHandler = "blockHandlerForGetUser",fallback = )
public User getUser(String id){
return new User("zzq");
}
/**
* 注意:
* 1、一定是public
* 2、返回值一定得和原方法返回值一致,包含方法的参数
* 3、可以在参数的最后添加BlockException,可以区分是什么规则的处理方法
* @param id
* @param e
* @return
*/
//降级方法
public User blockHandlerForGetUser(String id,BlockException e){
e.printStackTrace();
return new User("被流控了!");
}
通过代码方式设置降级规则-降级规则初体验
java
@RestController
@RequestMapping("/test")
public class TestController {
private static final String DEGRADE_RESOURCE_NAME="degrade";
@RequestMapping("/degrade")
@SentinelResource(value = DEGRADE_RESOURCE_NAME,entryType = EntryType.IN,blockHandler = "blockHandlerForJob")
public User degrade(String id){
int i=1;
int sum=i/0;
return new User("成功");
}
public User blockHandlerForJob(String id, BlockException e){
e.printStackTrace();
return new User("触发降级规则");
}
@PostConstruct
public void initDegradeRule(){
List<DegradeRule> rules=new ArrayList<>();
DegradeRule rule = new DegradeRule();
rule.setResource(DEGRADE_RESOURCE_NAME);
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
//触发熔断异常数
rule.setCount(2);
//触发熔断的最小请求数
rule.setMinRequestAmount(2);
//统计时长:单位ms 1分钟
rule.setStatIntervalMs(60*1000);
//一分钟内:执行了两次 ,出现两次异常 就会触发熔断
/**
* 熔断持续时间,单位秒。一旦触发了熔断,再次请求接口则直接调用降级方法。
* 10秒后,---半开状态,恢复接口调用。如果再次请求,则会熔断,不再根据熔断规则进入熔断,而是直接进入熔断
*/
rule.setTimeWindow(10);
rules.add(rule);
DegradeRuleManager.loadRules(rules);
}
}
流控规则一般设置在服务生产方,而降级规则一般设置在服务消费方
sentinel控制台部署
下载dashboard--https://github.com/alibaba/Sentinel/releases
运行jar包:java -jar sentinel-dashboard-1.8.0.jar。运行完毕进行访问,默认端口号8080。用户名和密码默认sentinel
客户端整合服务端
客户端需要引入Transport模块来与sentinel控制台进行通信
xml
<!--sentinel整合dashbaord控制台-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.8.0</version>
</dependency>
- 配置启动
客户端启动时需要加入JVM参数-Dcsp.sentinel.dashboard.server=192.168.1.15:8080,指定控制台地址和端口