一只阿木木

什么是微服务雪崩问题?Sentinel 特征介绍与下载使用

Image

什么是微服务雪崩问题?Sentinel 特征介绍与下载使用

Sentinel 特征介绍

分布式系统的流量防卫兵,Sentinel以“流量”为切入点,在流量控制、断路、负载保护等多个方面进行续航,保证服务的可靠性。

Sentinel具有以下特征:

丰富的应用场景:Sentinel承接了大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。

完备的实时监控:Sentinel 同时提供实时的监控功能。可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。

广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Apache Dubbo、gRPC、Quarkus 的整合。只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。同时 Sentinel 提供 Java/Go/C++ 等多语言的原生实现。

完善的 SPI 扩展机制:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。


Image

Sentinel断流产品的特性

当分布式系统面临复杂的体系结构中应用程序可能有数十个依赖关系,每个依赖关系在某些时候将不可避免的失败,这些服务中某一个出现问题了,就有可能会出现整体系统效率的下降,严重的甚至出现服务雪崩。

多个微服务之间互相调用的时候,比如我们调用 D\F\K 这几个服务,如果D调用K和F,而K和F又调用其他的微服务,那么就会形成扇出,如果扇出某个链路上的微服务调用超时或者响应很慢,那么微服务D就会占用越来越多的系统资源,导致系统崩溃,也就是服务雪崩。

容错的三个核心思想
  • 保证自己不被上游服务压垮
  • 保证自己不被下游服务拖垮
  • 保证自己不受外界环境影响

解决雪崩问题的常见方式有四种:

1.超时处理

超时处理:设定超时时间,请求超过一定时间没有响应就返回错误信息,不会无休止等待

2.仓壁模式

方案2:仓壁模式

仓壁模式来源于船舱的设计:Image

船舱都会被隔板分离为多个独立空间,当船体破损时,只会导致部分空间进入,将故障控制在一定范围内,避免整个船体都被淹没。

于此类似,仓壁模式可以限定每个业务能使用的线程数,避免耗尽整个tomcat的资源,因此也叫线程隔离。

3.断路器

断路器模式:由断路器统计业务执行的异常比例,如果超出阈值则会熔断该业务,拦截访问该业务的一切请求。

4.限流

流量控制:限制业务访问的QPS(每秒钟请求数量),避免服务因流量的突增而故障。

所以什么是雪崩问题?
微服务之间相互调用,因为调用链中的一个服务故障,引起整个链路都无法访问的情况。
可以认为:
限流是对服务的保护,避免因瞬间高并发流量而导致服务故障,进而避免雪崩。是一种预防措施。
超时处理、线程隔离、降级熔断是在部分服务故障时,将故障控制在一定范围,避免雪崩。是一种补救措施。

Sentinel 下载使用

下载地址:https://github.com/alibaba/Sentinel/releases

Image

Sentinel分为两个部分:

核心库:不依赖任何框架/库,只需要Java运行时环境,同时对Dubbo\SpringCloud等框架也有很好的支持
控制台:基于SpringBoot开发,打包后可以直接运行,不需要额外的应用容器

注意:jdk1.8环境/8080端口不能被占用

启动命令:java -jar sentinel-dashboard-1.8.4.jar
Image

访问地址:http://localhost:8080/

账号密码:sentinel/sentinel

Image

这里Sentinel就安装成功了,在界面上没有发现监控的服务,这因为我们还没有启动项目,而Sentinel本身采用的是懒加载模式,要先去访问服务对应的接口,Sentinel才会进行工作。

接下来来搭建我们的测试项目

搭建Sentinel 测试项目

Sentinel官方参考文档:https://sentinelguard.io/zh-cn/docs/quick-start.html

注意:这里我们使用到了Nacos,启动一个端口为8848的Nacos就行

导入依赖:

<!-- Nacos客户端依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- sentinel依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

配置属性:

server:
port: 8006

spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
#配置Sentinel地址,就是我们的WEB界面
dashboard: localhost:8080
#Sentinel配置默认8719端口,被占用端口会自动从+1,直到找到未被占用的端口
port: 8719

management:
endpoints:
web:
exposure:
include: '*'

测试类:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;

@RestController
public class TestController {

@GetMapping("/playA")
public String playA() {
return "hello my name is playA ,wo shi boy";
}

@GetMapping("/playB")
public String playB(){
return "hi my name is playB, me girl";
}
}

最后在启动类上加上 :@EnableDiscoveryClient,点击启动,访问我们的测试地址:

http://localhost:8006/playA

http://localhost:8006/playB

访问之后,我们在Sentinel上看到监控信息如下所示:
Image

Sentinel 流控规则

Image

上图是我们要讲解的全部内容,主要有分为以下几点:

