Day99.Sleuth链路追踪(Zpikin)、Nacos注册与配置中心(集群 持久化)、Sentinel熔断与限流

目录

一、Sleuth 链路追踪 (了解)

1、zipkin 使用、介绍

二、SpringCloud Alibaba 简介

三、Alibaba Nacos服务注册和配置中心  ★★★

1、安装并运行Nacos

2、Nacos作为服务注册中心演示

3、Nacos 作为服务配置中心演示

4. 分类配置 (多环境配置)

4、Nacos 集群和持久化配置 ★★

1. derby 持久化存储到mysql 切换配置步骤

2. Linux版Nacos+MySQL生产环境配置

问题:ip、端口、用户名、密码全都正确,Mysql依旧无法远程访问!

四、Alibaba Sentinel实现熔断与限流  ★★

1、安装Sentinel控制台

2、案例

流控模式 

3、流控规则  ★

1. 降级规则​编辑

2. 热点key限流

3. 系统规则

4. @SentinelResource 自定义降级方法  ★

5. 规则持久化  (鸡肋)


一、Sleuth 链路追踪 (了解)

在微服务框架中,一个由客户端发起的请求在后端系统中会经过多个不同的服务节点调用来协同产生最后的请求结果,每一个前端请求都会形成一个复杂的分布式服务调用链路,链路中的任何一环出现高延时或错误都会引起整个请求最后的失败。

SpringCloud Sleuth提供了一套完整的服务跟踪的解决方案,在分布式系统中提供追踪解决方案并且集成、兼容支持了 zipkin(负责展现) ,Sleuth(负责链路数据采集)
Sleuth:Spring Cloud Sleuth
zipkinOpenZipkin · A distributed tracing system

1、zipkin 使用、介绍

通过jar包启用即可,java -jar zipkin-server-2.23.4.jar

下载:https://github.com/openzipkin/zipkin

访问:http://localhost:9411/zipkin/ 

Trace:类似于树结构的Span集合,表示一条调用链路,唯一标识 Trace Id

span:表示调用链路来源,通俗的理解span就是单次请求信息

一条链路通过Trace Id唯一标识,Span标识发起的请求信息,各span通过parent id 关联起来。

(1). 服务提供者

1. 在cloud-provider-payment8001,导入依赖

        <!--zipkin(负责展示) 集成了 sleuth(负责信息采集)-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
    </dependencies>

2. 添加YMl配置

spring:
  application:
    name: cloud-payment-service

  zipkin:
    base-url: http://localhost:9411
  sleuth:
    sampler:
      #采样率值介于0~1之间,1表示全部采样
      probability: 1

3. 业务类PaymentController

    //zipkin
    @GetMapping("/payment/zipkin")
    public String paymentZipkin(){
        return "hi ,i'am paymentzipkin server,welcome to atguigu,O(∩_∩)O哈哈~";
    }

(2). 服务消费者(调用方)

1. cloud-consumer-order80 导入依赖

     <!--包含了sleuth+zipkin-->
    <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
    </dependency>

2. YML添加配置

spring:
    application:
        name: cloud-order-service

    zipkin:
      base-url: http://localhost:9411
    sleuth:
      sampler:
        probability: 1

3. 业务类PaymentController

    //==> zipkin+sleuth
    @GetMapping("/consumer/payment/zipkin")
    public String paymentZipkin(){
        String result = restTemplate.getForObject(PATH+"/payment/zipkin/", String.class);
        return result;
    }

(3). 测试

访问:http://localhost:9411/zipkin/ 

二、SpringCloud Alibaba 简介

SpringCloud Netflix 的项目进入维护模式,技术停止更新,不再开发新的组件。

新组件功能将以其他替代的方式实现

SpringCloud alibaba:

可以做什么: 

  1. 服务限流降级:默认支持 WebServlet、WebFlux, OpenFeign、RestTemplate、Spring Cloud Gateway, Zuul, Dubbo 和 RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。
  2. 服务注册与发现:适配 Spring Cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。
  3. 分布式配置管理:支持分布式系统中的外部化配置,配置更改时自动刷新。
  4. 消息驱动能力:基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。
  5. 分布式事务:使用 @GlobalTransactional 注解, 高效并且对业务零侵入地解决分布式事务问题。。
  6. 阿里云对象存储:阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。
  7. 分布式任务调度:提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有 Worker(schedulerx-client)上执行。
  8. 阿里云短信服务:覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。

