微服务系列:Spring Cloud Alibaba 之 Sentinel 详细入门

在前面学习 Spring Cloud Gateway 的时候,我们已经使用过了 Sentinel 来进行限流,但是并没有对 Sentinel 进行详细的学习,那今天就要补上这块知识了。

话不多说,开始今天的学习。

Sentinel 介绍

Sentinel 是阿里中间件团队开源的,面向分布式服务架构的轻量级高可用流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助用户保护服务的稳定性。

1. Sentinel 基本概念

  • 资源

资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。

只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。

  • 规则

围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。

2. Sentinel 特征

Sentinel 具有以下特征:

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

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

  • 广泛的开源生态: Sentinel 提供开箱即用的与其他框架/库的整合模块,例如与SpringCloud,Dubbo,gRPC的整合,您只需要引入响应的依赖并进行简单的配置即可快速接入Sentinel

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

3. Sentinel VS Hystrix

Sentinel 和之前常用的熔断降级库 Hystrix 有什么不同呐?

Hystrix 的不足之处:

  • 需要自己手工搭建监控平台
  • 没有一套 web 界面可以给我们进行更细粒度化的配置流控、速率控制、熔断、降级等
  • Hystrix 常用的线程池隔离会造成线程上下切换的 overhead 比较大。

Hystrix 的关注点在于以 隔离熔断 为主的容错机制,超时或被熔断的调用将会快速失败,并可以提供 fallback 机制。

而 Sentinel 的侧重点在于:

  • 多样化的流量控制
  • 熔断降级
  • 系统负载保护
  • 实时监控和控制台

项目集成

Sentinel 可以简单的分为 Sentinel 核心库和 Dashboard控制台。核心库不依赖 Dashboard,但是结合 Dashboard 可以取得最好的效果。

  • 核心库(Java 客户端):不依赖任何框架/库,能够运行于 Java 8 及以上的版本的运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
  • 控制台(Dashboard):Dashboard 主要负责管理推送规则、监控、管理机器信息等。

上面有说 资源是 Sentinel 的关键概念 使用 Sentinel 来进行资源保护,主要分为这几个步骤:

  1. 定义资源
  2. 定义规则
  3. 检验规则是否生效

看了上面这么多概念,感觉头都要秃了,我们还是来实战试试吧。

1. 下载启动

我们可以从https://github.com/alibaba/Sentinel/releases下载sentinel-dashboard-$version.jar包。

我们可以用以下命令来启动下载的 jar 包:

java -Dserver.port=8718 -jar sentinel-dashboard-1.8.3.jar

其中 -Dserver.port=8718 指定控制台端口

image.png

启动成功浏览器访问地址 http://localhost:8718 ,默认用户名密码:sentinel/sentinel

image.png

登录进去之后是这样的,空空如也,接下来我们就要看看到底如何使用了。

image.png

2. 如何集成

1、添加依赖

<!-- springcloud alibaba sentinel -->
<dependency>
	<groupId>com.alibaba.cloud</groupId>
	<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

<!-- SpringBoot Web -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>

2、添加 Sentinel 配置

server:
  port: 9201
spring:
  application:
    # 应用名称
    name: cloud-sentinel
  cloud:
    sentinel:
      transport:
        # 控制台地址
        dashboard: 127.0.0.1:8718

3、测试接口

@RestController
public class TestController {

    @GetMapping("/testA")
    public Object testA(){
        return "testA......";
    }

    @GetMapping("/testB")
    public Object testB(){
        return "testB......";
    }
}

4、启动项目,访问控制台

image.png

访问 Sentinel 控制台发现还是空空如也,这是怎么回事呐?

image.png

原来Sentinel控制台有懒加载机制,我们需要访问一次我们服务的接口,控制台才会出现相关信息

我们来访问一下接口 localhost:9201/testA

image.png

再次刷新 Sentinel 控制台,发现出现了很多请求相关信息

image.png

我们也可以在配置文件中配置 spring.cloud.sentinel.eager: true 属性来取消控制台懒加载

这一步,到这里项目只是成功集成了 Sentinel 并打开了控制台,关于控制台上的相关操作,此文暂不讨论,下篇文章开始学习。

使用案例

上面有说过,使用 Sentinel 来进行资源保护,主要分为这几个步骤:

  1. 定义资源
  2. 定义规则
  3. 检验规则是否生效

1. 定义资源

Sentinel 定义资源的方式有好几种,有抛出异常的方式、返回布尔值的方式、注解的方式等,我们不再逐个讲解,详情可以查看官方文档 basic-api-resource-rule (sentinelguard.io)

