17 SpringCloud Alibaba入门简介

17.1 why会出现SpringCloud alibaba

  • Spring Cloud Netflix项目进入维护模式
    • https://spring.io/blog/2018/12/12/spring-cloud-greenwich-rc1-available-now

    • 说明

  • Spring Cloud Netflix Projects Entering Maintenance Mode
    • 什么是维护模式
      • 将模块置于维护模式,意味着 Spring Cloud 团队将不会再向模块添加新功能。我们将修复 block 级别的 bug 以及安全问题,我们也会考虑并审查社区的小型 pull request。
    • 进入维护模式意味着什么呢?
      • Spring Cloud Netflix 将不再开发新的组件
      • 我们都知道Spring Cloud 版本迭代算是比较快的,因而出现了很多重大ISSUE都还来不及Fix就又推另一个Release了。进入维护模式意思就是目前一直以后一段时间Spring Cloud Netflix提供的服务和功能就这么多了,不在开发新的组件和功能了。以后将以维护和Merge分支Full Request为主
      • 新组件功能将以其他替代平代替的方式实现

17.2 SpringCloud alibaba带来了什么

是什么

  • 官网:
    • https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md
  • 诞生:
    • 2018.10.31,Spring Cloud Alibaba 正式入驻了 Spring Cloud 官方孵化器,并在 Maven 中央库发布了第一个版本。

去哪下:

  • https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md
  • 之前在pom文件已经引入此依赖了

能干嘛:

  • 服务限流降级:默认支持 Servlet、Feign、RestTemplate、Dubbo 和 RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。
  • 服务注册与发现:适配 Spring Cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。
  • 分布式配置管理:支持分布式系统中的外部化配置,配置更改时自动刷新。
  • 消息驱动能力:基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。
  • 阿里云对象存储:阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。
  • 分布式任务调度:提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有 Worker(schedulerx-client)上执行。

怎么玩

  • 如下图:

17.3 SpringCloud alibaba学习资料获取

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

    • Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。
    • 依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。
    • SpringCloud Alibaba进入了SpringCloud官方孵化器,而且毕业了
    • 即:这个网址是改版之前的网址,改版后加入到了SpringCloud中,所以之后查看SpringCloud中的阿里巴巴即可
  • 英文

    • https://github.com/alibaba/spring-cloud-alibaba

    • 英文文档:https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html

  • 中文

    • 中文文档:https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md

18 Nacos服务注册和配置中心

  • SpringCloud Alibaba—-Nacos服务注册和配置中心

18.1 Nacos简介

18.1.1 为什么叫Nacos

  • 前四个字母分别为Naming和Configuration的前两个字母,最后的s为Service。
  • github网址:https://github.com/alibaba/Nacos

18.1.2 是什么

  • 一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
  • Nacos: Dynamic Naming and Configuration Service
  • Nacos就是注册中心 + 配置中心的组合
    • 等价于:Nacos = Eureka+Config +Bus

18.1.3 能干嘛

  • 替代Eureka做服务注册中心
  • 替代Config做服务配置中心

18.1.4 去哪下

  • 官网:https://nacos.io/zh-cn/index.html

  • 下载地址:https://github.com/alibaba/nacos/releases

  • spring-cloud-alibaba在GitHub上面的总文档:使用Nacos

    • https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html#_spring_cloud_alibaba_nacos_discovery
  • 也可以直接在Nacos官网中查看文档:

18.1.5 各种注册中心比较(简单讲解)

据说 Nacos 在阿里巴巴内部有超过 10 万的实例运行,已经过了类似双十一等各种大型流量的考验

18.2 安装并运行Nacos

18.2.1 新老版本说明

  • GitHub官网查看各个组件对应的版本:

    • https://github.com/alibaba/spring-cloud-alibaba

  • 老版本的直接启动即可

  • 新版本需要修改配置文件才能启动成功:

    • 官方文档说明:

    • 原因:老版本的鉴权有默认值,新版本为了安全去掉了默认值所以需要手动配置

    • 如何修改查看:B站动力节点SpringCloud视频

18.2.2 运行

  • 下载之后解压压缩包

  • 本地Java8+Maven环境已经OK

  • 在bin目录中输入cmd,进入到命令行窗口

    • 启动命令:startup.cmd -m standalone
    • standalone代表着单机模式运行,非集群模式
  • 命令运行成功后直接访问:http://localhost:8848/nacos

    • 默认账号密码都是nacos

18.3 Nacos作为服务注册中心演示

18.3.1 官网文档

  • https://spring.io/projects/spring-cloud-alibaba
  • 阿里巴巴指导手册:

18.3.2 基于Nacos的服务提供者

1)新建Module:cloudalibaba-provider-payment9001

2)POM
  • 父POM:之前已经引入过,这样子工程不需要每次都引入了。
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2.1.0.RELEASE</version><type>pom</type><scope>import</scope></dependency>
  • 本模块POM
<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>cloud2020</artifactId><groupId>com.angenin.springcloud</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><groupId>com.angenin.springcloud.alibaba</groupId><artifactId>cloudalibaba-provider-payment9001</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><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></project>
  • 查看官网文档:
    • spring cloud alibaba依赖坐标
    • SpringCloud ailibaba nacos依赖坐标
3)YML

server:port: 9001spring:application:name: nacos-payment-providercloud:nacos:discovery:server-addr: localhost:8848 #配置Nacos地址management:endpoints:web:exposure:include: '*'#暴露监控所有的端点
  • 官方文档:
4)主启动

package com.angenin.springcloud.alibaba;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@EnableDiscoveryClient //这个注解和之前的不一样,开启服务注册功能@SpringBootApplicationpublic class PaymentMain9001 {public static void main(String[] args) {SpringApplication.run(PaymentMain9001.class, args);}}
  • 官方文档
5)业务类

package com.angenin.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;@RestControllerpublic class PaymentController {@Value("${server.port}")private String serverPort;@GetMapping(value = "/payment/nacos/{id}")public String getPayment(@PathVariable("id") Integer id) {return "nacos registry, serverPort: "+ serverPort+"\t id"+id;}}
6)测试
  • 启动Nacos8848注册中心,启动9001生产者

    • 不像Eureka需要自己构建服务模块才能使用,这个只需要安装就可以用了。
  • 访问控制层方法:http://localhost:9001/payment/nacos/1

  • nacos控制台:http://localhost:8848/nacos

    • 默认账号密码都是nacos
  • nacos服务注册中心+服务提供者9001都OK了

7)提前创建9002
  • nacos自带负载均衡功能:为了下一章节演示nacos的负载均衡,参照9001新建9002

  • 方式一:取巧不想新建重复体力劳动,直接拷贝虚拟端口映射

    • 有时候可能会报错。
  • 方式二:手动创建新建 cloudalibaba-provider-payment9002

    • 创建步骤:略

    • 效果:

  • 启动9001,9002查看后台管理界面:

18.3.3 基于Nacos的服务消费者

1)新建Module:cloudalibaba-consumer-nacos-order83

2)POM

<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>cloud2020</artifactId><groupId>com.angenin.springcloud</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><groupId>com.angenin.springcloud.alibaba</groupId><artifactId>cloudalibaba-consumer-nacos-order83</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>com.angenin.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></project>
  • 为什么nacos支持负载均衡:自动集成了Ribbon(新版本没有,已经被LoadBalancer代替了
3)YML

server:port: 83spring:application:name: nacos-order-consumercloud:nacos:discovery:server-addr: localhost:8848 #Nacos注册中心的地址#消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)#之前直接写的是生产者集群服务的名称 写死了,现在是写在配置文件中通过注解@Value读取获得service-url:nacos-user-service: http://nacos-payment-provider
4)主启动

package com.angenin.springcloud.alibaba;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@EnableDiscoveryClient@SpringBootApplicationpublic class OrderNacosMain83 {public static void main(String[] args) {SpringApplication.run(OrderNacosMain83.class,args);}}
5)配置类

package com.angenin.springcloud.alibaba.config;import org.springframework.cloud.client.loadbalancer.LoadBalanced;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.client.RestTemplate;@Configurationpublic class ApplicationContextBean {@Bean@LoadBalanced //使用@LoadBalanced注解赋予RestTemplate负载均衡的能力public RestTemplate getRestTemplate() {//RestTemplate提供了多种便捷访问远程http访问的方法return new RestTemplate();}}
6)业务类

