SpringCloudAlibaba 学习第二节 Sentinel第一节

Sentinel 简介

    Sentinel是面向云原生微服务的高可用流控防护组件、分布式系统的流量防卫兵。随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。官网详细介绍与文档,之前学习Hystrix时,需要手动搭建监控平台、没有一套完整的web界面可以提供更细粒度化的配置,比如流控、速率控制、服务熔断、服务降级等等。Sentinel是一个单独的组件,可以独立出来;界面化的细粒度统一配置。
    Sentinel的主要特性
在这里插入图片描述

Sentinel 控制台

    Sentinel组件由两部分构成:1、核心库,(Java客户端)不依赖任何框架/库,能够运行于所有的Java运行时环境,同时对Spring Cloud 等框架有较好的支持。2、控制台(Dashboard)基于SpringBoot开发,打包后直接运行,无需额外的Tomcat等应用程序。粗略的来说就是后台和前台8080。Sentinel的下载地址https://github.com/alibaba/Sentinel/releases,可以直接下载jar包运行。
    运行方式 可以直接使用 java -jar sentinel-dashboard-1.8.0.jar但是要保证Java8环境和8080端口不被占用,修改端口可以使用官网推荐的启动方式java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar,将端口替换为10010 避免端口端口冲突。官网介绍中有更多详细配置,更多需求请参考官方网站配置信息

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
其中 -Dserver.port=8080 用于指定 Sentinel 控制台端口为 8080
从 Sentinel 1.6.0 起,Sentinel 控制台引入基本的登录功能,默认用户名和密码都是 sentinel
用户可以通过如下参数进行配置:
-Dsentinel.dashboard.auth.username=sentinel 用于指定控制台的登录用户名为 sentinel;
-Dsentinel.dashboard.auth.password=123456 用于指定控制台的登录密码为 123456;如果省略这两个参数,默认用户和密码均为 sentinel;
-Dserver.servlet.session.timeout=7200 用于指定 Spring Boot 服务端 session 的过期时间,如 7200 表示 7200 秒;60m 表示 60 分钟,默认为 30 分钟;

在这里插入图片描述
在这里插入图片描述

Sentinel 初始化演示工程

    新建Module cloudalibaba-sentinel-service8401,做初始化演示
    pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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>
        <artifactId>zjt-cloud-api</artifactId>
        <groupId>com.zjt.cloud-api</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloudalibaba-sentinel-service8401</artifactId>

    <dependencies>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--SpringCloud ailibaba sentinel-datasource-nacos 后续做持久化用到-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
        <!--SpringCloud ailibaba sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!--openfeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!-- SpringBoot整合Web组件+actuator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--日常通用jar包配置-->

        <dependency>
            <groupId>com.zjt.cloud-api</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

     application.yml

server:
  port: 8401

spring:
  application:
    name: cloud-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #Nacos服务注册中心地址
    sentinel:
      transport:
        dashboard: localhost:10010 #配置Sentinel dashboard地址
        port: 8719 #本地启动 HTTP API Server 的端口号 若端口冲突会自动向下探测可用的端口
                   # 指定应用与sentinel控制台交互的端口,本地应用会起一个占用该端口的 Http Server
                   # 这里的 spring.cloud.sentinel.transport.port 端口配置会在应用对应的机器上启动一个 Http Server,
                   # 该 Server 会与 Sentinel 控制台做交互。比如 Sentinel 控制台添加了一个限流规则,
                   # 会把规则数据 push 给这个 Http Server 接收,Http Server 再将规则注册到 Sentinel 中

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

     主启动类和业务类

package com.zjt.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

import java.util.TimeZone;

/**
 * @author zjt
 * @date 2020-09-30
 */
@SpringBootApplication
@EnableDiscoveryClient
public class CloudAlibabaSentinel8401Application {

    public static void main(String[] args) {
        // 时区设置
        TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
        SpringApplication.run(CloudAlibabaSentinel8401Application.class, args);
    }

}
package com.zjt.cloud.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

/**
 * @author zjt
 * @date 2020-09-30
 */
@RestController
@RequestMapping("/sentinel")
public class SentinelController {

    @GetMapping("/ok")
    public String ok() {
        return "OK";
    }

    @GetMapping("/time-out")
    public String ok(Integer seconds) {
        try {
            TimeUnit.SECONDS.sleep(seconds);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return String.format("time-out->%d->-ok", seconds);
    }


}

    测试: 启动 Nacos 8848 、 sentinel dashboard 10010 、 启动项目 8401
在这里插入图片描述
    测试 发送请求
在这里插入图片描述
    查看 sentinel dashboard 的实时监控
在这里插入图片描述
在这里插入图片描述

Sentinel 流控规则 流量限制控制规则

