06_sentinel—分布式系统遇到的问题

sentinel—分布式系统遇到的问题

06_sentinel—分布式系统遇到的问题_第1张图片

sentinel—服务雪崩

服务雪崩效应:因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过程,就叫服务雪崩效应

sentinel—容错机制

  • 超时机制

在不做任何处理的情况下,服务提供者不可用会导致消费者清求线程强制等待,而造成系统资源耗尽。加入超时机制,一旦超时,就释放资源。由于释放资源速度较快,一定程度上可以抑制资源耗尽的问题。

  • 服务限流

  • 隔离

原理:用户的求将不再直接访问服务,而是通过线程池中的空闲线程来访问服务,如果线程池已满,则会进行降级处理,用户的请求不会被堵塞,至少可以看到一个执行结果((例如返回友好的提示信息),而不是无休止的等待或者看到系统崩溃。

  • 服务熔断(保险丝的概念)

远程服务不稳定或网络抖动时暂时关闭,就叫服务熔断。

  • 服务降级(B计划的概念)

有服务熔断,必然要有服务降级。

所谓降级,就是当某个服务熔断之后,服务将不再被调用,此时客户端可以自己准备一个本地的fallback(回退)回调,返回一个缺省值,例如:(备用接口缓存/mock数据),这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强,当然这也要看适合的业务场景。

sentinel—介绍

sentinel是阿里巴巴开源的,面向分布式服务架构的高可用防护组件

06_sentinel—分布式系统遇到的问题_第2张图片

sentinel具有以下特征:

  • 丰富的应用场景: Sentiel承接了阿里巴巴近10年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范国)、消息削峰填谷、实时熔断下游不可用应用等
  • 完备的实时监控: Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至500台以下规模的集群的汇总运行情况。
  • 广泛的开源生态: Sertinel提供开箱即用的与其它开源框架库的整合模块,例如与spring Cloud、Dubbo, gRPC的整合,您只需要引入相应的依赖并进行简单的配置即可快速地接入Sentinel。
  • 完善的SPI扩展点: Sentinel提供简单易用、完善的SPI扩展点。您可以通过实现扩展点,快速的定制逻辑。例如定制规则管理、适配数据源等。

06_sentinel—分布式系统遇到的问题_第3张图片

sentinel和Hystrix对比

06_sentinel—分布式系统遇到的问题_第4张图片

sentinel—流控规则初体验

Sentinel 可以简单的分为Sentinel核心库和Dashboard

核心库不依赖Dashboard,但是结合Dashboard可以取得最好的效果。

1.创建项目导入依赖


<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.3.7.RELEASEversion>
        <relativePath/>
    parent>
    <modelVersion>4.0.0modelVersion>
    <artifactId>sentinel-demoartifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        
        <dependency>
            <groupId>com.alibaba.cspgroupId>
            <artifactId>sentinel-coreartifactId>
            <version>1.8.0version>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <version>1.18.20version>
        dependency>
        
        <dependency>
            <groupId>com.alibaba.cspgroupId>
            <artifactId>sentinel-annotation-aspectjartifactId>
            <version>1.8.0version>
        dependency>
    dependencies>

project>

2.controller层

package com.tian.sentinel.controller;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer;
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 lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.util.ArrayList;

@RestController
@Slf4j
public class HelloController {
    private static final String RESOURCE_NAME ="hello";
    private static final String USER_RESOURCE_NAME="user";
    private static final String DEGRADE_RESOURCE_NAME="degrade";
    //进行流控
    @RequestMapping(value = "/hello")
    public String hello(){
        Entry entry=null;
        try {
            //sentinel针对资源进行限制
            entry= SphU.entry(RESOURCE_NAME);
            //被保护的业务逻辑
            String str = "hello world";
            log.info("-------"+str+"--------");
            return str;
        }catch (BlockException e1){
            //资源访问阻止,被限流或被降级
            //进行对应的处理操作
            log.info("block!");
            return  "被流控了!";
        }catch (Exception ex){
            //若需要配置降级规则,需要通过这种方式记录业务异常
            Tracer.traceEntry(ex,entry);
        }finally {
            if (entry != null) {
                entry.exit();
            }
        }
        return null;
    }


    @PostConstruct
    private static void initFlowRules(){
        //流控规则
        ArrayList<FlowRule> rules = new ArrayList<>();
        //流控
        FlowRule rule = new FlowRule();
        //为那个资源进行流控
        rule.setResource(RESOURCE_NAME);
        //设置受保护的资源阈值
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule.setCount(1);
        rules.add(rule);

        //加载配置好的规则
        FlowRuleManager.loadRules(rules);


    }
}

3.主启动类

4.application.yml

server:
  port: 8060

5.测试访问

http://localhost:8060/hello

一秒点击一次 访问没问题 显示 hello world

一秒点击2次或以上,显示被限流了

sentinel—@SentinelResource

改善接口中资源定义和被流控降级后的处理方法

1.添加依赖


<dependency>
    <groupId>com.alibaba.cspgroupId>
    <artifactId>sentinel-annotation-aspectjartifactId>
    <version>1.8.0version>
dependency>

2.配置@bean

//注解支持的配置Bean
@Bean
public SentinelResourceAspect sentinelResourceAspect(){
    return new SentinelResourceAspect();
}

3.pojo

@Data
public class User {
    private final String username;
}

4.controller

package com.tian.sentinel.controller;

@RestController
@Slf4j
public class HelloController {
    private static final String RESOURCE_NAME ="hello";
    private static final String USER_RESOURCE_NAME="user";
    private static final String DEGRADE_RESOURCE_NAME="degrade";


