一、sentinel的安装与介绍
sentinel是分布式系统的流量防卫兵,以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
首先从GitHub上下载最新的sentinel,下载完成以后在cmd运行java -jar的命令执行jar包,我们可以在localhost:8080查看主页面,用户名和密码都是sentinel。
二、搭建一个监控模块
首先在pom文件中导入Sentinel相关的jar包
com.alibaba.csp
sentinel-datasource-nacos
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
然后在yml文件中进行相关的配置
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinal-service
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
sentinel:
transport:
dashboard: localhost:8080 #配置sentinel dashboard地址
port: 8719 # 默认8719端口,假如被占用会自动从8719端口+1进行扫描,直到找到未被占用的端口
management:
endpoints:
web:
exposure:
include: '*'
controller层
@RestController
public class FlowController {
@GetMapping("/testA")
public String testA() throws InterruptedException {
return "----testA";
}
}
主启动类
@EnableDiscoveryClient
@SpringBootApplication
public class Service8401 {
public static void main(String[] args) {
SpringApplication.run(Service8401.class,args);
}
}
完成搭建以后,访问localhost:8401/testA,以后我们在Sentinel Dashboard进行刷新,可以看到访问的相关信息。
三、流控规则
1. 通过QPS限制的快速失败策略
如果请求的QPS超过阈值,那么就会执行快速失败的策略
当请求次数超过QPS阈值以后
2. 通过线程数限制的快速失败策略
如果线程数超过设置的阈值以后就进行服务降级
当超过阈值以后
3. 通过QPS限制的预热启动方式
启动时的阈值=设置好的阈值 / 3(冷因子数),在经过一段预热时间就会达到当时设置的阈值。
可以看到在刚启动的时候如果QPS太大就会进行限流,当预热时间过去以后就会发现可以正常访问。
4. 通过QPS限制的排队等待方式
当QPS数量超过以后不会立即失败,而是进入一个队列进行排队等待,当过了超时时间就会失败。
当QPS过大的时候就会出现排队的情况。
5. 通过QPS限制的关联流程模式
当请求/testA的QPS超过阈值的时候同样也会将/testB进行限流,经常会出现在当支付模块QPS过高时会限制下订单模块。
6. 通过QPS限制的链路流程模式
如果有两个入口entrance1和entrance2都能请求到某一资源,可以针对从某一个入口的请求会记录到资源的QPS中。
四、熔断降级
1. 平均响应时间(RT)
当 1s 内持续进入N个请求,对应时刻的平均响应时间(秒级)均超过阈值(ms 为单位),那么在接下的时间窗口(s 为单位)之内,对这个方法的调用都会自动地熔断(抛出 DegradeException
)。注意 Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项 -Dcsp.sentinel.statistic.max.rt=xxx
来配置。
2. 异常比例
当资源的每秒请求量 >= N(可配置),并且每秒异常总数占通过量的比值超过阈值之后,资源进入降级状态,即在接下的时间窗口( s 为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是 [0.0, 1.0]
。
3. 异常数
当资源近1分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若时间窗口小于60s,则结束熔断状态后仍可能再进入熔断状态。
五、热点参数限流
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
如果不带热点参数进行访问,QPS的阈值就是设置的单机阈值,如果携带热点参数,那么有将会是另外一个限流阈值。可以在参数索引中设置第几个参数(从0开始),还可以携带参数的类型以及参数值为多少的时候才可以进行热点限流。
六、系统规则
这是对整个系统的一种设置,一共可以从5个方面进行设置
maxQps * minRt
估算得出。设定参考值一般是 CPU cores * 2.5
。这种设置不能细化,不太好用所以不推荐在系统层面进行某些设置
七、@SentinelResource 注解
1. 按照资源名进行限流
@GetMapping("/byResource")
@SentinelResource(value = "byResource",blockHandler = "handleException") // 按照资源名称限流就是按照SentinelResource注解的value进行限流,被限流以后执行blockHandler的兜底方法
public CommentResult byResource() {
return new CommentResult(200,"按照资源名称限流测试",new Payment(2020,"serial001"));
}
// 需要添加BlockException
public CommentResult handleException(BlockException exception) {
return new CommentResult(444,exception.getClass().getCanonicalName() + "\t 服务不用");
}
2. 按照url进行限流
对某个url进行限流
3. 自定义限流
我们可以指定某个类的某个指定的方法进行兜底
@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler",blockHandlerClass = CustomerBlockHandler.class,blockHandler = "handlerException2")
// blockHandlerClass 指定兜底方法的类,blockHandler指定兜底方法的类的哪个方法
public CommentResult customerBlockHandler() {
return new CommentResult(200,"按照客户自定义限流测试",new Payment(2020,"serial003"));
}
异常类
public class CustomerBlockHandler {
public static CommentResult handlerException(BlockException exception) {
return new CommentResult(444,"按照客户自定义的Glogal 全局异常处理 ---- 1",new Payment(2020,"serial003"));
}
}
八、sentinel+Ribbon
@RestController
public class ConsumerController {
public static final String SERVICE_URL = "http://nacos-payment-provider";
@Resource
private RestTemplate restTemplate;
@RequestMapping("/consumer/fallback/{id}")
// fallback是负责在运行期间的兜底方法,blockHandler负责sentinel控制台的异常兜底方法。
// exceptionsToIgnore 指定的方法不走兜底方法,直接报错
@SentinelResource(value = "fallback",fallback ="handlerFallback",blockHandler = "blockHandler", exceptionsToIgnore = {IllegalArgumentException.class})
public CommentResult fallback(@PathVariable Integer id) {
CommentResult result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/" + id,CommentResult.class);
if(id == 4){
throw new IllegalArgumentException("IllegalArgument ,非法参数异常...");
}else if(result.getData() == null) {
throw new NullPointerException("NullPointerException,该ID没有对应记录,空指针异常");
}
return result;
}
public CommentResult handlerFallback(@PathVariable Integer id,Throwable e) {
Payment payment = new Payment(id,"null");
return new CommentResult(444,"异常handlerFallback,exception内容: " + e.getMessage(), payment);
}
public CommentResult blockHandler(@PathVariable Integer id,BlockException e) {
Payment payment = new Payment(id,"null");
return new CommentResult(444,"blockHandler-sentinel 限流,BlockException: " + e.getMessage(), payment);
}
}
九、sentinel+Openfeign
service接口
// 定义异常错误接口
@FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)
public interface PaymentService {
@GetMapping("/paymentSQL/{id}")
public CommentResult paymentSQL(@PathVariable("id") Integer id);
}
处理机制
@Component // 实现接口添加注解
public class PaymentFallbackService implements PaymentService{
public CommentResult paymentSQL(Integer id) {
return new CommentResult(444,"服务降级返回");
}
}
主启动类
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients // 添加openfeign
public class Consumer84 {
public static void main(String[] args) {
SpringApplication.run(Consumer84.class, args);
}
}
十、sentinel持久化
首先导入持久化的jar包
com.alibaba.csp
sentinel-datasource-nacos
然后在yml文件进行nacos相关的配置
spring:
cloud:
sentinel:
datasource:
ds1:
nacos:
server-addr: localhost:8848 # nacos的地址
dataId: cloudalibaba-sentinal-service # nacos上配置文件的名称
groupId: DEFAULT_GROUP # 配置文件的分组
data-type: json # 配置文件的类型
rule-type: flow # 配置文件的规则
然后在nacos上创建一个配置文件,选为json格式,配置内容如下:
[
{
"resource": "/testA", # 资源名称
"limitApp": "default", # 来源App一般是默认
"grade": 1, # 阈值类型,0代表线程数,1代表QPS
"count": 1, # 单机阈值
"strategy": 0, # 流控模式,0直接,1关联,2链路
"controlBehavior": 0, # 流控效果,0快速失败,1warm up,2排队等待
"clusterMode": false # 是否集群
}
]
这样配置信息不会随着服务的宕机而消失了,将配置信息存在nacos上。