资源名:流控规则中唯一的名称,默认我们的请求路径

针对来源:Sentinel 对调用者进行限流,填写微服务名,默认为default,对来源不进行区分

阈值类型/单机阈值:

QPS(每秒请求数量),使用该类型时,QPS达到我们设置的单机阈值,进行限流
线程数:当使用该类型时,线程数量达到我们设置的单机阈值,进行限流
是否集群:默认否,如果是集群勾选

流控模式:

直接:API达到限流条件时直接限流,如果我们设置QPS为1,如果大于这个数量直接返回错误
关联:当关联的资源达到阈值时,限流自己,比如A调用B,B达到了阈值,A进行限流
链路:只记录链路上的流量,指定对应的链路路径,从入口开始,如果达到阈值,则进行限流

流控效果:

快速失败:直接抛异常
Warm Up:根据冷加载因子codeFactor经过预热时长,才达到设置的QPS阈值
排队等待:匀速排队,让请求以匀速速度进行请求,阈值类型,需要设置为QPS,否则无效

我们先来新增一个流控规则,操作方式有两种

在流控规则中添加
在簇点链路中添加

因为方便,我们一般会选择在簇点链路中添加,我们先来试一下QPS的操作:
Image

Image

这里我们设置单机阈值为1,所以playA这个接口一秒中只能被访问一次,如果超过,则进行限流操作进行一个阻塞操作,这个效果我们是可以直接看到的,当我们不停的刷新playA时,就会现在如下信息,而没有设置的playB,则不会

Image

在这里我们如果设置为线程数会怎么样呢?

在这里我们要注意:如果项目重新启动,需要将修改后的playA,重新访问后重新,添加流控规则

Image

同时我们需要在代码中设置延时执行,如果处理太快,我们是看不到实际效果的,如果有兴趣的小伙伴可以自己启动线程去跑,在这里我们设置playA,进行一秒钟的延时操作,

       @GetMapping("/playA")
public String playA() {
try {
//阻塞1 秒
TimeUnit.MILLISECONDS.sleep(1000);
}catch (Exception e){
e.printStackTrace();
}
return "hello my name is playA ,wo shi boy";
}

这里使用两个不同浏览器去跑,同一个浏览器使用的是同一线程,先请求的某歌,后请求的某火,

效果如下所示:

Image

QPS和并发线程数的规则如下所示:

Image

总结

对比与其他的断流产品(Hystrix)而言,sentinel 不需要我们自己手动搭建监控平台,而且它有一套属于自己的Web界面,可对多种指标进行流控、熔断,且提供了实时监控和控制面板,功能更为强大。

Sentinel规则

1. 流控规则

流量控制,其原理是监控流量的QPS(每秒查询率)或者并发线程数等指标
1.1流控模式

  • 直接(默认)

  • 关联(当关联的资源达到限流条件时,开启限流(适用于资源让步))

  • 链路(当从某个接口的过来的资源达到限流时,开启限流,有点类似于针对来源配置项,区别在针对来源配置项针对上级微服务,链路流控针对于上级接口,也就是粒度最细)
    如果要使链路规则生效,则版本需要2.1.1之后,并且增加配置

    spring.cloud.sentinel.web-context-unify=false

1.2 流控效果

  • 快速失败

  • warm up(预热)

  • 排队等待

2. 降级规则

降级规则指的就是在满足什么条件的时候对服务进行降级

  • 慢调用比例
    RT:平均响应时间
    时间窗口:降级持续时间
    当平均响应时间 大于 输入的值的时候,进入预降级状态,如果1秒内持续进入的请求响应时间依然大于输入的值,则进入降级状态,降级时间为时间窗口输入的值

  • 异常比例
    当资源的每秒异常总数占总量的比例超过阈值后,就会进入降级状态

  • 异常数
    当1分钟之内的异常数大于异常数,则进入降级状态,注意 时间窗口需要大于60秒

3. 热点规则

热点参数流控规则是一种更细粒度的规则,它允许将规则具体细化到具体的参数上

4. 授权规则

自定义授权规则,继承 RequestOriginParse,自定义授权。

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Configuration;

import javax.servlet.http.HttpServletRequest;

/**
* 自定义授权规则
*
* @author mrhy
* @date 2020/10/3 11:25 下午
* Copyright (C), 2018-2020
*/

@Configuration
public class MyRequestOriginParser implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest request) {
// 判断来源或者指定带有的规则
String origin = request.getHeader("origin");
if (StringUtils.isEmpty(origin)){
throw new RuntimeException("origin is not empty");
}
return origin;
}
}

5. 系统规则

(不推荐)

文:一只阿木木

欢迎转发、交流小数据。

Image

松花酿酒,春水煎茶。

眉上风止,见字如晤。

一只阿木木  

Image