SpringCloud Alibaba五大组件之——Sentinel

SpringCloud Alibaba五大组件之------Sentinel(文末附有完整项目GitHub链接)

前言

前文,我们已经介绍了SpringCloud Alibaba五大组件中的两个:dubbo和nacos,文章连接:太细了有手就行,SpringCloud Alibaba+Nacos+Dubbo整合,有需要的可以去查阅。
ps:本文用到的项目demo也是基于这篇文章去扩展的,包括模块结构和版本依赖等等。

一、什么是Sentinel

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、流量路由、熔断降级、系统自适应过载保护、热点流量防护等多个维度保护服务的稳定性。

Sentinel 具有以下特征:

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

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

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

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

Sentinel 的主要特性:

上面内容都是引用于官网

二、Sentinel控制台

官方提供两种方式跑控制台,我建议没有特殊需求下,通通用第一种就行

1.下载jar包

打来Sentinel的官网:https://github.com/alibaba/Sentinel/releases,找到自己需要的版本下载,本文编写时最高版本是1.8.8,本文用的是1.8.6版本

版本问题作者这里再啰嗦一句,一定要选对,因为我这一系列文章,SpringCloud alibaba定的是2021.0.6.0,所以一切版本如下图来选,直接毕业版本。

2.自己打包

下载整个工程,用mvn clean package打成jar包

3.启动控制台

打开cmd,进入jar包的目录,执行一下代码:

java 复制代码
java -Dserver.port=8180 -Dcsp.sentinel.dashboard.server=localhost:8180 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.6.jar

其中 -Dserver.port=8180 用于指定 Sentinel 控制台端口为 8180,默认8080

dashboard.server:网页的端口,客户端必须按指定的访问,也可以省略,默认是127.0.0.1:8080

4.浏览器访问

访问:http://localhost:8180,默认账户和密码都是sentinel

登录,显示这个界面则成功

三、项目中引入Sentinel

1.在api-service模块的pom文件引入依赖:

csharp 复制代码
 <dependency>
     <groupId>com.alibaba.cloud</groupId>
     <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
 </dependency>

2.application.yml

修改配置文件,新加如下配置:

yaml 复制代码
spring:
  cloud:
    sentinel:
      transport:
        port: 8719
        dashboard: localhost:8180

此处的port,默认是8179,主要就是项目启动后,会自行启动一个HTTP server,通过这个端口和sentinel客户端进行交互,来传输数据。

dashboard: localhost:8180,这个要和上一步启动sentinel控制台时候的ip端口一致。

3.补充:jvm启动参数

只要你前面配置和项目都正确,这一步可以省略,但是如果你项目启动,sentinel控制台服务注册不上,你就jvm加入下面参数:

java 复制代码
-Dcsp.sentinel.dashboard.server=127.0.0.1:8180

4.编写简单的测试程序

controller:

java 复制代码
@RestController
@RequestMapping("/testSentinel")
public class SentinelController {

    @Resource
    UserInfoService userInfoService;

    @RequestMapping("/one")
    public void testThree() {
        userInfoService.testSentinel();
    }
}

service:

java 复制代码
@Service
public class UserInfoServiceImpl{

    @Override
    @SentinelResource(value = "testSentinel", blockHandler = "testBlockHandler", fallback = "testFallback")
    public void testSentinel() {
        System.out.println("testSentinel");
        //这行代码是为了测试报错熔断,如果只是流控测试,此行代码可以屏蔽
        //int a = 1/0;
    }

    public void testBlockHandler(BlockException ex) {
        System.out.println("进入testBlockHandler");
    }

    public void testFallback(Throwable e) {
        System.out.println("进入testFallback");
        e.printStackTrace();
    }
}

浏览器访问一下接口

查看控制台,这里可以看到我们的测试接口,项目已经集成好了sentinel

PS:1.因为sentinel是懒加载,这里一定要浏览器随便访问一个接口,不然服务注册不上,也可以添加配置:spring.cloud.sentinel.eager:true实现服务器启动了自动心跳注册。
2.访问了要等个几秒钟,有延迟,刷新一下就能看到了。