如何使用: 

        <---总体依赖->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.2.6.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

一整套解决方案, 简单理解就是替换Netflix那一套 ,微服务一站式解决方案

Sentinel:把流量作为切入点,从流量控制熔断降级、系统负载保护等多个维度保护服务的稳定性。

Nacos:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

RocketMQ:一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。

Dubbo:Apache Dubbo™ 是一款高性能 Java RPC 框架 (远程过程调用),支持负载均衡(默认随机)。

Seata:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。

Alibaba Cloud ACM:一款在分布式架构环境中对应用配置进行集中管理和推送的应用配置中心产品。

Alibaba Cloud OSS: 阿里云对象存储服务 (Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。

Alibaba Cloud SchedulerX: 阿里中间件团队开发的一款分布式任务调度(定时任务)产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。

Alibaba Cloud SMS: 覆盖全球的短息服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。 

官网:https://spring.io/projects/spring-cloud-alibaba#overview 

英文:GitHub - alibaba/spring-cloud-alibaba: Spring Cloud Alibaba provides a one-stop solution for application development for the distributed solutions of Alibaba middleware.

中文:spring-cloud-alibaba/README-zh.md at 2.2.x · alibaba/spring-cloud-alibaba · GitHub

三、Alibaba Nacos服务注册和配置中心  ★★★

Nacos:Dynamic Naming and Configuration Service

等价于:Nacos = Eureka+Config+Bus

Nacos就是注册中心+配置中心的组合

官网文档:home

下载地址:GitHub - alibaba/nacos: an easy-to-use dynamic service discovery, configuration and service management platform for building cloud native applications.

各种注册中心比较

CAP原则又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。

Nacos支持AP和CP模式的切换

curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP'

1、安装并运行Nacos

1. 本地Java8+Maven环境

2. 解压安装包,直接运行  bin/startup.cmd -m standalone

standalone: 单机模式,Nacos1.4.0之后默认启动是集群模式不加启动会报错

可以用命令行startup.cmd -m standalone就能以单体方式启动服务。
如果觉得每次启动都是单体模式,就可以在startup.cmd中的配置信息set MODE="cluster"修改为set MODE=“standalone”,
于是每次启动就默认单体模式。

3. 启动成功,访问 http://localhost:8848/nacos

默认用户名密码:nacos 

2、Nacos作为服务注册中心演示

(1). 基于Nacos的服务提供者

1. 新建Module:cloudalibaba-provider-payment9001,导入依赖

<dependencies>
        <!--spring cloud alibaba 2.1.0.RELEASE-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <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>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </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>

2. YML配置文件

server:
  port: 9001

spring:
  application:
    name: nacos-payment-provider
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #配置Nacos地址

#健康监控
management:
  endpoints:
    web:
      exposure:
        include: '*'  #默认只公开了/health和/info端点,要想暴露所有端点只需设置成星号

3. 主启动

package com.atguigu.springcloud.alibaba;

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

@SpringBootApplication
//作用: 与@EnableEurekaClient作用相同,声明注册中心客户端,适用于Eureka,Nacos,Consul,Zookeeper
@EnableDiscoveryClient
public class PaymentMain9001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain9001.class,args);
    }
}

4. 业务类Controller

package com.atguigu.springcloud.alibaba.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PaymentController{
    @Value("${server.port}")
    private String serverPort;

    @GetMapping(value = "/payment/nacos/{id}")
    public String getPayment(@PathVariable("id") Long id) {
        return "nacos registry, serverPort: "+ serverPort+"\t id"+id;
    }
}

5. 测试

6. 为了下一章节演示nacos的负载均衡,新建实例9002

 

(2). 基于Nacos的服务消费者

为什么nacos支持负载均衡:Nacos也集成了Ribbon,无需引入

1. 新建Module:cloudalibaba-consumer-nacos-order83,导入依赖

<dependencies>
        <!--SpringCloud ailibaba nacos -->
        <!--Nacos也集成了Ribbon,支持负载均衡-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <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>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </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>