    @PostConstruct
    private static void initFlowRules(){
        //流控规则
        ArrayList<FlowRule> rules = new ArrayList<>();
        //流控
        FlowRule rule = new FlowRule();
        //为那个资源进行流控
        rule.setResource(RESOURCE_NAME);
        //设置受保护的资源阈值
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule.setCount(1);
        rules.add(rule);

        FlowRule rule2 = new FlowRule();
        rule2.setResource(USER_RESOURCE_NAME);
        rule2.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule2.setCount(1);
        rules.add(rule2);

        //加载配置好的规则
        FlowRuleManager.loadRules(rules);


    }

    /**
     * value 定义资源
     * blockHandler 设置 流控降级后的处理方法 (默认该方法必须声明在同一个类)
     * 如果不想在同一个类,用blockHandlerClass 但是方法必须加上static关键字
     * fallback 当接口出现了异常,就可以交给fallback指定的方法进行处理
     * blockHandler > fallback
     * fallbackClass 和 用blockHandlerClass一样的用法
     * @return
     */
    @RequestMapping("/user")
    @SentinelResource(value = USER_RESOURCE_NAME,
            fallback = "fallbackHandlerForGetUser",
            blockHandler = "blockHandlerForGetUser")
    public User getUser(String id){
//        int i=1/0;
        return new User("tian");
    }

    /**
     * 1.一定要public
     * 2.返回值一定要和源方法(上面的)保证一致,包含源方法的参数.顺序也要一样
     * 3.必须在参数最后添加BlockException,可以区分是什么规则的处理方法
     * @return
     */
    public User blockHandlerForGetUser(String id,BlockException ex){
        ex.printStackTrace();
        return new User("流控!!!");
    }

    public User fallbackHandlerForGetUser(String id,Throwable e){
        e.printStackTrace();
        return new User("异常处理");
    }
}

5.配置文件

server:
  port: 8060

6.主启动类

@SpringBootApplication
public class StartApplication {
    public static void main(String[] args) {
        SpringApplication.run(StartApplication.class,args);
    }

    //注解支持的配置Bean
    @Bean
    public SentinelResourceAspect sentinelResourceAspect(){
        return new SentinelResourceAspect();
    }
}

7.测试访问

http://localhost:8060/user

现象:点击速度快,会被流控

sentinel—降级规则初体验

同上controller再加上代码

@PostConstruct  //初始化
    public void initDegradeRule(){
        //降级规则    异常
        ArrayList<DegradeRule> degradeRules = new ArrayList<>();
        DegradeRule degradeRule = new DegradeRule();
        degradeRule.setResource(DEGRADE_RESOURCE_NAME);
        //设置规则测率 : 异常数
        degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
        //出发熔断异常数: 2
        degradeRule.setCount(2);
        //出发熔断的最小请求数 : 2
        degradeRule.setMinRequestAmount(2);
        //统计时长  单位 ms   1分钟
        degradeRule.setStatIntervalMs(60*1000); //时间太短不好测
        //一分钟内 :执行了2次,出现了2次异常

        //熔断持续时长: 10s
        //一但出发熔断,再次请求对应的接口就会直接调用降级方法
        //10s过后----半开状态,恢复接口请求调用,再次熔断,不会根据设置的条件进行
        degradeRule.setTimeWindow(10);

        degradeRules.add(degradeRule);
        DegradeRuleManager.loadRules(degradeRules);
    }

    @RequestMapping("/degrade")
    @SentinelResource(value = DEGRADE_RESOURCE_NAME,
            entryType = EntryType.IN,
            blockHandler = "blockHandlerForFb")
    public User degarde(String id) throws InterruptedException {
        // 异常数\比例
        throw new RuntimeException("异常---");
    }


    public User blockHandlerForFb(String id,BlockException ex){
        ex.printStackTrace();
        return new User("流控!!!");
    }

访问 http://localhost:8060/degrade 页面都是报500错误访问几次页面显示 流控 (在10s内一直访问页面显示都是流控,10s后的话页面显示500)

sentinel—控制台部署

下载控制台jar包并在本地启动 下载地址

java -jar sentinel-dashboard-1.8.0.jar 默认端口8080

访问localhost:8080

账号sentinel

密码sentinel

06_sentinel—分布式系统遇到的问题_第5张图片

自定义端口 用户名 密码 启动

java -Dserver.port=8888 -Dsentinel.dashboard.auth.username=tian -Dsentinel.dashboard.auth.password=123 -jar sentinel-dashboard-1.8.0.jar

客户端需要引入Transport模块来与sentinel控制台进行通信

导入依赖


<dependency>
    <groupId>com.alibaba.cspgroupId>
    <artifactId>sentinel-transport-simple-httpartifactId>
    <version>1.8.0version>
dependency>

idea中配置

-Dcsp.sentinel.dashboard.server=127.0.0.1:8888

06_sentinel—分布式系统遇到的问题_第6张图片

启动项目 随便访问一个 localhost:8060/user

发现sentinel监控有东西了

06_sentinel—分布式系统遇到的问题_第7张图片

sentinel—整合springcloud alibaba

1.引入依赖

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-webartifactId>
dependency>

<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>

2.添加yml配置文件

server:
  port: 8861
spring:
  application:
    name: order-sentinel
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8888

3.controller

@RestController
@RequestMapping("/order")
public class OrderController {
    @RequestMapping("/add")
    public String add(){
        System.out.println("下单成功!");
        return "hello world";
    }
}

4.主启动类

5.访问测试 http://localhost:8861/order/add

6.发现sentinel控制台 有记录

你可能感兴趣的:(sentinel,spring,cloud)