5.@SentinelResource注解

常用的几个注解参数:

  • value:定义资源名
  • blockHandler:会在原方法被限流/降级/系统保护的时候调用,记得方法定义在同一个类中。
  • fallback: 会针对所有类型的异常,出现时调用
  • defaultFallback:全局默认出异常时候调用,定义了fallback,则此参数不生效

6.其他方式

当然除了注解之外,还提供了其他编码方式去控制一段代码或者一个方法的访问,比如最常见的SphU.entry,大家也可以去官网上查阅根据需求选择

java 复制代码
try {
  // 资源名可使用任意有业务语义的字符串,注意数目不能太多(超过 1K),超出几千请作为参数传入而不要直接作为资源名
  // EntryType 代表流量类型(inbound/outbound),其中系统规则只对 IN 类型的埋点生效
  entry = SphU.entry("自定义资源名");
  // 被保护的业务逻辑
  // do something...
} catch (BlockException ex) {
  // 资源访问阻止,被限流或被降级
  // 进行相应的处理操作
} catch (Exception ex) {
  // 若需要配置降级规则,需要通过这种方式记录业务异常
  Tracer.traceEntry(ex, entry);
} finally {
  // 务必保证 exit,务必保证每个 entry 与 exit 配对
  if (entry != null) {
    entry.exit();
  }
}

四、规则讲解

这里会讲几个常用的配置,其余的配置大家可以去官方查看:sentinel官网,配置规则主要有两种方式,第一种是代码中硬编码,第二种是通过控制台配置的形式

1.代码中硬编码

先介绍下,java代码中的几个规则对象:

  • DegradeRule:熔断降级,主要是当一个接口不可访问后,进行的一系列操作,避免所有请求堵塞
  • AuthorityRule: 授权规则(来源访问),判断来源请求是否放行,常用的场景是黑白名单
  • FlowRule: 流量控制规则,监控QPS,避免系统被瞬时的流量高峰冲垮
  • ParamFlowRule: 热点参数限流,可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效
  • SystemRule:系统保护规则,当系统负载高于某个阈值,就禁止或者减少流量的进入;当 load 开始好转,则恢复流量的进入

当然还有网关控制和集群流量控制,这两者在代码中无法实现,只有通过控制台配置。

我们就拿熔断规则来举例,在service中,增加如下规则初始化方法:

java 复制代码
    @PostConstruct
    public void initRule() {
        //熔断规则: 5s内调用接口出现异常次数超过5的时候, 进行熔断
        List<DegradeRule> degradeRules = new ArrayList<>();
        DegradeRule rule = new DegradeRule();
        rule.setResource("testSentinel");
        rule.setCount(5);
        //统计时长
        rule.setStatIntervalMs(5000);
        rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);//熔断规则
        //熔断时长
        rule.setTimeWindow(10);
        degradeRules.add(rule);
        DegradeRuleManager.loadRules(degradeRules);
    }

大家可以在文末获取代码自行去测试。

2.控制台配置(生产环境中不推荐)

控制台中我们有两种方式去添加流控规则

第一种方式:

(1)左侧菜单栏添加


注意这里的资源名,和我们代码中的资源名要匹配,不然配置不会生效。

(2)簇点链路中添加


在链路中添加,可以保证我们的资源名是一定存在的,两种添加方式,你自己选择喜欢的。

3.为何不推荐控制台中添加

因为控制台中添加规则,会推送到项目的内存中,重启就没了,不能持久化,所以在生产环境中不推荐,总不能你每次重启项目都要单独配置一次。

五、生产环境下,规则集成Nacos

生产环境下,都用的Nacos统一管理规则,就是常说的push规则,通过Nacos推送到sentinel控制台,然后再更新到项目中。这样即使项目重启,只要Nacos还在,配置就是接近持久化的状态。

1.引入依赖

由于spring-cloud-starter-alibaba-sentinel 的Maven依赖并没有引入Nacos相关的,所以我们要单独引入依赖:

xml 复制代码
  <dependency>
      <groupId>com.alibaba.csp</groupId>
      <artifactId>sentinel-datasource-nacos</artifactId>
  </dependency>