2. YML配置文件

server:
  port: 83

spring:
  application:
    name: nacos-order-consumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

#消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者【可选】,注意:nacos-payment-provider含有IP和端口)
service-url:
  nacos-user-service: http://nacos-payment-provider

3. 主启动

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

4. 配置类 ApplicationContextBean

使用RestTemplate做实验,暂时不用Feign声明式远程服务调用

@Configuration
public class ApplicationContextConfig{

    @Bean
    @LoadBalanced //远程调用集群,还需要LoadBalanced,负载均衡
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

5. 业务类Controller

@RestController
@Slf4j
public class OrderNacosController{
    @Resource
    private RestTemplate restTemplate;

    //从配置文件中获取fuwu 地址
    @Value("${service-url.nacos-user-service}")
    private String serverURL;

    @GetMapping(value = "/consumer/payment/nacos/{id}")
    public String paymentInfo(@PathVariable("id") Long id){
        return restTemplate.getForObject(serverURL+"/payment/nacos/"+id,String.class);
    }

6. 启动测试

  

3、Nacos 作为服务配置中心演示

1. 新建Module:cloudalibaba-config-nacos-client3377,导入依赖

<dependencies>
        <!--nacos-config-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!--nacos-discovery-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--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>
        <!--一般基础配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </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>

2. YML配置 

Nacos同springcloud-config一样,在项目初始化时,要保证先从配置中心进行配置拉取,拉取配置之后,才能保证项目的正常启动

springboot中配置文件的加载是存在优先级顺序的,bootstrap加载优先级高于application

bootstrap.yml

server:
  port: 3377

spring:
  application:
    name: nacos-config-client
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #服务注册中心地址
      config:
        server-addr: localhost:8848 #配置中心地址
        file-extension: yaml #指定yaml格式的配置(yml和yaml都可以)

#${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
#nacos-config-client-dev.yaml  (一定要与file-extension值保持一致)

application.yml

spring:
  profiles:
    active: dev #表示开发环境

3. 主启动

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

4. 业务类 Controller 

@RestController
@RefreshScope   //通过SpringCould原生注解@RefreshScope实现配置自动更新
public class ConfigClientController{
    //对应nacos配置:nacos-config-client-dev.yaml
    @Value("${config.info}") //从配置中心拉去配置,
    private String configInfo;