package com.angenin.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;import org.springframework.web.client.RestTemplate;import javax.annotation.Resource;@RestControllerpublic class OrderNacosController {@Resourceprivate RestTemplate restTemplate;//之前直接写的是生产者集群服务的名称 写死了,现在是写在配置文件中通过注解@Value读取获得@Value("${service-url.nacos-user-service}")private String serverURL;@GetMapping("/consumer/payment/nacos/{id}")public String paymentInfo(@PathVariable("id") Long id) {//getForObject两个参数:请求地址,返回的对象类型----读操作return restTemplate.getForObject(serverURL+"/payment/nacos/"+id,String.class);}}
7)测试
  • 启动nacos,9001生产者,9002生产者,83消费者

  • nacos控制台

  • http://localhost:83/consumer/payment/nacos/13

  • 83访问9001/9002,轮询负载OK

18.3.4 服务注册中心对比(细节讲解)

  • Nacos全景图所示

  • Nacos和CAP

  • Nacos 支持AP和CP模式的切换

    • C是所有节点在同一时间看到的数据是一致的;而A的定义是所有的请求都会收到响应。
    • 何时选择使用何种模式?
    • 一般来说,如果不需要存储服务级别的信息且服务实例是通过nacos-client注册,并能够保持心跳上报,那么就可以选择AP模式。当前主流的服务如 Spring cloud 和 Dubbo 服务,都适用于AP模式,AP模式为了服务的可能性而减弱了一致性,因此AP模式下只支持注册临时实例。
    • 如果需要在服务级别编辑或者存储配置信息,那么 CP 是必须,K8S服务和DNS服务则适用于CP模式。
    • CP模式下则支持注册持久化实例,此时则是以 Raft 协议为集群运行模式,该模式下注册实例之前必须先注册服务,如果服务不存在,则会返回错误。
    • curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches" />18.4 Nacos作为服务配置中心演示

      18.4.1 Nacos作为配置中心-基础配置

      1)新建:cloudalibaba-config-nacos-client3377

      2)POM

      <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>cloud2020</artifactId><groupId>com.angenin.springcloud</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloudalibaba-config-nacos-client3377</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><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></project>
      3)YML
      • why配置两个
        • Nacos同springcloud-config一样,在项目初始化时,要保证先从配置中心进行配置拉取,拉取配置之后,才能保证项目的正常启动。
        • springboot中配置文件的加载是存在优先级顺序的,bootstrap优先级高于application
        • 即:bootstrap存放拉去配置中心共有的, application存放自己本地的

      • bootstrap.yml
      # nacos配置server:port: 3377spring:application:name: nacos-config-clientcloud:nacos:discovery:server-addr: localhost:8848 #Nacos服务注册中心地址config:server-addr: localhost:8848 #Nacos作为配置中心地址file-extension: yaml #指定yaml格式的配置(3377就可以到8848上去读取,后缀名指定为yaml格式的文件)# ${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}# nacos-config-client-dev.yaml (不识别yml)
      • application.yml
      spring:profiles:active: dev #表示开发环境# 这样bootstrap+application结合起来就相当于:3377到8848配置中心上去读取,一个什么样的yml文件
      4)主启动

      package com.angenin.springcloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@EnableDiscoveryClient@SpringBootApplicationpublic class NacosConfigClientMain3377{public static void main(String[] args) {SpringApplication.run(NacosConfigClientMain3377.class, args);}}
      5)业务类

      通过Spring Cloud 原生注解@RefreshScope实现配置自动更新:

      • 之前是在SpringCloud Config分布式配置中心解决:不需要重启就可以手动刷新功能,之后还需要发送post请求生效。

      package com.angenin.springcloud.controller;import org.springframework.beans.factory.annotation.Value;import org.springframework.cloud.context.config.annotation.RefreshScope;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestController@RefreshScope //在控制器类加入@RefreshScope注解使当前类下的配置支持Nacos的动态刷新功能。public class ConfigClientController {/** * 和之前学习SpringCloud Config分布式配置中心一样: * 分布式配置中心可以,将配置信息以REST接口的形式暴露:post、curl访问刷新均可...... * 既然配置信息暴漏了,那么3355就可以通过REST风格读取到3344配置中心的消息和内容的配置。 */@Value("${config.info}")private String configInfo;@GetMapping("/config/info")public String getConfigInfo() {return configInfo;}}
      6)在Nacos中添加配置信息:Nacos中的匹配规则

      理论:

      • Nacos中的data id的组成格式及与SpringBoot配置文件中的匹配规则

      • 官网:https://nacos.io/zh-cn/docs/v2/ecology/use-nacos-with-spring-cloud.html

      • 最后公式:

        • ${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
        • 配置文件中对应的配置:nacos-config-client-dev.yaml

      实操:

      • 配置新增:nacos-config-client-dev

      • Nacos界面配置对应

      config:info: nacos config center,version = 1
      • 点击发布:配置列表就多了一行配置信息

      • 总结:设置DataId

        • 公式:${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
        • prefix 默认为 spring.application.name 的值
        • spring.profile.active 即为当前环境对应的 profile,可以通过配置项 spring.profile.active 来配置。
        • file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置
        • 画图说明:
      • 历史配置

        • Nacos会记录配置文件的历史版本默认保留30天,此外还有一键回滚功能,回滚操作将会触发配置更新
        • 回滚
      7)测试
      • 启动前需要在nacos客户端-配置管理-配置管理栏目下有对应的yaml配置文件
      • 启动nacos
      • 运行cloud-config-nacos-client3377的主启动类
      • 调用接口查看配置信息:http://localhost:3377/config/info
      8)自带动态刷新
      • 修改下Nacos中的yaml配置文件,再次调用查看配置的接口,就会发现配置已经刷新

      18.4.2 Nacos作为配置中心-分类配置

      1)问题:多环境多项目管理
      • 问题1:
        • 实际开发中,通常一个系统会准备
          • dev开发环境
          • test测试环境
          • prod生产环境。
        • 如何保证指定环境启动时服务能正确读取到Nacos上相应环境的配置文件呢?
      • 问题2:
        • 一个大型分布式微服务系统会有很多微服务子项目,每个微服务项目又都会有相应的开发环境、测试环境、预发环境、正式环境…
        • 那怎么对这些微服务配置进行管理呢?
      2)Nacos的图形化管理界面
      • 配置管理

      • 命名空间

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

        • 类似Java里面的package名和类名,最外层的namespace是可以用于区分部署环境的,Group和DataID逻辑上区分两个目标对象。
      • 三者情况

      • 默认情况:

        • Namespace=public,Group=DEFAULT_GROUP, 默认Cluster是DEFAULT
        • Nacos默认的命名空间是public,Namespace主要用来实现隔离。
          • 比方说我们现在有三个环境:开发、测试、生产环境,我们就可以创建三个Namespace,不同的Namespace之间是隔离的。
        • Group默认是DEFAULT_GROUP,Group可以把不同的微服务划分到同一个分组里面去
        • Service就是微服务;一个Service可以包含多个Cluster(集群),Nacos默认Cluster是DEFAULT,Cluster是对指定微服务的一个虚拟划分。
          • 比方说为了容灾,将Service微服务分别部署在了杭州机房和广州机房,这时就可以给杭州机房的Service微服务起一个集群名称(HZ),给广州机房的Service微服务起一个集群名称(GZ),还可以尽量让同一个机房的微服务互相调用,以提升性能。
        • 最后是Instance,就是微服务的实例。

      18.4.3 案例:三种方案加载配置

      1)DataID方案
      • 指定spring.profile.active和配置文件的DataID来使不同环境下读取不同的配置

      • 默认空间+默认分组+新建dev和test两个DataID

        • 新建dev配置DataID:就是上面创建的哪个
        • 新建test配置DataID
      • 通过spring.profile.active属性就能进行多环境下配置文件的读取

      • 测试

        • 重启3377

        • http://localhost:3377/config/info

        • 配置是什么就加载什么:test

      2)Group方案
      • 通过Group实现环境区分:新建Group

      • 在nacos图形界面控制台上面新建配置文件DataID


      • bootstrap+application

        • 在config下增加一条group的配置即可。
          可配置为DEV_GROUP或TEST_GROUP
      • 测试

        • 启动Nacos
        • 重启3377
        • http://localhost:3377/config/info
      • 流程:nacos-config-client + TEST_GROUP + info + yaml

        • 表示找的是nacos-config-client微服务下的TEST_GROUP分组下的,前缀为info ,后缀为yaml的文件
      3)Namespace方案
      • 新建dev/test的Namespace


      • 回到服务管理-服务列表查看

      • 按照域名配置填写



      • YML

        • bootstrap

        • application

      • 测试:

      • 启动Nacos,3377

      • http://localhost:3377/config/info

      • 此时找的是:dev命名空间下的+TEST_GROUP分组下的+dev前缀+yaml后缀文件

      18.5 Nacos集群和持久化配置(重要)

      • 之前使用eureka注册中心需要手动创建模块,而Nacos不需要创建只需要解压使用即可
      • eureka有自我保护机制问题,但是Nacos把他屏蔽了没有这些问题。

      18.5.1 官网说明

      • 官方文档2.x:https://nacos.io/zh-cn/docs/v2/guide/admin/cluster-mode-quick-start.html

      • 官网架构图(写的o(╥﹏╥)o)(vip:虚拟ip)

      • 上图官网翻译,真实情况

      • 说明:

        • 默认Nacos使用嵌入式数据库实现数据的存储。所以,如果启动多个默认配置下的Nacos节点,数据存储是存在一致性问题的。
          为了解决这个问题,Nacos采用了集中式存储的方式来支持集群化部署,目前只支持MySQL的存储。
          • 即:内存的东西一般断电就没了,但是我们在nacos中配置的作为配置中心时的yml配置文件,在重启nacos后发现还存在。原因:是nacos自带了内嵌是的数据库derby。问题:这样如果是集群模式每个nacos都携带了一个derby,数据的一致性统一会出现问题。解决:把数据都存储在一个mysql数据库集群中。
        • 按照上述,我们需要mysql数据库
        • 官方文档2.x:
          • https://nacos.io/zh-cn/docs/v2/guide/admin/deployment.html

          • 重点说明

      18.5.2 Nacos持久化配置解释

      1)Nacos自带数据库derby
      • Nacos默认自带的是嵌入式数据库derby
        • Nacos源码的pom文件:https://github.com/alibaba/nacos/blob/develop/config/pom.xml
      2)derby到mysql切换配置步骤
      • 步骤1:nacos-server-1.1.4\nacos\conf目录下找到sql脚本

        • nacos-mysql.sql

        • 执行脚本:先创建一个数据库nacos_config(从脚本文件中查看,名字自己随便写一个也行)

      • 步骤2:nacos-server-1.1.4\nacos\conf目录下找到application.properties(需要多加个时区否则报错:startup.cmd -m standalone

      spring.datasource.platform=mysqldb.num=1db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config" />&serverTimezone=UTC&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=truedb.user=rootdb.password=root
      • 配置来源于官网文档:
      2)重启Nacos进行测试
      • 在bin目录中输入cmd,进入到命令行窗口

        • 启动命令:startup.cmd -m standalone
        • standalone代表着单机模式运行,非集群模式
      • 命令运行成功后直接访问:http://localhost:8848/nacos

        • 默认账号密码都是nacos
      • 效果:重启Nacos,可以看到是个全新的空记录界面,以前是记录进derby

      • 测试:

        • 在配置;列表添加一个配置信息

        • 可以看到数据已经存储到了mysql数据库中

      18.5.3 Linux版Nacos+MySQL生产环境配置

      这个虚拟机SpringCloud之前配置的有

      • Zookeeper服务注册中心,运行环境依赖jdk,所以需要配置Zookeeper和jdk
      • 学习SpringCloud Bus消息总线屏蔽不同的消息中间件差异时,配置了RabbitMQ,依赖于erlang环境
      1)Nacos集群部署架构说明
      • 说明:按照Nacos官网配置集群的说明,nginx要配置成集群,Nacos配置成集群,MySQL配置成高可用。此时为了学习阶段方便测试配置成 1个Nginx+3个nacos注册中心+1个mysql

      • 条件有限只有一台电脑,如果配置成3个虚拟机占用内存太大。所以我们配置成伪集群,在当前一台虚拟机上配置成3个Nacos节点。

      • 官网集群环境要求:

      2)nginx下载 安装 配置(linux系统)

      详情查看:我写的另一篇博客:https://blog.csdn.net/aa35434/article/details/124853852

      • 安装完成后访问:http://192.168.10.140/
      • 启动:
        • 进入到安装后的sbin目录:cd /usr/local/src/Nginx/sbin/

        • ./nginx 启动

        • ./nginx -s stop 快速停止

        • ./nginx -v 查看 nginx 版本号

      3)mysql下载 安装 配置(linux系统)

      详情查看:我写的另一篇博客:https://blog.csdn.net/aa35434/article/details/124716035

      • 设置的有开机自动启动

      • 安装完成后使用sqlyog远程登录连接

      4)Nacos之Linux版本安装
      • 下载步骤

        • https://github.com/alibaba/nacos/releases

        • nacos-server-1.4.6.tar.gz

        • 上传到目录:/usr/local/src/Nacos/

        • 进入到此目录,解压后安装:tar -zxvf nacos-server-1.4.6.tar.gz

      • 查看目录:windows启动使用的是startup.cmd,linux执行的是startup.sh

      • 在配置之前,先保存一份原始的配置,以防以后改错恢复配置时麻烦。(要养成这个习惯)

      • 问题:原先只有一个Nacos,直接使用命令启动即可。现在有3个Nacos组成的集群,那么使用命令该如何区分启动的是集群中的哪一个Nacos呢???

      • 解决:修改linux里面的nacos脚本,可以通过端口号进行区分。

      5) Nacos集群配置(上)

      第一个:和之前windows一样,在linux也需要进行Nacos持久化配置,目的是把数据由默认的derby迁移到MySQL。

      • 查看linux下的Nacos中的SQL脚本:在安装后的conf目录下

      • 把此文件的内容复制到Mysql中,执行此脚本:先创建好数据库
        我这个地方使用sqlyog远程工具连接的linux下的mysql8.0

      • 同样在conf目录下修改application.properties 配置

      • 改之前先把这个文件备份下

      #127.0.0.1代表的是linux系统下的本机spring.datasource.platform=mysqldb.num=1db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config" />&serverTimezone=UTC&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=truedb.user=rootdb.password=root

      第二个:Linux服务器上nacos的集群配置cluster.conf

      • 梳理出3台nacos集器的不同服务端口号

      • 复制cluster.conf.example文件为cluster.conf:
        cp cluster.conf.example cluster.conf

      • 我们修改的是这个新复制的文件cluster.conf

      192.168.10.140: 3333192.168.10.140: 4444192.168.10.140: 5555
      • 这个IP不能写127.0.0.1,必须是Linux命令hostname -i能够识别的IP

      第三个:编辑Nacos的启动脚本startup.sh,使它能够接受不同的启动端口

      • /mynacos/nacos/bin 目录下有startup.sh

      • 在什么地方,修改什么,怎么修改

      • 思考

      • 修改内容
        59行:添加参数p,表示会执行p)分支

        最后:明确告诉Nacos启动的是那台节点

      • 新版:p已经被占用了,随便改一个字母为o
        PORT=$OPTARG;;

        -Dserver.port=${PORT}

      • 执行方式:bin目录下
        ./startup.sh -o 3333

      6) Nacos集群配置(下)

      第一个:Nginx的配置,由它作为负载均衡器

      • 修改nginx的配置文件:nginx安装路径的conf目录下的nginx.conf文件

      • nginx.conf:修改之前

      • nginx.conf:修改之后

      • Nginx服务器指定启动配置文件命令:

      7)测试1:集群是否搭建成功

      截止到此处,1个Nginx+3个nacos注册中心+1个mysql

      • 启动3台Nacos:/usr/local/src/Nacos/nacos/bin/

        • ./startup.sh -o 3333
        • ./startup.sh -o 4444
        • ./startup.sh -o 5555
        • 查看进程:ps -ef|grep nacos | grep -v grep | wc -l
      • Nginx服务器指定启动配置文件命令:在/usr/local/nginx/sbin/目录下
        ./nginx -c /usr/local/nginx/conf/nginx.conf
        查看进程:ps -ef | grep nginx

        • 指向的文件
      • 启动mysql:开机自动启动

      • 测试通过nginx访问nacos:http://192.168.10.140:1111/nacos/#/login
        默认账号密码都是nacos

      • 新建一个配置测试

      • linux服务器的mysql插入一条记录

      8)测试2:9002启动注册进nacos集群

      微服务cloudalibaba-provider-payment9002启动注册进nacos集群

      • yml
      #server-addr: localhost:8848 #配置Nacos地址 配置在windows本机上的server-addr: 192.168.10.140:1111#配置在linux上的nginx1111,由nginx在转发给3333 4444 5555Nacos
      • 启动9001
      • 结果:查看服务列表发现9002成功注册到安装在linux系统上的Nacos注册中心
      9)高可用小总结

      19 Sentinel实现熔断与限流

      • SpringCloud Alibaba Sentinel实现熔断与限流

      19.1 Sentinel

      19.1.1 官网

      • https://github.com/alibaba/Sentinel

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

      19.1.2 是什么

      • 一句话解释,之前我们讲解过的Hystrix
      • 和Hystrix的对比

      19.1.3 去哪下

      • https://github.com/alibaba/Sentinel/releases
        • 视频学习时的版本:
        • 截止到:2323/9/2的版本(Pre-release:预发布版本为v2.0.0-alpha,Latest:最新版为v1.8.6 )

      19.1.4 能干嘛

      19.1.5 怎么玩

      • 文档:https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html#_spring_cloud_alibaba_sentinel

      • 服务使用中的各种问题

        • 服务雪崩
        • 服务降级
        • 服务熔断
        • 服务限流

      19.2 安装Sentinel控制台

      19.2.1 sentinel组件由2部分构成

      Sentinel 分为两个部分:

      • 核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
      • 控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。

      19.2.2 安装 启动-步骤

      下载

      • 本次以1.8.6版本为例

      运行命令

      • 前提
        • java8环境OK
        • 8080端口不能被占用(注意tomact默认端口号也是8080
        • 他是个jar包,不需要安装直接java -jar运行即可。
      • 命令:java -jar sentinel-dashboard-1.8.6.jar

      访问sentinel管理界面

      • http://localhost:8080

      • 登录账号密码均为sentinel

      19.3 初始化演示工程

      19.3.1 启动Nacos8848成功

      • 启动

      • 访问:http://localhost:8848/nacos/#/login

      19.3.2 创建:Module

      1)cloudalibaba-sentinel-service8401

      2)POM

      <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>cloud2020</artifactId><groupId>com.angenin.springcloud</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloudalibaba-sentinel-service8401</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>com.angenin.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></dependencies></project>
      3)YML

      server:port: 8401spring:application:name: cloudalibaba-sentinal-servicecloud:nacos:discovery:#Nacos服务注册中心地址(即:把此服务注册到注册中心8848‍)server-addr: 127.0.0.1:8848sentinel:transport:#配置Sentin dashboard地址(配置sentinel8080监控8401服务)dashboard: 127.0.0.1:8080# 默认8719端口,假如被占用了会自动从8719端口+1进行扫描,直到找到未被占用的 端口port: 8719 #指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServermanagement:endpoints:web:exposure:include: '*'
      4)主启动

      package com.angenin.springcloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@EnableDiscoveryClient@SpringBootApplicationpublic class MainApp8401 {public static void main(String[] args) {SpringApplication.run(MainApp8401.class, args);}}
      5)业务类FlowLimitController

      package com.angenin.springcloud.controller;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class FlowLimitController {@GetMapping("/testA")public String testA() {return "------testA";}@GetMapping("/testB")public String testB() {return "------testB";}}
      6)测试
      • nacos已启动

      • sentinel控制台已启动

      • 启动8401微服务后查看sentienl控制台

        • 空空如也,啥都没有

        • Sentinel采用的懒加载机制,需要执行一次访问才能监控到。

          • 执行一次访问即可
          • http://localhost:8401/testA
        • http://localhost:8401/testB

        • 多点几次testA查看效果:

      • 结论:sentinel8080正在监控微服务8401

      • 在图形化界面可以看到每一个微服务的restful风格的接口调用的访问情况。

      19.4 流控规则

      属于流量限制控制规则,不是流程控制。

      19.4.1 基本介绍

      • 位置:

      • 解释:

      19.4.2 流控模式

      1)直接(默认)
      • 系统默认:直接->快速失败

      • 即:那个资源触发了阈值,我就对那个资源进行限流。

      • 配置及说明:
        表示1秒钟内查询1次就是OK,若超过次数1,就直接-快速失败,报默认错误

      • 测试1:QPS

        • 快速点击访问http://localhost:8401/testA

        • 结果:Blocked by Sentinel (flow limiting)

        • 思考" />

          • 多次点击发现结果不变。

          • QPS和并发线程数的区别:QPS是请求没有进来之前就被阻挡了,并发线程数是随便进来但是里面能处理的只有一个线程。

          • 在A方法中加上暂停时间:

          • 多次点击,会出现报错:1秒钟内只允许一个线程进来

        2)关联
        • 是什么

          • 当关联的资源达到阈值时,就限流自己
          • 当与A关联的资源B达到阀值后,就限流A自己
          • B惹事,A挂了
        • 恢复代码:

        • 配置A

        • postman模拟并发密集访问testB

          • 访问testB成功

          • postman里新建多线程集合组

          • 将访问地址添加进新新线程组

          • Run:大批量线程高并发访问B,导致A失效了

        • 运行后发现testA挂了

          • 点击访问http://localhost:8401/testA
          • 结果:Blocked by Sentinel (flow limiting)
        • 等这20个线程跑完,再次访问恢复正常。

        3)链路
        • 多个请求调用了同一个微服务
        • eg:a、b、c三个资源,a、b都要访问c资源,但是我在统计资源c的时候我只统计从A过来的请求,b过来的不管。所以这种流控模式是对请求的来源来做判断和限流。


        19.4.3 流控效果

        1)直接->快速失败(默认的流控处理)
        • 直接失败,抛出异常:Blocked by Sentinel (flow limiting)
        • 源码:
          • com.alibaba.csp.sentinel.slots.block.flow.controller.DefaultController
        2)预热
        • 说明

          • 公式:阈值除以coldFactor(默认值为3),经过预热时长后才会达到阈值
        • 官网:https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6

          • 默认coldFactor为3,即请求 QPS 从 threshold / 3 开始,经预热时长逐渐升至设定的 QPS 阈值。
          • 限流 冷启动:https://github.com/alibaba/Sentinel/wiki/%E9%99%90%E6%B5%81---%E5%86%B7%E5%90%AF%E5%8A%A8
        • 源码

          • com.alibaba.csp.sentinel.slots.block.flow.controller.WarmUpController
        • WarmUp配置

        • 多次点击http://localhost:8401/testB,刚开始不行,后续慢慢OK

        • 应用场景:

          • 如:秒杀系统在开启的瞬间,会有很多流量上来,很有可能把系统打死,预热方式就是把为了保护系统,可慢慢的把流量放进来,慢慢的把阀值增长到设置的阀值。
        3)排队等待
        • 匀速排队,阈值必须设置为QPS

        • 官网:https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6

        • 源码:com.alibaba.csp.sentinel.slots.block.flow.controller.RateLimiterController

        • 测试



        19.5 降级规则

        19.5.1 官网

        • https://github.com/alibaba/Sentinel/wiki/%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7

        19.5.2 基本介绍

        1) 老版本:

        • 进一步说明
          • Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。
          • 当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException)。
        • Sentinel的断路器是没有半开状态的
          • 半开的状态系统自动去检测是否请求有异常,没有异常就关闭断路器恢复使用,有异常则继续打开断路器不可用。具体可以参考Hystrix
          • 新版本1.8.0开始有半开状态了。
          • 复习Hystrix:有半开状态
        2) 新版本:

        慢调用:

        名词解释:

        • 熔断降级:熔断降级是解决雪崩问题的重要手段。其思路是由断路器统计服务调用的异常比例、慢请求比例如果超出阈值则会熔断该服务。即拦截访问该服务的一切请求;而当服务恢复时,断路器会放行访问该服务的请求。

        • 熔断策略:断路器想要从open变为close状态,需要判断服务有没有触发熔断的条件,而熔断条件的判断就是依据熔断策略完成的。

        • 慢调用比例:看的是响应的时间,如果响应时间RT(response time)过长超过了指定时间,那么你这个调用就是慢调用,请求很慢就会调用额外的资源 会拖慢整个服务。

        • 最大RT:响应时间,表示超过500毫秒的响应都算是慢调用。

        • 比例阈值:慢调用的比超过了0.5达到一半以上就触发阈值了。

        • 熔断时长:一旦熔断,熔断时长持续5秒,5秒后进入Half-Open半熔断状态。

        • 最小请求数,统计时长:表示我会统计最近1秒内的至少10次请求,那么10次里面超过500ms的这种慢调用比例达到了一半以上,那么我就触发熔断,而熔断时间为5秒钟。

        异常比例、异常数:

        • 异常比例:不是看你调用的快和慢而是看你有没有抛出异常,按照异常的比例。
        • 以上配置含义:1秒钟内统计10次请求,如果10次请求里有4次都抛了异常,那么就触发了熔断,熔断时长为5秒钟。
        • 异常数:按异常的次数
        • 以上配置含义:1秒钟内统计10次请求,如果10次请求里有2次都抛了异常,那么就触发了熔断,熔断时长为5秒钟。

        19.5.3 降级策略实战

        • 这里我是用的是Sentinel1.8.6版本,而老师使用的是1.7.0版本,所以配置方式会有些不一样。
        1)RT

        测试

        • 代码
        @GetMapping("/testD")public String testD() { //暂停几秒钟线程try {TimeUnit.MILLISECONDS.sleep(60);} catch (InterruptedException e) {e.printStackTrace();}log.info("testD 测试RT");return "------testD";}
        • 配置:表示我会统计最近1秒内的至少5次请求,那么5次里面超过50ms的这种慢调用比例达到了2次以上,那么我就触发熔断,而熔断时间为5秒钟。

        • 测试:不需要使用压测工具,自己点就可以,只要1秒钟5次请求只需要有2次触发就行了。

        2)异常比例

        测试

        • 代码
        @GetMapping("/testE")public String testE() {log.info("testD 测试RT");int age = 10/0;return "------testD";}
        • 配置:1秒钟内统计5次请求,如果5次请求里有2次都抛了异常,那么就触发了熔断,熔断时长为5秒钟。

        • 同样不需要jmeter,手动测试,只要1秒钟5次请求只需要有2次触发就行了。
        3)异常数
        • 按异常的次数
        • 代码
        @GetMapping("/testF")public String testF() {log.info("testD 测试RT");int age = 10/0;return "------testD";}
        • 配置:1秒钟内统计5次请求,如果5次请求里有2次都抛了异常,那么就触发了熔断,熔断时长为5秒钟。
        • 同样不需要jmeter,手动测试,只要1秒钟5次请求只需要有2次触发就行了。

        19.6 热点key限流

        19.6.1 基本介绍

        • 何为热点
          • 热点即经常访问的数据,很多时候我们希望统计或者限制某个热点数据中访问频次最高的TopN数据,并对其访问进行限流或者其它操作

        19.6.2 官网

        • https://github.com/alibaba/Sentinel/wiki/%E7%83%AD%E7%82%B9%E5%8F%82%E6%95%B0%E9%99%90%E6%B5%81

        19.6.3 承上启下复习start

        兜底方法:分为系统默认和客户自定义,两种

        • 之前的case,限流出问题后,都是用sentinel系统默认的提示:Blocked by Sentinel (flow limiting)
          我们能不能自定" />19.6.4 代码
          • 源码:com.alibaba.csp.sentinel.slots.block.BlockException
          • 代码测试
          @GetMapping("/testHotKey")//value:资源的唯一标识,名字任意一般和上面的地址值保持一致。@SentinelResource(value = "testHotKey",blockHandler = "dealHandler_testHotKey")public String testHotKey(@RequestParam(value = "p1",required = false) String p1, @RequestParam(value = "p2",required = false) String p2){return "------testHotKey";}public String dealHandler_testHotKey(String p1, String p2, BlockException exception) {//sentinel系统默认的提示:Blocked by Sentinel (flow limiting)return "-----dealHandler_testHotKey";}

          19.6.5 配置


          19.6.6 测试

          多次点击测试:方法testHotKey里面第一个参数只要QPS超过每秒1次,马上降级处理。用了我们自己定义的

          • error:http://localhost:8401/testHotKey" />

          • error:http://localhost:8401/testHotKey?p1=abc&p2=33

          • right:http://localhost:8401/testHotKey" />

          如果使用默认的提示:异常打到了前台用户界面看到,不友好

          • 多次点击测试:http://localhost:8401/testHotKey?p1=abc

          19.6.7 参数例外项

          • 上述案例演示了第一个参数p1,当QPS超过1秒1次点击后马上被限流

          • 特例情况

            • 普通:超过1秒钟一个后,达到阈值1后马上被限流
            • 我们期望p1参数当它是某个特殊值时,它的限流值和平时不一样
            • 特例:假如当p1的值等于5时,它的阈值可以达到200
          • 配置:添加按钮不能忘

          • 测试:多次点击

            • http://localhost:8401/testHotKey" />

            • http://localhost:8401/testHotKey?p1=3

            • 当p1等于5的时候,阈值变为200

            • 当p1不等于5的时候,阈值就是平常的1

          • 前提条件:热点参数的注意点,参数必须是基本类型或者String

          19.6.8 其它

          • 手贱添加异常看看…/(ㄒoㄒ)/~~

          • 效果:发现并没有执行自定义的提示方法。

          • @SentinelResource
            处理的是Sentinel控制台配置的违规情况,有blockHandler方法配置的兜底处理;

          • RuntimeException
            int age = 10/0,这个是java运行时报出的运行时异常RunTimeException,@SentinelResource不管

          • 总结
            @SentinelResource主管配置出错,运行出错该走异常走异常

          • 后面讲:还有其它的配置来解决这个问题

          19.7 系统规则

          • 是什么:之前是细粒度的从控制层的方法进行限流,现在是粗粒度的进行限流。

            • https://github.com/alibaba/Sentinel/wiki/%E7%B3%BB%E7%BB%9F%E8%87%AA%E9%80%82%E5%BA%94%E9%99%90%E6%B5%81
          • 各项配置参数说明

          • 配置全局QPS

          • 多次访问:不管是访问p1还是p2,都会报错。(之前配置的是只有p1会报错)

          19.8 @SentinelResource

          19.8.1 按资源名称限流+后续处理

          1)启动
          • 启动Nacos成功
          • 启动Nacos成功
          2)修改:cloudalibaba-sentinel-service8401
          • pom:之前已引入

          • yml:没有改变

          • 业务类RateLimitController

          package com.angenin.springcloud.controller;import com.alibaba.csp.sentinel.annotation.SentinelResource;import com.alibaba.csp.sentinel.slots.block.BlockException;import com.angenin.springcloud.entities.CommonResult;import com.angenin.springcloud.entities.Payment;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class RateLimitController {//既可以使用url地址来配置:/byResource//也可以使用@SentinelResource注解中的value 属性来配置@GetMapping("/byResource")@SentinelResource(value = "byResource",blockHandler = "handleException")public CommonResult byResource() {return new CommonResult(200,"按资源名称限流测试OK",new Payment(2020L,"serial001"));}public CommonResult handleException(BlockException exception) {return new CommonResult(444,exception.getClass().getCanonicalName()+"\t 服务不可用");}}
          • 主启动:没有变化
          3)配置流控规则
          • 配置步骤

          • 图形配置和代码关系

          • 表示1秒钟内查询次数大于1,就跑到我们自定义的处流,限流

          4)测试
          • 1秒钟点击1下,OK
          • 超过上述,疯狂点击,返回了自己定义的限流处理信息,限流发生
          5)额外问题
          • 此时关闭问服务8401看看
          • Sentinel控制台,流控规则消失了?????
          • 临时/持久?:说明是临时的

          19.8.2 按照Url地址限流+后续处理

          • 通过访问的URL来限流,会返回Sentinel自带默认的限流处理信息
          • 业务类RateLimitController
          @GetMapping("/rateLimit/byUrl")@SentinelResource(value = "byUrl")public CommonResult byUrl() {return new CommonResult(200,"按url限流测试OK",new Payment(2020L,"serial002"));}
          • 访问一次:http://localhost:8401/rateLimit/byUrl

          • Sentinel控制台配置

          • 测试

            • 疯狂点击http://localhost:8401/rateLimit/byUrl
            • 结果:没有配置自定义的提示,就使用系统自带的。

          19.8.3 上面兜底方案带来的问题

          1. 系统默认的,没有体现我们自己的业务要求。
          2. 依照现有条件,我们自定义的处理方法又和业务代码耦合在一块,不直观。
          3. 每个业务方法都添加一个兜底的,那代码膨胀加剧。
          4. 全局统一的处理方法没有体现。

          19.8.4 客户自定义限流处理逻辑

          • 创建CustomerBlockHandler类用于自定义限流处理逻辑
          package com.angenin.springcloud.myhandler;import com.alibaba.csp.sentinel.slots.block.BlockException;import com.angenin.springcloud.entities.CommonResult;public class CustomerBlockHandler {public static CommonResult handleException1(BlockException exception){return new CommonResult(2020,"自定义的限流处理信息......CustomerBlockHandler1");}public static CommonResult handleExceptio2(BlockException exception){return new CommonResult(2020,"自定义的限流处理信息......CustomerBlockHandler2");}}
          • RateLimitController
          /** * 自定义通用的限流处理逻辑, * blockHandlerClass = CustomerBlockHandler.class * blockHandler = handleException2 * 上述配置:找CustomerBlockHandler类里的handleException2方法进行兜底处理 */@GetMapping("/rateLimit/customerBlockHandler")//指定哪一个全局类中的的哪一个方法@SentinelResource(value = "customerBlockHandler",blockHandlerClass = CustomerBlockHandler.class, blockHandler = "handleExceptio2")public CommonResult customerBlockHandler() {return new CommonResult(200,"按客户自定义限流处理逻辑");}
          • 启动微服务后先调用一次:http://localhost:8401/rateLimit/customerBlockHandler

          • Sentinel控制台配置

          • 多次刷新后我们自定义的出来了

          • 进一步说明

          19.8.5 更多注解属性说明

          • 多说一句:除了默认的系统提示,和使用注解编写自定义提示外,他还支持使用代码的方式编写自定义提示规则。

          • Sentinel主要有三个核心Api

            • SphU定义资源
            • Tracer定义统计
            • ContextUtil定义了上下文

          19.9 服务熔断功能

          • sentinel整合ribbon+openFeign+fallback

          19.9.1 Ribbon系列

          • 启动nacos和sentinel
          • 结构
          1)提供者9003/9004
          • 新建cloudalibaba-provider-payment9003/9004两个一样的做法

          • POM

          <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>cloud2020</artifactId><groupId>com.angenin.springcloud</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloudalibaba-provider-payment9003</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>com.angenin.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></project>
          • YML:记得修改不同的端口号
          server:port: 9003spring:application:name: nacos-payment-providercloud:nacos:discovery:server-addr: localhost:8848 #配置Nacos地址management:endpoints:web:exposure:include: '*'
          • 主启动
          package com.angenin.springcloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@SpringBootApplication@EnableDiscoveryClientpublic class PaymentMain9003{public static void main(String[] args) {SpringApplication.run(PaymentMain9003.class, args);}}
          • 业务类
          package com.angenin.springcloud.controller;import com.angenin.springcloud.entities.CommonResult;import com.angenin.springcloud.entities.Payment;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;import java.util.HashMap;@RestControllerpublic class PaymentController {@Value("${server.port}")private String serverPort;public static HashMap hashMap = new HashMap();//模拟连接一个数据库static {hashMap.put(1L,new Payment(1L,"28a8c1e3bc2742d8848569891fb42181"));hashMap.put(2L,new Payment(2L,"bba8c1e3bc2742d8848569891ac32182"));hashMap.put(3L,new Payment(3L,"6ua8c1e3bc2742d8848569891xt92183"));}@GetMapping(value = "/paymentSQL/{id}")public CommonResult paymentSQL(@PathVariable("id") Long id) {Payment payment = (Payment)hashMap.get(id);CommonResult result = new CommonResult(200,"from mysql,serverPort:"+serverPort,payment);return result;}}
          • 结构
          • 测试地址:http://localhost:9003/paymentSQL/1
          • 测试地址:http://localhost:9004/paymentSQL/1

          2)消费者84
          • 新建cloudalibaba-consumer-nacos-order84

          • pom

          <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>cloud2020</artifactId><groupId>com.angenin.springcloud</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloudalibaba-consumer-nacos-order84</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency><dependency><groupId>com.angenin.springcloud</groupId><artifactId>cloud-api-commons</artifactId><version>1.0-SNAPSHOT</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></project>
          • yml
          server:port: 84spring:application:name: nacos-order-consumercloud:nacos:discovery:server-addr: localhost:8848sentinel:transport:#配置Sentinel dashboard地址dashboard: localhost:8080#默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口port: 8719#消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)service-url:nacos-user-service: http://nacos-payment-provider
          • 主启动
          package com.angenin.springcloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@EnableDiscoveryClient@SpringBootApplicationpublic class OrderNacosMain84 {public static void main(String[] args) {SpringApplication.run(OrderNacosMain84.class, args);}}
          • 结构
          • 业务类详情查看下面
          • 修改后请重启微服务
            • 热部署对java代码级生效及时
            • 对@SentinelResource注解内属性,有时效果不好
          • 目的
            • fallback管运行异常
            • blockHandler管配置违规
          3)配置类:ApplicationContextConfig
          • ApplicationContextConfig
          package com.angenin.springcloud.config;import org.springframework.cloud.client.loadbalancer.LoadBalanced;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.client.RestTemplate;@Configurationpublic class ApplicationContextConfig {@Bean@LoadBalancedpublic RestTemplate getRestTemplate() {return new RestTemplate();}}
          4)业务类 CircleBreakerController :没有任何配置

          package com.angenin.springcloud.controller;import com.alibaba.csp.sentinel.annotation.SentinelResource;import com.angenin.springcloud.entities.CommonResult;import com.angenin.springcloud.entities.Payment;import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;import javax.annotation.Resource;@RestController@Slf4jpublic class CircleBreakerController {public static final String SERVICE_URL = "http://nacos-payment-provider";@Resourceprivate RestTemplate restTemplate;@RequestMapping("/consumer/fallback/{id}")@SentinelResource(value = "fallback")//没有配置public CommonResult<Payment> fallback(@PathVariable Long id) {CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id, CommonResult.class,id);if (id == 4) {throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");}else if (result.getData() == null) {throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");}return result;}}
          • 测试
            • 测试地址:http://localhost:84/consumer/fallback/1
              通过84消费者可以以负载均衡轮训的方式,访问9003/9004

            • 没有任何配置:给客户error页面,不友好(在控制层方法中设置的访问1、2、3正常,4、5异常)

          5)业务类 CircleBreakerController :只配置fallback
          • 代码
          package com.angenin.springcloud.controller;import com.alibaba.csp.sentinel.annotation.SentinelResource;import com.angenin.springcloud.entities.CommonResult;import com.angenin.springcloud.entities.Payment;import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;import javax.annotation.Resource;@RestController@Slf4jpublic class CircleBreakerController {public static final String SERVICE_URL = "http://nacos-payment-provider";@Resourceprivate RestTemplate restTemplate;@RequestMapping("/consumer/fallback/{id}")//@SentinelResource(value = "fallback")//没有配置@SentinelResource(value = "fallback", fallback = "handlerFallback") //fallback只负责业务异常public CommonResult<Payment> fallback(@PathVariable Long id) {CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id, CommonResult.class,id);if (id == 4) {throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");}else if (result.getData() == null) {throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");}return result;}//本例是fallbackpublic CommonResult handlerFallback(@PathVariableLong id,Throwable e) {Payment payment = new Payment(id,"null");return new CommonResult<>(444,"兜底异常handlerFallback,exception内容"+e.getMessage(),payment);}}
          • 测试:http://localhost:84/consumer/fallback/5(错误页面变为自定义的兜底方法)
          6)业务类 CircleBreakerController :只配置blockHandler
          • 代码
          package com.angenin.springcloud.controller;import com.alibaba.csp.sentinel.annotation.SentinelResource;import com.alibaba.csp.sentinel.slots.block.BlockException;import com.angenin.springcloud.entities.CommonResult;import com.angenin.springcloud.entities.Payment;import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;import javax.annotation.Resource;@RestController@Slf4jpublic class CircleBreakerController {public static final String SERVICE_URL = "http://nacos-payment-provider";@Resourceprivate RestTemplate restTemplate;@RequestMapping("/consumer/fallback/{id}")//@SentinelResource(value = "fallback")//没有配置//@SentinelResource(value = "fallback", fallback = "handlerFallback") //fallback只负责业务异常@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规public CommonResult<Payment> fallback(@PathVariable Long id) {CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id, CommonResult.class,id);if (id == 4) {throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");}else if (result.getData() == null) {throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");}return result;}//本例是fallback/*public CommonResult handlerFallback(@PathVariableLong id,Throwable e) {Payment payment = new Payment(id,"null");return new CommonResult(444,"兜底异常handlerFallback,exception内容"+e.getMessage(),payment);}*///本例是blockHandlerpublic CommonResult blockHandler(@PathVariableLong id, BlockException blockException) {Payment payment = new Payment(id,"null");return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException"+blockException.getMessage(),payment);}}
          • 配置

          • 测试:http://localhost:84/consumer/fallback/4

            • 第一次点击
            • 快速点击
            • 说明:fallback只负责业务异常,blockHandler只负责sentinel控制台配置违规
          7)业务类 CircleBreakerController :fallback和blockHandler都配置
          • 代码
          package com.angenin.springcloud.controller;import com.alibaba.csp.sentinel.annotation.SentinelResource;import com.alibaba.csp.sentinel.slots.block.BlockException;import com.angenin.springcloud.entities.CommonResult;import com.angenin.springcloud.entities.Payment;import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;import javax.annotation.Resource;@RestController@Slf4jpublic class CircleBreakerController {public static final String SERVICE_URL = "http://nacos-payment-provider";@Resourceprivate RestTemplate restTemplate;@RequestMapping("/consumer/fallback/{id}")//@SentinelResource(value = "fallback")//没有配置//@SentinelResource(value = "fallback", fallback = "handlerFallback") //fallback只负责业务异常//@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规@SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler") //都配置public CommonResult<Payment> fallback(@PathVariable Long id) {CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id, CommonResult.class,id);if (id == 4) {throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");}else if (result.getData() == null) {throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");}return result;}//本例是fallbackpublic CommonResult handlerFallback(@PathVariableLong id,Throwable e) {Payment payment = new Payment(id,"null");return new CommonResult<>(444,"兜底异常handlerFallback,exception内容"+e.getMessage(),payment);}//本例是blockHandlerpublic CommonResult blockHandler(@PathVariableLong id, BlockException blockException) {Payment payment = new Payment(id,"null");return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException"+blockException.getMessage(),payment);}}
          • 配置

          • 测试1:http://localhost:84/consumer/fallback/1(访问正常)

            • 第一次点击:正常访问

            • 快速点击:超过阈值,会访问自定义的blockHandler方法

          • 测试2:http://localhost:84/consumer/fallback/4(访问异常)

            • 第一次点击:返回fallback属性标注的自定义方法

            • 快速点击:超过阈值,此时既满足fallback业务异常又满足blockHandler控制台配置违规,那么此时返回的结果是blockHandler属性指定的方法。

          • 结论:若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑。

          8)业务类 CircleBreakerController :忽略属性…
          • 即:排除指定的异常,即便配置了出现异常后执行自定义的方法提示,但是加上此属性后出现此异常执行的仍然是系统自带的提示信息。

            exceptionsToIgnore = {IllegalArgumentException.class}

            http://localhost:84/consumer/fallback/4

          19.9.2 Feign系列

          1)修改84模块
          • 84消费者调用提供者9003

          • Feign组件一般是消费侧

          2)POM

          <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency>
          3)YML

          server:port: 84spring:application:name: nacos-order-consumercloud:nacos:discovery:server-addr: localhost:8848sentinel:transport:#配置Sentinel dashboard地址dashboard: localhost:8080#默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口port: 8719#消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)service-url:nacos-user-service: http://nacos-payment-provider# 激活Sentinel对Feign的支持feign:sentinel:enabled: true
          4)业务类
          • 接口
          package com.angenin.springcloud.service;import com.angenin.springcloud.entities.CommonResult;import org.springframework.cloud.openfeign.FeignClient;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;/** * value:找到注册中心上的微服务接口名 * 过程:fallback:相当于去找nacos-payment-provider这个微服务的名字,去调用下面已有的方法, * 假如出事了去调用PaymentFallbackService里面的方法 */@FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)//调用中关闭9003服务提供者public interface PaymentService {@GetMapping(value = "/paymentSQL/{id}")public CommonResult paymentSQL(@PathVariable("id") Long id);}
          • 接口实现类:解决和业务逻辑混一起???混乱
          package com.angenin.springcloud.service;import com.angenin.springcloud.entities.CommonResult;import com.angenin.springcloud.entities.Payment;import org.springframework.stereotype.Component;@Componentpublic class PaymentFallbackService implements PaymentService {@Overridepublic CommonResult paymentSQL(Long id) {return new CommonResult(444,"服务降级返回,没有该流水信息",new Payment(id, "errorSerial......"));}}
          • Controller
          //==================OpenFeign@Resourceprivate PaymentService paymentService;@GetMapping(value = "/consumer/openfeign/{id}")public CommonResult paymentSQL(@PathVariable("id") Long id) {if(id == 4) {throw new RuntimeException("没有该id");}return paymentService.paymentSQL(id);}
          5)主启动

          package com.angenin.springcloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.cloud.openfeign.EnableFeignClients;@EnableDiscoveryClient@SpringBootApplication@EnableFeignClients //启用 激活public class OrderNacosMain84 {public static void main(String[] args) {SpringApplication.run(OrderNacosMain84.class, args);}}
          6)测试
          • 启动消费者84,启动生产者9003

          • http://localhost:84/consumer/openfeign/1(正确访问)

          • 测试84调用9003,此时故意关闭9003微服务提供者,看84消费侧自动降级,不会被耗死

          19.9.3 熔断框架比较

          SentinelHystrixresilience4j
          隔离策略信号量隔离(并发线程数限流)线程池隔商/信号量隔离信号量隔离
          熔断降级策略基于响应时间、异常比率、异常数基于异常比率基于异常比率、响应时间
          实时统计实现滑动窗口(LeapArray)滑动窗口(基于RxJava)Ring Bit Buffer
          动态规则配置支持多种数据源支持多种数据源有限支持
          扩展性多个扩展点插件的形式接口的形式
          基于注解的支持支持支持支持
          限流基于QPS,支持基于调用关系的限流有限的支持Rate Limiter
          流量整形支持预热模式匀速器模式、预热排队模式不支持简单的Rate Limiter模式
          系统自适应保护支持不支持不支持
          控制台提供开箱即用的控制台,可配置规则、查看秒级监控,机器发观等简单的监控查看不提供控制台,可对接其它监控系统

          19.10 规则持久化

          19.10.1 是什么

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

          19.10.2 怎么玩

          将限流配置规则持久化进Nacos保存,只要刷新8401某个rest地址,sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,针对8401上sentinel上的流控规则持续有效

          19.10.3 步骤:修改cloudalibaba-sentinel-service8401

          1)POM

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

          server:port: 8401spring:application:name: cloudalibaba-sentinal-servicecloud:nacos:discovery:#Nacos服务注册中心地址(即:把此服务注册到注册中心8848‍)server-addr: 127.0.0.1:8848sentinel:transport:#配置Sentin dashboard地址(配置sentinel8080监控8401服务)dashboard: 127.0.0.1:8080# 默认8719端口,假如被占用了会自动从8719端口+1进行扫描,直到找到未被占用的 端口port: 8719 #指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServerdatasource: #<---------------------------关注点,添加Nacos数据源配置ds1:nacos:server-addr: localhost:8848dataId: cloudalibaba-sentinel-servicegroupId: DEFAULT_GROUPdata-type: jsonrule-type: flowmanagement:endpoints:web:exposure:include: '*'
          3)添加Nacos业务规则配置


          • 内容解析
            • resource:资源名称;
            • limitApp:来源应用;
            • grade:阈值类型,0表示线程数,1表示QPS;
            • count:单机阈值;
            • strategy:流控模式,0表示直接,1表示关联,2表示链路;
            • controlBehavior:流控效果,0表示快速失败,1表示Warm Up,2表示排队等待;
            • clusterMode:是否集群。
          [{"resource": "/rateLimit/byUrl","limitApp": "default","grade": 1,"count": 1,"strategy": 0,"controlBehavior": 0,"clusterMode": false}]
          4)添加配置,启动8401
          • 控制层方法:之前的方法

          • 配置流控规则

          • 启动8401

          5)快速访问测试接口
          • http://localhost:8401/rateLimit/byUrl
          6)停止8401再看sentinel
          • 停机后发现流控规则没有了
          7)重新启动8401再看sentinel
          • 乍一看还是没有,稍等一会儿

          • 多次调用:http://localhost:8401/rateLimit/byUrl

          • 刷新sentinel页面:重新配置出现了,持久化验证通过

          20 Seata处理分布式事务

          • SpringCloud Alibaba Seata处理分布式事务
          • 阳哥讲的版本太老了,这里我已黑马的版本为例进行学习。
            • 博客查看:待发布

          20.1 Seata-Server安装(1.7.0)

          20.3.1 版本说明

          • 说明:Seata不同版本的配置有很大的不同,1.4.2之前conf下需要修改2个配置文件,到现在都整合为了一个application.yml文件,下面讲解使用1.7.0版本如何进行安装配置(2023-9-5)

          20.1.2 Seata Server存储模式(3种)

          • seata-server-1.7.0.zip解压到指定目录并修改conf目录下的application.yml配置文件,先备份原始application.yml文件
          • 查看application.yml文件
          #Copyright 1999-2019 Seata.io Group.##Licensed under the Apache License, Version 2.0 (the "License");#you may not use this file except in compliance with the License.#You may obtain a copy of the License at##http://www.apache.org/licenses/LICENSE-2.0##Unless required by applicable law or agreed to in writing, software#distributed under the License is distributed on an "AS IS" BASIS,#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.#See the License for the specific language governing permissions and#limitations under the License.server:port: 7091 #它是UI界面的端口号,不是对外提供服务的端口号spring: #服务名application:name: seata-serverlogging: #日志config: classpath:logback-spring.xmlfile:path: ${user.home}/logs/seataextend:logstash-appender:destination: 127.0.0.1:4560kafka-appender:bootstrap-servers: 127.0.0.1:9092topic: logback_to_logstashconsole:#平台界面的用户名密码user:username: seatapassword: seataseata:config:#配置中心# support: nacos, consul, apollo, zk, etcd3type: fileregistry:#注册中心# support: nacos, eureka, redis, zk, consul, etcd3, sofatype: filestore: #存储中心# support: file 、 db 、 redismode: file#server: #这才是对外提供的端口号,默认是7091+1000=8091.所以不用配置#service-port: 8091 #If not configured, the default is '${server.port} + 1000'security:#安全secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017tokenValidityInMilliseconds: 1800000ignore:urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login
          • 3种存储模式:Seata Server需要对全局事务与分支事务进行存储,以便对它们进行管理。共存储模式目前支持三种:file、 db 与redis(后续将引入raft,mongodb)。
            • file模式:会将相关数据存储在本地文件中,一般用于Seata Server的中机测试。
            • db模式:会将相关数据存储在数据库中,一般用于生产环境下的Seata Server集群部著。生产环境下使用最多的模式。
            • redis模式:会将相关数据存储在redis 中,一般用于生产环境下的Seata Server集群部署。性能略高于db模式,如果对性能要求较高,可选择redis模式。

          20.1.3 配置步骤:以db模式为例

          1)修改application.yml配置文件

          说明:此文件的修改都可以参考示例文件的内容。

          修改之前先复制一份原始文件

          修改存储中心

          • 拷贝示例文件内容
          • 修改application.yml
          store:# support: file 、 db 、 redismode: dbsession:mode: dblock:mode: dbdb:datasource: druiddb-type: mysqldriver-class-name: com.mysql.jdbc.Driver #如果是mysql8.0驱动为:com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/seata" />user: rootpassword: rootmin-conn: 10max-conn: 100global-table: global_tablebranch-table: branch_tablelock-table: lock_tabledistributed-lock-table: distributed_lockquery-limit: 1000max-wait: 5000

          修改配置中心

          • 拷贝示例文件内容

          • 修改application.yml

          seata:config:# support: nacos, consul, apollo, zk, etcd3type: nacosnacos:server-addr: 127.0.0.1:8848namespace:group: fsp_tx_group #分组名称username: nacos #连接Nacos平台的用户名密码默认都是nacospassword: nacoscontext-path:##if use MSE Nacos with auth, mutex with username/password attribute#access-key:#secret-key:data-id: seataServer.properties#之后需要再nacos配置中心创建此文件。

          修改注册中心

          • 拷贝示例文件内容

          • 修改application.yml

          registry:# support: nacos, eureka, redis, zk, consul, etcd3, sofatype: nacosnacos:application: seata-server#启动后注册到注册中心的服务名server-addr: 127.0.0.1:8848group: fsp_tx_group #组名保持一致namespace:cluster: defaultusername: nacospassword: nacoscontext-path:##if use MSE Nacos with auth, mutex with username/password attribute#access-key:#secret-key:
          2)新建库seata,并执行脚本
          • 之前在application.yml文件中配置的是使用数据库来管理全局事务与分支事务,所以要创建库,在库中新建表。

          • 脚本位置:注意不推荐从官网上找脚本,因为官网上更新的速度比较慢可能会导致版本不一致。推荐从下载的安装包查找。

          • 创建seata数据库,并执行脚本

          3)seataServer.properties
          • 需要在nacos平台,配置此文件

          • 配置内容来源:

          • 复制一份原始文件,修改config.txt文件内容。


          #For details about configuration items, see https://seata.io/zh-cn/docs/user/configurations.html#Transport configuration, for client and servertransport.type=TCPtransport.server=NIOtransport.heartbeat=truetransport.enableTmClientBatchSendRequest=falsetransport.enableRmClientBatchSendRequest=truetransport.enableTcServerBatchSendResponse=falsetransport.rpcRmRequestTimeout=30000transport.rpcTmRequestTimeout=30000transport.rpcTcRequestTimeout=30000transport.threadFactory.bossThreadPrefix=NettyBosstransport.threadFactory.workerThreadPrefix=NettyServerNIOWorkertransport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandlertransport.threadFactory.shareBossWorker=falsetransport.threadFactory.clientSelectorThreadPrefix=NettyClientSelectortransport.threadFactory.clientSelectorThreadSize=1transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThreadtransport.threadFactory.bossThreadSize=1transport.threadFactory.workerThreadSize=defaulttransport.shutdown.wait=3transport.serialization=seatatransport.compressor=none#Transaction routing rules configuration, only for the clientservice.vgroupMapping.default_tx_group=default#If you use a registry, you can ignore itservice.default.grouplist=127.0.0.1:8091service.enableDegrade=falseservice.disableGlobalTransaction=false#Transaction rule configuration, only for the clientclient.rm.asyncCommitBufferLimit=10000client.rm.lock.retryInterval=10client.rm.lock.retryTimes=30client.rm.lock.retryPolicyBranchRollbackOnConflict=trueclient.rm.reportRetryCount=5client.rm.tableMetaCheckEnable=trueclient.rm.tableMetaCheckerInterval=60000client.rm.sqlParserType=druidclient.rm.reportSuccessEnable=falseclient.rm.sagaBranchRegisterEnable=falseclient.rm.sagaJsonParser=fastjsonclient.rm.tccActionInterceptorOrder=-2147482648client.tm.commitRetryCount=5client.tm.rollbackRetryCount=5client.tm.defaultGlobalTransactionTimeout=60000client.tm.degradeCheck=falseclient.tm.degradeCheckAllowTimes=10client.tm.degradeCheckPeriod=2000client.tm.interceptorOrder=-2147482648client.undo.dataValidation=trueclient.undo.logSerialization=jacksonclient.undo.onlyCareUpdateColumns=trueserver.undo.logSaveDays=7server.undo.logDeletePeriod=86400000client.undo.logTable=undo_logclient.undo.compress.enable=trueclient.undo.compress.type=zipclient.undo.compress.threshold=64k#For TCC transaction modetcc.fence.logTableName=tcc_fence_logtcc.fence.cleanPeriod=1h#Log rule configuration, for client and serverlog.exceptionRate=100#Transaction storage configuration, only for the server. The file, db, and redis configuration values are optional.store.mode=dbstore.lock.mode=dbstore.session.mode=db#Used for password encryption#store.publicKey=#If `store.mode,store.lock.mode,store.session.mode` are not equal to `file`, you can remove the configuration block.#store.file.dir=file_store/data#store.file.maxBranchSessionSize=16384#store.file.maxGlobalSessionSize=512#store.file.fileWriteBufferCacheSize=16384#store.file.flushDiskMode=async#store.file.sessionReloadReadSize=100#These configurations are required if the `store mode` is `db`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `db`, you can remove the configuration block.store.db.datasource=druidstore.db.dbType=mysqlstore.db.driverClassName=com.mysql.jdbc.Driverstore.db.url=jdbc:mysql://127.0.0.1:3306/seata" />=true&rewriteBatchedStatements=truestore.db.user=rootstore.db.password=rootstore.db.minConn=5store.db.maxConn=30store.db.globalTable=global_tablestore.db.branchTable=branch_tablestore.db.distributedLockTable=distributed_lockstore.db.queryLimit=100store.db.lockTable=lock_tablestore.db.maxWait=5000#These configurations are required if the `store mode` is `redis`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `redis`, you can remove the configuration block.#store.redis.mode=single#store.redis.single.host=127.0.0.1#store.redis.single.port=6379#store.redis.sentinel.masterName=#store.redis.sentinel.sentinelHosts=#store.redis.maxConn=10#store.redis.minConn=1#store.redis.maxTotal=100#store.redis.database=0#store.redis.password=#store.redis.queryLimit=100#Transaction rule configuration, only for the serverserver.recovery.committingRetryPeriod=1000server.recovery.asynCommittingRetryPeriod=1000server.recovery.rollbackingRetryPeriod=1000server.recovery.timeoutRetryPeriod=1000server.maxCommitRetryTimeout=-1server.maxRollbackRetryTimeout=-1server.rollbackRetryTimeoutUnlockEnable=falseserver.distributedLockExpireTime=10000server.xaerNotaRetryTimeout=60000server.session.branchAsyncQueueSize=5000server.session.enableBranchAsyncRemove=falseserver.enableParallelRequestHandle=false#Metrics configuration, only for the servermetrics.enabled=falsemetrics.registryType=compactmetrics.exporterList=prometheusmetrics.exporterPrometheusPort=9898
          • 以上这些配置参数信息所代表的含义,可以查看官网:
          • 启动Nacos,并登录管理页面
          • 在配置列表新建:seataServer.properties,配置内容为刚刚修改的config.txt文件,注意类型为properties。

          4)启动

          先启动Nacos端口号8848,再启动seata-server

          • 位置
          • cmd,输入命令:seata-server.bat -m db,默认是file所以要指定db。如果不是本机还要指定ip和端口号。
          • 查看服务列表:

          20.2 domain实体类

          • 不同的公司,实体类的叫法可能不同。
          • 封装数据库的实体类。与前端页面交互的实体类。