这里我们使用注解的方式来定义资源,Sentinel提供了@SentinelResource注解用于定义资源,并提供了AspectJ的扩展用于自动定义资源、处理BlockException等。

因为我们是通过 Spring Cloud Alibaba 接入的 Sentinel,则无需额外进行配置即可使用 @SentinelResource 注解,否则的话需要引入如下依赖:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-annotation-aspectj</artifactId>
    <version>x.y.z</version>
</dependency>

我们来看一下注解的使用案例

@Service
public class IUserServiceImpl implements IUserService {

    public static final String RESOURCE_NAME = "selectUserByName";

    @Override
    @SentinelResource(value = RESOURCE_NAME, blockHandler = "selectUserByNameBlockHandler", fallback = "selectUserByNameFallback")
    public String selectUserByName(String username) {
        return "{"userName": " + username + ", "age": 25}";
    }

    // 服务流量控制处理,注意细节,一定要跟原函数的返回值和形参一致,并且形参最后要加个BlockException参数,否则会报错,FlowException: null
    public String selectUserByNameBlockHandler(String username, BlockException ex)
    {
        System.out.println("selectUserByNameBlockHandler异常信息:" + ex.getMessage());
        return "{"code":"500","msg": "" + username + "服务流量控制处理"}";
    }

    // 服务熔断降级处理,函数签名与原函数一致或加一个 Throwable 类型的参数
    public String selectUserByNameFallback(String username, Throwable throwable)
    {
        System.out.println("selectUserByNameFallback异常信息:" + throwable.getMessage());
        return "{"code":"500","msg": "" + username + "服务熔断降级处理"}";
    }
}

@SentinelResource注解包含以下属性:

参数描述
value资源名称,必需项(不能为空)
entryType资源调用方向,可选项(默认为EntryType.OUT
resourceType资源的分类
blockHandler对应处理BlockException的函数名称
blockHandlerClass处理类的Class对象,函数必需为static函数
fallback用于在抛出异常的时候提供fallback处理逻辑
defaultFallback用作默认的回退的方法
fallbackClass异常类的Class对象,函数必需为static函数
exceptionsToTrace异常类跟踪列表(默认为Throwable.class)
exceptionsToIgnore排除掉的异常类型

注意:注解方式埋点不支持 private 方法。

注意:

  • blockHandler / blockHandlerClass: blockHandler 对应处理 BlockException 的函数名称,可选项。blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。

官方注解支持文档:注解支持 · alibaba/Sentinel Wiki · GitHub

2. 定义规则

@SpringBootApplication
public class SentinelApplication {

    public static void main(String[] args) {
        SpringApplication.run(SentinelApplication.class, args);
        initFlowQpsRule();
    }

    //定义了每秒最多接收2个请求
    private static void initFlowQpsRule() {
        List<FlowRule> rules = new ArrayList<>();
        FlowRule rule = new FlowRule(IUserServiceImpl.RESOURCE_NAME);
        // set limit qps to 2
        rule.setCount(2);
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule.setLimitApp("default");
        rules.add(rule);
        FlowRuleManager.loadRules(rules);
    }
}
注意 FlowRule rule = new FlowRule(IUserServiceImpl.RESOURCE_NAME) 资源名称

流量控制规则(FlowRule)重要属性

参数描述描述
resource资源名,资源名是限流规则的作用对象
limitApp流控针对的调用来源,若为 default 则不区分调用来源default,代表不区分调用来源
grade限流阈值类型,QPS 模式(1)或并发线程数模式(0)QPS 模式
count限流阈值
strategy调用关系限流策略:直接、链路、关联根据资源本身(直接)
controlBehavior流量控制效果(直接拒绝、Warm Up、匀速排队)直接拒绝
clusterMode是否集群限流

3. 检验规则是否生效

@RestController
public class UserController {

    @Autowired
    private IUserService userService;

    @GetMapping("/user/getUserByName")
    public String getUserByName(String userName){
        return userService.selectUserByName(userName);
    }
}

浏览器访问地址 localhost:9201/user/getUserByName?userName=小黑

快速刷新几次接口之后触发限流

image.png

同时观察控制台簇点链路

image.png

总结

Sentinel 的功能强大,肯定不是我们一篇文章能容纳的,此文只是提供了一个入门案例,后面会继续学习 Sentinel 的其他知识。

PS: 都看到这里了,点个赞吧,彦祖

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值