    @GetMapping("/config/info")
    public String info() {
        return configInfo;
    }

5. 在Nacos中添加配置信息 (id匹配规则 关键)  

Nacos中的dataid的组成格式与SpringBoot配置文件中的匹配规则

最后公式:${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

{应用名}-{指定的开发环境}-{指定格式(扩展名)}

nacos-config-client-dev.yaml

Nacos界面配置内容对应 (注意间隔)

config:

        info: from nacos config center

 小总结说明:

 历史配置:Nacos会记录配置文件的历史版本默认保留30天

6. 测试

 

 改Nacos中的yaml配置,查看配置已经刷新  (因为标注了 @RefreshScope 注解)

4. 分类配置 (多环境配置)

多环境多项目管理

问题1

  1. 实际开发中,通常一个系统会准备
  2. dev开发环境
  3. test测试环境
  4. prod生产环境
  5. 如何保证指定环境启动时服务能正确读取到 Nacos上相应环境的配置文件呢?

问题2

  1. 一个大型分布式微服务系统会有很多微服务子项目
  2. 每一个微服务项目又会相应的开发环境、测试环境、预发环境、正式环境….
  3. 那怎么对这些微服务配置进行管理呢?

图形化管理界面:

spring:
  application:
    name: nacos-config-client
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #服务注册中心地址
      config:
        server-addr: localhost:8848 #配置中心地址
        file-extension: yaml #指定yaml格式的配置(yml和yaml都可以)
        #从哪个命名空间、哪个组拉取
        namespace: 46685e96-4b13-4636-b3e3-c65de732b207
        group: DEV_GROUP
spring:
  profiles:
    active: dev #表示开发环境
    #active: test #表示测试环境
    #active: pro #表示生产环境

Namespace+Group+Data ID三者关系?为什么这么设计? 

最外层的namespace是可以用于区分部署环境的,Group和DataID逻辑上区分两个目标对象。

默认情况:Namespace=public,Group=DEFAULT_GROUP,默认Cluster是DEFAULT

4、Nacos 集群和持久化配置 ★★

官网:集群部署说明

 暂时不去搭建Nginx主备、双主模式。

默认Nacos使用嵌入式数据库 derby 实现数据的存储。所以,如果启动多个默认配置下的Nacos节点,各自使用自己的数据库,数据存储会存在不一致的问题

为了解决这个问题,Nacos采用了集中式存储的方式来支持集群化部署,目前只支持MySQL 的存储。

默认集群模式启动。单机启动:bin/startup.cmd -m standalone

1. derby 持久化存储到mysql 切换配置步骤

1. 创建存储数据库,生成表结构

nacos-server-1.4.2\nacos\conf目录下找到sql脚本,执行脚本

2. 修改 nacos 配置

nacos-server-1.4.2\nacos\conf目录下找到application.properties

#持久化存储转为mysql
spring.datasource.platform=mysql

db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
db.user=root
db.password=*******

注意!!:Mysql8.0需要加入时区:&serverTimezone=Asia/Shanghai  否则连接失败

启动nacos,可以看到是个全新的空记录界面。(数据库还没有数据)

2. Linux版Nacos+MySQL生产环境配置

1. 创建/opt/nacoscluster目录,解压3个节点

tar -zxvf nacos-server-1.4.2.tar.gz  (解压)

mv nacos nacoscluster/  (移动)

mv nacos nacos8848 (改名)
 

2. 修改Nacos配置文件,添加Mysql持久存储

找到 conf/application.properties 配置文件

注意Mysql1.8加时区、链接wendows上Mysql要用VMNet8虚拟网卡,或真实ip

spring.datasource.platform=mysql

db.num=1
db.url.0=jdbc:mysql://192.168.86.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&serverTimezone=Asia/Shanghai
db.user=root
db.password=*******

3. conf 下创建配置 cluster.conf

 

4. 修改内存大小,不然内存不够用

修改93行 

5. 拷贝出额外两个节点,修改端口号即可

 

6. 启动三个节点

ps -ef|grep nacos 查看进程

登录任意节点查看集群:http://192.168.86.86:8848/nacos

7. Nginx 反向代理的配置,由它作为负载均衡器

 

    #nacos集群 2022-7-9
    upstream nacosgroup{
        server 192.168.86.86:8848 weight=1;
        server 192.168.86.86:8849 weight=1;
        server 192.168.86.86:8850 weight=1;
    }

    server {
        listen       1111;
        server_name  192.168.86.86;

        location / {
                proxy_pass http://nacosgroup;
        }

启动Nginx

8. 测试通过nginx反向代理 访问nacos

http://192.168.86.86:1111/nacos

9. 使用之前的项目 client3377 进行测试

Nacos进行配置,yml修改nacos地址

spring:
  application:
    name: nacos-config-client
  cloud:
    nacos:
      discovery:
        #server-addr: localhost:8848 #服务注册中心地址
        server-addr: 192.168.86.86:1111 #Nginx反向代理,Nacos集群
      config:
        #server-addr: localhost:8848 #配置中心地址
        server-addr: 192.168.86.86:1111
        file-extension: yaml #指定yaml格式的配置(yml和yaml都可以)
        #从哪个命名空间、哪个组拉取
        namespace: e2e179df-4581-483e-bac1-c09ac10422cc
        group: DEV_GROUP

成功 

问题:ip、端口、用户名、密码全都正确,Mysql依旧无法远程访问!

org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.

详见:SQLNonTransientConnectionException: Could not create connection to database server. Attempted reconn_焰火青年·的博客-CSDN博客

MySQL允许root远程登录_小gu的博客-CSDN博客_mysql允许root远程连接

四、Alibaba Sentinel实现熔断与限流  ★★

https://github.com/alibaba/Sentinel

中文

https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D

介绍:

功能:

解决服务使用中的各种问题:服务雪崩、服务降级、服务熔断、服务限流  

1、安装Sentinel控制台

下载:  Releases · alibaba/Sentinel · GitHub

前提:java8环境OK、8080端口不能被占用

命令:java -jar sentinel-dashboard-1.8.2.jar 启动 sentinel

访问sentinel管理界面: http://localhost:8080

登录账号密码均为sentinel

2、案例

1. 创建Module:cloudalibaba-sentinel-service8401,导入依赖

    <dependencies>
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <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>
        <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>4.6.3</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>

2. YML配置文件

server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:8080   #sentinal的后台
        #port: 8719  #默认8719,应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用HttpServer,如果8719被占用会自动改变。可以不用配置

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

3. 主启动

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

4. FlowLimitControlle

@RestController
@Slf4j
public class FlowLimitController{
    @GetMapping("/testA")
    public String testA() {
        return "------testA";
    }

    @GetMapping("/testB")
    public String testB() {
        return "------testB";
    }
}

5. 访问测试

Sentinel采用懒加载机制,服务需要至少访问一次才能监控到。

流控模式 

设置限流 :一秒钟不能超过1次 单机阈值

 

3、流控规则  ★

注:规则是临时的,服务、Sentinel重启后设置的规则就没了。

  • 资源名:唯一名称,默认请求路径。

  • 针对来源:Sentinel可以针对调用者进行限流,填写微服务名,默认default (不区分来源)。

  • 阈值类型/单机阈值。

    • QPS (每秒钟的请求数):当调用该api的QPS达到阈值的时候,进行限流。

    • 线程数:当调用该api的线程数达到阈值的时候,进行限流。

  • 是否集群:不需要集群

  • 流控模式:

    • 直接:api达到限流条件时,直接限流。

    • 关联:当关联的资源达到阈值时,就限流自己 (背锅、限制来源)。

    • 链路:只记录指定链路上的流量 (指定资源从入口资源进来的流量,如果到达阈值,就进行限流。api级别的针对来源 )(较少使用)。。

  • 流控效果:

    • 快速失败:直接失败,抛出异常。

    • Warm Up (预热):根据codeFactor (冷加载因子,默认3) 的值,从赋值/codeFactor,经过预热时长,才达到设置的QPS阈值。

    • 排队等待:均匀排队,让请求以均匀的速度通过,阈值类型必须设置QPS,否则无效。

1. 降级规则

 

2. 热点key限流

    @GetMapping("/testHotKey123")
    //与Hystrix中@HystrixCommand注解作用一致,降级熔断处理。value:资源名,blockHandler:降级方法名
    @SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")
    public String testHotKey(@RequestParam(value = "p1",required = false) String p1,
                             @RequestParam(value = "p2",required = false) String p2) {
        //int age = 10/0;
        return "------testHotKey";
    }

    /*
    /降级方法: 之针对于不符合配置规则的降级处理
        1.public
        2.返回值类型和目标方法一致
        3.参数列表要一致,并且最后多一BlockException类型参数
        4.方法名任意,与上面blockHandler指定一致
     */
    public String deal_testHotKey (String p1, String p2, BlockException exception){
        return "------deal_testHotKey,o(╥﹏╥)o";
    }

 注意:索引从0开始,针对于testHotKey123,第一个参数

一秒内超过两次,调用了降级方法。
  

3. 系统规则

针对于应用整体的规则

4. @SentinelResource 自定义降级方法  ★

系统默认的,没有体现我们自己的业务要求。依照现有条件,我们自定义的处理方法又和业务代码耦合在一起,不直观。

每个业务方法都增加一个兜底的,那代码膨胀加剧。全局统一的处理方法没有体现。

blockHandler:处理配置违规。 fallback:处理程序代码异常

@RestController
public class RateLimitController{
    @GetMapping("/byResource123")
    @SentinelResource(value = "byResource",
            blockHandler = "handleException",  //指定的降级方法名
            blockHandlerClass = CustomerBlockHandler.class) //指定独立处理类
            //注意:blockHandler只处理配置违规,代码异常降级方法需要fallback参数指定
    public CommonResult byResource(){
        return new CommonResult(200,"按资源名称限流测试OK",new Payment(2020L,"serial001"));
    }

    /*
        1.代码耦合,目标方法和降级方法在一起
        2.代码膨胀,很多降级方法
     */
    /*public CommonResult handleException(BlockException exception){
        return new CommonResult(444,exception.getClass().getCanonicalName()+"\t 服务不可用");
    }*/
}
public class CustomerBlockHandler {
    //降级方法定义在独立的处理类中,必须是static修饰的,其他要求一致
    public static CommonResult handleException(BlockException exception){
        return new CommonResult(444,"自定义限流处理信息.... CustomerBlockHandler --- 1");
    }
    /*
    /降级方法: 之针对于不符合配置规则的降级处理
        1.public
        2.返回值类型和目标方法一致
        3.参数列表要一致,并且最后多一BlockException类型参数
        4.方法名任意,与上面blockHandler指定一致
     */
}

 blockHandler:处理配置违规。 fallback:处理程序代码异常

public class CustomerBlockHandler {
    //降级方法定义在独立的处理类中,必须是static修饰的,其他要求一致
    //        1.public
    //        2.返回值类型和目标方法一致
    //        3.参数列表要一致,并且最后多一BlockException类型参数
    //        4.方法名任意,与上面blockHandler指定一致
    public static CommonResult handleException(BlockException exception){
        return new CommonResult(444,"自定义限流处理信息:" +exception.getClass().getCanonicalName());
    }

    public static CommonResult handleException2(Long id,BlockException exception){
        return new CommonResult(444,"服务不可用 - 配置违规");
    }
    //注意:处理代码异常的降级方法,参数要与目标方法一致,最后多一个Throwable类型参数(可加可不加)
    public static CommonResult handleException3(Long id,Throwable exception){
        return new CommonResult(444,"服务不可用 - 代码异常");
    }
}
@RestController
public class RateLimitController{
    @GetMapping("/byResource123")
    @SentinelResource(value = "byResource",
            blockHandler = "handleException",  //指定的降级方法名
            blockHandlerClass = CustomerBlockHandler.class) //指定独立处理类
            //注意:blockHandler只处理配置违规,代码异常降级方法需要fallback参数指定
    public CommonResult byResource(){
        return new CommonResult(200,"按资源名称限流测试OK",new Payment(2020L,"serial001"));
    }
    
    //blockHandler 与 fallback 参数
    @RequestMapping("/fallback/{id}")
    @SentinelResource(value = "byFallbackName",
            //处理配置违规
            blockHandler = "handleException2", blockHandlerClass = CustomerBlockHandler.class,
            //处理代码异常
            fallback = "handleException3",fallbackClass = CustomerBlockHandler.class,
            //特殊异常处理
            exceptionsToIgnore=IllegalArgumentException.class
    )
    public CommonResult fallback(@PathVariable("id") Long id) {
        if (id == 4) {
            throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");
        }

        if (id==-1) {
            CommonResult result = new CommonResult(444,"数据不存在",null);
            throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");
        }
        CommonResult result = new CommonResult (200,"数据已经获取",new Payment(id,"test"+1));
        return result;
    }
}

2. 根据资源名称配置流控规则,一秒钟不能超过一次

注意:如果根据资源路径配置,@SentinelResource注解不生效

程序自身异常: 

配置违规:

 

5. 规则持久化  (鸡肋)

一旦我们重启应用,Sentinel规则将消失,生产环境需要将配置规则进行持久化

将限流配置规则持久化进Nacos保存,而Nacos的配置可以持久化到数据库中,进行拉取即可。

1. 添加nacos依赖 (已添加)

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

2 .添加配置

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:8080   #sentinal的后台
        #port: 8719  #默认8719,应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用HttpServer,如果8719被占用会自动改变。可以不用配置

      #将Sentinel配置规则持久化Nacos配置中心
      datasource:
        ds1:
          nacos:
            server-addr: localhost:8848  #配置中心
            dataId: cloudalibaba-sentinel-service
            groupId: DEFAULT_GROUP
            data-type: json
            rule-type: flow

3. 添加Nacos业务规则配置 

data id :cloudalibaba-sentinel-service

[

    {

         "resource": "/testA",

         "limitApp": "default",

         "grade": 1,

         "count": 1,

         "strategy": 0,

         "controlBehavior": 0,

         "clusterMode": false 

    }

]

4. 启动8401后刷新sentinel发现业务规则有了

熔断框架比较

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值