2.Nacos中新增config

新增一个流量控制的config

选取json格式:

yaml 复制代码
[
    {
        "resource": "testSentinel",
        "limitApp": "default",
        "grade": 1,
        "count": 2,
        "strategy": 0,
        "controlBehavior": 0,
        "clusterMode": false
    }
]
  • resource:资源名,即限流规则的作用对象
  • limitApp:流控针对的调用来源,若为 default 则不区分调用来源
  • grade:限流阈值类型(QPS 或并发线程数);0代表根据并发数量来限流,1代表根据QPS来进行流量控制
  • count:限流阈值
  • strategy:调用关系限流策略
  • controlBehavior:流量控制效果(直接拒绝、Warm Up、匀速排队)
  • clusterMode:是否为集群模式

3.application.yml文件修改

在前面的基础上,新增datasource的配置:

注意,这里的nacos一定要和上一步新增的对应,

yaml 复制代码
spring:
  cloud:
    sentinel:
      transport:
        port: 8719
        dashboard: localhost:8180
      datasource:
        ds:
          nacos:
            server-addr: 172.16.72.132:8848
            data-id: sentinel-rule
            namespace: 76dae550-4133-44d8-b591-dc82f5f97b6e
            group-id: SENTINEL_PROVIDER_GROUP
            username: nacos
            password: nacos
            data-type: json
            rule-type: flow

由于spring.cloud.sentinel.datasource属性对应的是一个Map,所以它的需要自定义指定Map的KEY,下面的配置中ds就作为KEY,然后后面就可以配置不同的数据源

4.重启

重启后,查看sentinel控制台,可以看到我们在nacos定义的规则

测试一下新加的流控规则,我们是定义的qps不超过2,超过的请求全部拒绝(默认),这里补充一下拒绝策略。

  • 快速失败:超过设置阈值的请求全部拒绝,请求失败
  • Warm Up :
  • 排队等待:

可以看到,标记1和标记2都能正常打印,当第三个请求来了的时候,"进入testFallback"就不打印了,转而进入了blockHandler方法,说明流控是生效了的。

六、结语

到这里,SpringCloud alibaba五大组件之一的流控熔断降级sentinel就讲解完了,欢迎大家评论区指点,后面还剩两个组件:分布式队列RocketMQ和分布式事务Seata,RocketMQ可能会找个时间再写一篇文章,但是Seata的话,如果项目比较庞大,加上事务会顶不住,qps明显降低很多,我一个阿里工作的朋友给我谈过,他们项目组的微服务,都是裸奔的没有用事务,所以这文章我再考虑出不出,其实本文项目中的一个分支seata,我是已经实现了整合的,但是感觉生产环境中又不试用,就没有发出来,后面看情况吧

附上项目GitHub链接:https://github.com/wangqing-github/DubboAndNacos/tree/sentinel,选取sentinel分支。

相关推荐
wang_book6 小时前
Gitlab学习(007 gitlab项目操作)
java·运维·git·学习·spring·gitlab
一个诺诺前行的后端程序员8 小时前
springcloud微服务实战<1>
spring·spring cloud·微服务
Tatakai2511 小时前
Mybatis Plus分页查询返回total为0问题
java·spring·bug·mybatis
掐指一算乀缺钱13 小时前
SpringBoot 数据库表结构文档生成
java·数据库·spring boot·后端·spring
一叶飘零_sweeeet13 小时前
为什么 Feign 要用 HTTP 而不是 RPC?
java·网络协议·http·spring cloud·rpc·feign
bug菌¹13 小时前
滚雪球学SpringCloud[4.1讲]: Spring Cloud Gateway详解
java·spring cloud·微服务
bug菌¹14 小时前
滚雪球学SpringCloud[4.2讲]: Zuul:Netflix API Gateway详解
spring·spring cloud·gateway
小哇66614 小时前
spring-TransactionTemplate 编程式事务
数据库·spring
小筱在线15 小时前
SpringCloud微服务实现服务熔断的实践指南
java·spring cloud·微服务