    参考文档
在这里插入图片描述
    上图中信息简要解释说明
    资源名:唯一名称,默认是请求路径
    针对来源:Sentinel可以针对调用者进行限流,填写微服务名,默认default(不区分来源)
    阈值类型/单机阈值:1、QPS(每秒钟的请求数量):当调用该api的QPS达到设定的阈值,进行限流。2、线程数:当调用该api的线程数达到设定阈值,进行限流。
    是否集群:学习时暂时不需要集群
    流控模式:1、直接:api达到限流条件时,直接限流。2、关联:当关联的资源达到设定的阈值,就限流自己。3、链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流)[api级别的针对来源]
    流控效果:1、快速失败:直接失败,抛出异常。2、Warm Up :根据codeFactor(冷加载因子,默认值是 3 ) 从阈值/codeFactor,经过预热时长,才达到设置的QPS阈值。3、排队等待:匀速排队,让请求以匀速的速度通过,阈值类型必须设置为QPS,否则无效。
    流控模式:QPS直接失败,在没有任何配置的情况下,资源名默认为访问路径,需要保证唯一,先对该资源进行流控配置。
在这里插入图片描述
    新增流控规则,每秒请求数大于1直接快速失败
在这里插入图片描述
在这里插入图片描述
    测试,当请求大于当前QPS,将会被Sentinel直接阻塞限流
在这里插入图片描述
    流控模式:线程数直接失败。并发数控制用于保护业务线程池不被慢调用耗尽。例如,当应用所依赖的下游应用由于某种原因导致服务不稳定、响应延迟增加,对于调用者来说,意味着吞吐量下降和更多的线程数占用,极端情况下甚至导致线程池耗尽。为应对太多线程占用的情况,业内有使用隔离的方案,比如通过不同业务逻辑使用不同线程池来隔离业务自身之间的资源争抢(线程池隔离)。这种隔离方案虽然隔离性比较好,但是代价就是线程数目太多,线程上下文切换的 overhead 比较大,特别是对低延时的调用有比较大的影响。Sentinel 并发控制不负责创建和管理线程池,而是简单统计当前请求上下文的线程数目(正在执行的调用数目),如果超出阈值,新的请求会被立即拒绝,效果类似于信号量隔离。并发数控制通常在调用端进行配置
    新增controller方法和配置规则

@GetMapping("test-thread")
    public String testThreadFlowLimiting() {
        try {
            TimeUnit.MILLISECONDS.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "testOK";
    }

在这里插入图片描述
    测试 postman 使用循环请求
在这里插入图片描述
在这里插入图片描述
    postman循环请求时去访问会看到被直接限流
在这里插入图片描述
    流控模式,关联。当两个资源之间具有资源争抢或者依赖关系的时候,这两个资源便具有了关联。比如对数据库同一个字段的读操作和写操作存在争抢,读的速度过高会影响写得速度,写的速度过高会影响读的速度。如果放任读写操作争抢资源,则争抢本身带来的开销会降低整体的吞吐量。可使用关联限流来避免具有关联关系的资源之间过度的争抢,举例来说,read_db 和 write_db 这两个资源分别代表数据库读写,我们可以给 read_db 设置限流规则来达到写优先的目的:设置 strategy 为 RuleConstant.STRATEGY_RELATE 同时设置 refResource 为 write_db。这样当写库操作过于频繁时,读数据的请求会被限流。
    controller添加两个方法

@PostMapping("/write")
    public String write() {
        try {
            TimeUnit.MILLISECONDS.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "write";
    }

    @GetMapping("/read")
    public String read() {
        try {
            TimeUnit.MILLISECONDS.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "read";
    }

    针对read接口新增流控规则
在这里插入图片描述
    测试使用postman模拟并发操作,请求write接口
    在这里插入图片描述
    请求读接口直接被Sentinel限流
在这里插入图片描述
    流控效果:Warm Up 限流 冷启动
    当流量突然增大的时候,我们常常会希望系统从空闲状态到繁忙状态的切换的时间长一些。即如果系统在此之前长期处于空闲的状态,我们希望处理请求的数量是缓步的增多,经过预期的时间以后,到达系统处理请求个数的最大值。Warm Up(冷启动,预热)模式就是为了实现这个目的的。下图配置的简要解释,单机最大阈值是10,预热时长是5秒,QPS突然提升时,一部分请求将会被限流,阈值逐步提高,5秒后阈值提升到10。公式阈值除以冷加载因子(coldFactor 默认值是3)经过预热时长后达到阈值
在这里插入图片描述
    测试 某些请求会被阻塞
在这里插入图片描述
    流控效果:排队等待
    匀速排队(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。
在这里插入图片描述
    配置
在这里插入图片描述
    测试 jmeter压力测试
在这里插入图片描述
在这里插入图片描述
    等待时间超过5秒的全部被限流
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值