学相伴Sentinel流控与降级实现

Posted 狂神说

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学相伴Sentinel流控与降级实现相关的知识,希望对你有一定的参考价值。

介绍

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统自适应保护等多个维度来帮助您保障微服务的稳定性。

基本概念

资源

资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。
只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。

规则

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

我们下载sentinelv1.8.1版本的控制台

使用命令启动
这里server.port=9000表示在9000端口启动
csp.sentinel.dashboard.server指定指定控制台地址和端口
project.name指定应用名
更多的参数参见 启动参数文档。

java -Dserver.port=9000 -Dcsp.sentinel.dashboard.server=localhost:9000 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.1.jar

启动后可以访问一下localhost:9000
输入默认用户名密码sentinel

进来后可以看到当前只有我们本机一台,我们再配置一下我们的项目

新建项目,别忘了改镜像

勾选sentinelweb

然后在配置文件配置

spring:
  cloud:
    sentinel:
      transport:
        # Sentinel 控制台地址
        dashboard: localhost:9000
        # 如果有多套网络,又无法正确获取本机IP,则需要使用下面的参数设置当前机器可被外部访问的IP地址,供admin控制台使用
      #  client-ip:
      # 取消Sentinel控制台懒加载
      # 默认情况下 Sentinel 会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包
      # 配置 sentinel.eager=true 时,取消Sentinel控制台懒加载功能
      eager: true
      filter:
        # 配置启用拦截器
        enabled: true
        # 配置拦截器路径
        url-patterns: /**

最后启动项目

刷新控制台发现我们这台机器

我们编写一个接口,再重新启动

访问一下这个接口

成功访问后可以看到我们的簇点链路里多了这个接口

我们这里可以对它进行配置一个流控,点击流控按钮
配置QPS1

点击新增后我们每秒都只能请求一次了
请求多了则会被限流

我们还可以定义我们受保护的资源
简单来说,就是我们的代码块
下面这段代码可以直接试着运行一下

package com.ruben.simplesentinel;import com.alibaba.csp.sentinel.Entry;import com.alibaba.csp.sentinel.SphU;import com.alibaba.csp.sentinel.annotation.SentinelResource;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 java.util.ArrayList;import java.util.List;/**
 * sentinel测试类
 *
 * @author <achao1441470436@gmail.com>
 * @since 2021/6/29 0029 22:35
 */public class SimpleSentinelTests {    public static void main(String[] args) {        // 配置规则.
        initFlowRules();        while (true) {            // 1.5.0 版本开始可以直接利用 try-with-resources 特性
            try (Entry entry = SphU.entry("HelloWorld")) {                // 被保护的逻辑
                System.out.println("hello world");
            } catch (BlockException ex) {                // 处理被流控的逻辑
                System.out.println("blocked!");
            }
        }
    }    private static void initFlowRules() {
        List<FlowRule> rules = new ArrayList<>();
        FlowRule rule = new FlowRule();
        rule.setResource("HelloWorld");
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);        // Set limit QPS to 20.
        rule.setCount(20);
        rules.add(rule);
        FlowRuleManager.loadRules(rules);
    }

}

效果如下

我们除了使用FlowRuleManager.loadRules去配置资源流控规则以外,还可以直接在sentinel控制台进行配置


以及我们可以使用@SentinelResource注解

若我们的应用使用了Spring AOP,我们需要通过配置的方式将 SentinelResourceAspect 注册为一个 Spring Bean:

@Configurationpublic class SentinelAspectConfiguration {     @Bean
     public SentinelResourceAspect sentinelResourceAspect() {            return new SentinelResourceAspect();
     }
}

找个地方注入这个Bean以后
我们在service实现类中写上这个注解

package com.ruben.simplesentinel.service.impl;import com.alibaba.csp.sentinel.annotation.SentinelResource;import com.ruben.simplesentinel.service.IHelloWorldService;import org.springframework.stereotype.Service;/**
 * helloWorld业务层实现类
 *
 * @author <achao1441470436@gmail.com>
 * @since 2021/6/29 0029 22:44
 */@Servicepublic class HelloWorldServiceImpl implements IHelloWorldService {    @SentinelResource("HelloWorld")    @Override
    public void helloWorld() {        // 资源中的逻辑
        System.out.println("hello world");
    }

}

然后调用

package com.ruben.simplesentinel;import com.alibaba.csp.sentinel.annotation.SentinelResource;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 com.ruben.simplesentinel.service.IHelloWorldService;import org.junit.jupiter.api.Test;import org.springframework.boot.test.context.SpringBootTest;import javax.annotation.Resource;import java.util.ArrayList;import java.util.List;@SpringBootTestclass SimpleSentinelApplicationTests {    @Resource
    private IHelloWorldService helloWorldService;    @Test
    void contextLoads() {
        initFlowRules();        while (true) {
            helloWorldService.helloWorld();
        }
    }    private static void initFlowRules() {
        List<FlowRule> rules = new ArrayList<>();
        FlowRule rule = new FlowRule();
        rule.setResource("HelloWorld");
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);        // Set limit QPS to 20.
        rule.setCount(20);
        rules.add(rule);
        FlowRuleManager.loadRules(rules);
    }

}

可以看到在执行20次后抛出了java.lang.reflect.UndeclaredThrowableException
并且是由我们com.alibaba.csp.sentinel.slots.block.flow.FlowException导致的

除了进行限流,我们还可以直接配置降级


当我们请求几次后,就不会再执行我们的方法抛出NPE了,因为此时我们配置的服务降级生效

小结

通过配置sentinel限流与降级,提升了我们程序的健壮性,使得其不至于在高并发场景下压力过大。学习一门新的技术,其实查阅官方文档极其重要,这也是我的首要学习方式之一!其次就是一定要有输出,写博客、写笔记都是很棒的输出方式,希望大家能有所收获!


看完记得点个在看吧,这对我们很重要哦~


长按扫码关注平台最新动态

以上是关于学相伴Sentinel流控与降级实现的主要内容,如果未能解决你的问题,请参考以下文章

Sentinel

springboot sentinel使用示例(基于sentinel 1.8),流控,降级,sentinel-dashboard使用,blockHandler和fallback

SpringCloud 学习笔记总结

SpringCloud 学习笔记总结

配置容错组件 Sentinel

sentinel整合springcloud alibaba