Spring Cloud Alibaba三大组件

本文深入探讨了Nacos作为云原生应用的动态服务发现、配置管理和服务管理平台的角色,以及Seata在微服务架构下提供高性能分布式事务服务的解决方案。文章详细介绍了Nacos的注册中心与配置中心功能,包括依赖引入、配置添加、环境切换、集群搭建等,并讲解了Seata的事务协调、资源管理及分布式事务服务。同时,还涵盖了Sentinel在流量控制、熔断降级和系统负载保护等方面的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring Cloud Alibaba

Nacos

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

可以理解为之前的 Eureka + Config + Bus

官网地址 : https://nacos.io/

下载最新的稳定版压缩包,解压之后进入bin目录,启动命令如下:

sh startup.sh -m standalone  

控制台地址 :http://localhost:8848/nacos

Nacos作为服务注册中心

引入依赖:

<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

添加配置:

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

启动类上需要加上@EnableDiscoveryClient注解

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

创建两个服务提供者 和 一个服务消费者,我们观察引入的这个依赖包
在这里插入图片描述
nacos已经集成了netflix的ribbon,所以nacos天生支持负载均衡。不要忘了消费者微服务注册RestTemplate时,加上@LoadBalanced注解。

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?/entry=serverMode&value=CP'
Nacos作为服务配置中心

引入依赖:

<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>

配置文件:

需要两个配置文件 bootstrap.yml 和 application.yml。Nacos同Spring Cloud Config一样,在项目初始化时,要保证先从配置中心进行配置拉取,拉取配置之后,才能保证项目的正常启动。

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

bootstrap.yml:

server:
  port: 3377

spring:
  application:
    name: nacos-config-client
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # Nacos作为服务注册中心地址
      config:
        server-addr: localhost:8848 # Nacos作为服务配置中心地址
        file-extension: yml # 指定yaml格式的配置

application.yml:

spring:
  profiles:
    active: dev

下面是nacos官方手册的一段说明

在 Nacos Spring Cloud 中,dataId 的完整格式如下:

${prefix}-${spring.profiles.active}.${file-extension}
  • prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix来配置。
  • spring.profiles.active 即为当前环境对应的 profile
  • 注意:当 spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 ${prefix}.${file-extension}
  • file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 propertiesyaml 类型。

根据文档说明,我们需要做如下配置: (配置列表 - - > 新建配置)
在这里插入图片描述

经过测试,不仅可以获取信息,而且修改配置文件,可以实时刷新,不需要像Spring Cloud Config一样需要发Post请求。

Namespace 、 Group 、DataID 三者关系

image-20200818150806027

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

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

Nacos默认命名空间是public, Namespace主要用来实现隔离。

比如我们现在有三个环境:开发(dev)、测试(test)、生产环境(prod) ,我们就可以创建三个Namespace,不同的Namespace之间是隔离的。

Group默认是DEFAULT_GROUP ,GROUP可以把不同的微服务划分到同一个分组里面去

Service就是微服务,一个Service可以包含对个Cluster(集群),Nacos默认Cluster是DEFAULT,Cluster是对指定微服务的一个虚拟划分。比如为了容灾,将Service微服务分别部署在杭州和广州机房,这时就可以给杭州机房的Service微服务起一个集群名称(HZ),广州机房的Service微服务起一个集群名称(GZ),还可以尽量让同一个机房的微服务互相调用,以提升性能。

最后是Instance,就是微服务的实例。

切换环境

  1. 控制台操作新增一个test环境的配置文件
    在这里插入图片描述
  2. 修改配置文件,指定spring.profile.active=test,启动后,读取的配置信息就是对应的nacos-config-client-test.yml中的内容。

GROUP分组方案

新建配置时,指定自定义的GROUP
在这里插入图片描述
bootstrap.yml配置文件中需要加上group的配置

spring:
  application:
    name: nacos-config-client
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # Nacos作为服务注册中心地址
      config:
        server-addr: localhost:8848 # Nacos作为服务配置中心地址
        file-extension: yml # 指定yaml格式的配置
        group: TEST_GROUP

为了测试区分,application.yml中重新指定环境为 info

命名空间

默认会有一个public的命名空间且不可删除,可以自己新建自定义命名空间,id会自动生成
在这里插入图片描述
此时,服务列表中就多了这个两个可选项目,可以在新的命名空间下面新建服务配置了。

在这里插入图片描述

这里的配置和在public命名空间下没有区别,代码中需要通过id值来指定对应哪个命名空间

spring:
  application:
    name: nacos-config-client
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # Nacos作为服务注册中心地址
      config:
        server-addr: localhost:8848 # Nacos作为服务配置中心地址
        file-extension: yml # 指定yaml格式的配置
        group: TEST_GROUP
        namespace: c2cd8b84-c8a2-4ef6-a751-5d8390ae60a0
Nacos 集群

方法一:

  1. 复制三分nacos包(本质就是三个java项目),修改application.properties中的server.port分别为8841、8842、8843
  2. 修改复制cluster.conf.example模板生成一个新的cluster.conf文件。内容修改如下
10.0.0.30:8841
10.0.0.30:8842
10.0.0.30:8843
  1. 本身项目会自带一个derby数据库。但是为了集群中每个nacos都共用同样的数据,我们需要修改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
db.user=root
db.password=heling

这个本地数据库,nacos为我们提供了数据库脚本,在conf目录下名为nacos-mysql.sql

方法二:

  1. cluster.conf和数据库配置同上,不需要复制成三个项目来逐个启动,只需要将启动脚本辅助三份,然后运行这个三个启动脚本即可。
  2. 辅助启动脚本,分别命名为 startup-8841.sh 、startup-8842.sh、startup-8843.sh。然后分别启动
./startup-8841.sh 
./startup-8842.sh 
./startup-8843.sh 

内容修改如下:

#===========================================================================================
# JVM Configuration
#===========================================================================================
JAVA_OPT="${JAVA_OPT} -Dserver.port=8841"
安装nginx

[用brew安装nginx并配置]

nginx.conf解读

nginx的配置文件,即 nginx.conf 分为三个大块

第一部分:全局块

从配置文件开始到events块之间的内容,主要设置一下影响nginx服务器整体运行的配置指令,主要包括配置运行nginx服务器的用户(组)、允许生成的worker process数,进程PID存放的路径、日志存放路径和类型以及配置文件的引入等。

比如默认配置中的

worker_processes	1;

这是Nginx服务器并发处理服务的关键配置,这个值越大,可以支持的并发处理量也越多,但是受到硬件、软件等设备的制约。

第二部分:events块

events块涉及的指令主要影响Nginx服务器与用户的网络连接,常用的设置包括 是否对多 work process下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种时间驱动模型来处理连接请求,每个work process 可以同时支持的最大连接数等。

例如:默认配置中的

events {
    worker_connections  1024;
}

就表示每个work process支持的最大连接数为 1024

第三部分:http块

直接拿我们nacos来举例子,我们监听1111端口,然后通过负载均衡来请求我们的三个nacos服务。

http {
    #gzip  on;
    upstream cluster{
        server 127.0.0.1:8841;
        server 127.0.0.1:8842;
        server 127.0.0.1:8843;
    }

    server {
        listen       1111;
        server_name  localhost;

        location / {
            #root   html;
            #index  index.html index.htm;
            proxy_pass http://cluster;
        }
		}
}

然后修改我们的9003微服务,将注册中心地址改成localhost:1111。

访问localhost:1111/nacos,检查服务列表,服务注册成功

Sentinel

Sentinel:分布式系统的流量卫兵

相当于是豪猪哥的升级版,借鉴了豪猪哥的设计思想。

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

Sentinel特点:

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

Sentinel的主要特性:

Sentinel-features-overview

Sentinel官方介绍

什么是SPI?

流控规则

相关名词:

  • 资源名:唯一名称,默认请求路径
  • 针对来源:Sentinel可以针对调用者进行限流,填写微服务名,默认default(不区分来源)
  • 阈值类型/单机阈值
    • QPS(每秒的请求数量):当调用该api的QPS达到阈值的时候,进行限流
    • 线程数:点调用该api的线程数达到阈值时,进行限流
  • 是否集群
  • 流控模式:
    • 直接:api达到限流条件时,直接限流
    • 关联:当关联的资源达到阈值时,就限流自己
    • 链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流)【api级别的针对来源】
  • 流控效果:
    • 快速失败:直接失败,抛异常
    • Warm Up:根据codeFactor(冷加载因子,默认3)的值,从阈值/codeFactor,经过预热时长,才达到设置的QPS阈值
    • 排队等待:匀速排队,让请求以匀速的速度通过,阈值类型必须设置为QPS,否则无效

直接-快速失败

这种规则也是默认规则,比如下面这个配置

阈值类型:QPS
在这里插入图片描述

代表一秒值运行请求一次,超过的话直接报错

而且setinel的配置是直接生效的,不需要重启任何服务。下面是请求限流的报错提示信息
image-20200820120929944

阈值类型:线程数
在这里插入图片描述
简单理解QPS在请求时,就被做了限制,线程数(设为1)限制是所有请求都放进来,但是只有一个线程处理这些请求,当进来的请求发现该线程忙碌状态,也就是当前没有线程处理该请求,就报错(当模式为直接的时候)。

当阈值类型为线程数的时候,流量模式可选,但是没有流控效果选项。

直接测试发现没有任何效果,是因为我们接口处理的业务过于简单,一个线程也能轻松应对,现在我们模拟业务耗时0.8s。那么我们两个请求间隙小于这个时间时,就代表达到阈值,直接报错

@GetMapping("/testA")
public String testA() {
  try {
    // 模拟业务耗时
    Thread.sleep(800);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  return

再次快速请求接口:

在这里插入图片描述

关联

即当B达到阈值时,让A限流,这里我们简单模拟 testB达到阈值,对testA限流。

实际应用中,因为很多服务是相互关联的,如支付接口到达阈值,需要对下单接口限流。
在这里插入图片描述
测试:利用postman 或者 jmeter工具对testB进行频繁访问,使其QPS达到阈值,此时再访问A,发现A被限流。

postman模拟并发

  1. 新建Collections,右键添加请求,run

在这里插入图片描述

  1. 设置参数

在这里插入图片描述

链路

参考博客

流控效果-Warm Up

在这里插入图片描述

称之为预热,冷却因子coldFactor默认为3,如上面这个配置表示,请求QPS一开始不是并不是10,有个预热的过程,防止请求一开始处于低水位,突然猛增导致服务器瘫痪。而是 QPS一开始从 10(设置的QPS)/3(冷却因子)开始,经过5s(设置的预热时长)后阈值慢慢升高至10

排队等待

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

在这里插入图片描述
以上配置表示 /testA每秒一次请求,超过的话就排队等待,等待的超时时间为20000毫秒。

测试:post设置每300ms请求一次testA。 查看后台日志。就类似与车站排队一样一秒一个通过。

在这里插入图片描述

项目小问题记录

当发现我们的服务注册不上nacos的时候,后台日志表现为 请求超时,但是页面显示是可以正常访问nacos。

可能为两种情况

  • 之前配置了持久化,所以要请求数据库,所以要保证数据库是正常启动的
  • 之前配置过集群,如果我们现在用单机的话,应该启动时候指定启动参数 -m standalone

Sentinel降级

Sentinel熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制。让请求快速失败。避免影响到其他的资源而导致级联错误。

当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都会自动熔断(默认行为是抛出DegradeException)。

Sentinel熔断器是**没有半开**状态的。(新版本又有这个状态了)

半开的状态系统会自动去检测是否请求有异常,没有异常就关闭熔断器恢复使用,有异常则继续打开断路器。Hystrix就是这种模式。

在这里插入图片描述

Sentinel 提供以下几种熔断策略:

  • 慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。
  • 异常比例 (ERROR_RATIO):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
  • 异常数 (ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。

以上规则中,单位统计时长默认值为1s,最小请求数目默认值为5

引入问题:

目前我们服务限流和服务熔断返回值都是 Blocked by Sentinel(flow limiting)这个默认的提示。如何像Hystrix那样自定义降级处理呢? (也就是下面热点限流例子中的@SentinelResource注解)

热点限流

何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:

  • 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
  • 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制

热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。

 // 测试热点限流
@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey", blockHandler = "deal_testHotKey")
public String testHotKey(@RequestParam(value = "p1", required = false) String p1,
                         @RequestParam(value = "p2", required = false) String p2) {
  return "**** test hot key ****";
}

public String deal_testHotKey(String p1, String p2, BlockException blockException) {
  return "**** test hot key **** o(╥﹏╥)o";
}

这是我们测试接口,有两个参数p1和p2 ,接下来我们配置一种热点限流规则,对第一个参数p1限流。

在这里插入图片描述
热点限流仅支持QPS模式,资源名也就是@SentinelResource设置的value值,这个值可以自定义,一般我们设置和接口地址一样,参数索引0,代表第一个参数,本例中就是p1,阈值和统计窗口时长都设置为1 就代表一秒超过1个请求是带p1参数的就进行限流

@SentinelResource还可以通过blockHandler指定自定义的限流处理方法。处理方法必须和原方法参数列表一致,并且还需要一个BlockException参数。

高级选项之参数例外项

我称之为 vip 配置项。正如小马哥所说,充钱你就会变得更强。我们可以为某些参数的值开辟特殊通道。如当p1的值为999时,阈值可以改成100

在这里插入图片描述

经过测试发现,p1为其他值时,QPS大于1则限流,P1为999时不会(QPS<100)。

注意:

  1. @SentinelResource中blockHandler指定的处理方法,只有发生热点限流时才会进入。如果是其他情况如程序运行异常,是不会进入这个限流处理方法的。
  2. 当未指定限流处理方法时,发生了热点限流,不会提示默认信息 Blocked by Sentinel(flow limiting),而是直接显示错误页面。

系统规则

系统保护规则是从应用级别的入口流量进行控制,从单台机器的 load、CPU 使用率、平均 RT、入口 QPS 和并发线程数等几个维度监控应用指标,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。

系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量(EntryType.IN),比如 Web 服务或 Dubbo 服务端接收的请求,都属于入口流量。

系统规则支持以下的模式:

  • Load 自适应(仅对 Linux/Unix-like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps * minRt 估算得出。设定参考值一般是 CPU cores * 2.5
  • CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。
  • 平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
  • 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
  • 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。

扩展

Sentinel注意有三个核心Api

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

@SentinelResource深入

  • 按照请求url 配置流控规则 会有默认兜底方法 也就是 默认的那个错误提示
  • 按照资源名配置的 需要自己写处理方法

自定义限流处理逻辑

  • 自定义限流处理类 CustomerBlcokHandler
  • 定义静态处理方法
public class CustomerBlockHandler {
    public static CommonResult handlerException1(BlockException e) {
        return new CommonResult(444, "测试自定义处理之限流-------1", e.getMessage());
    }

    public static CommonResult handlerException2(BlockException e) {
        return new CommonResult(444, "测试自定义处理之限流-------2", e.getMessage());
    }
}
  • 指定使用这个自定义处理类中的指定方法
    • 通过blockHandlerClass指定自定义全局异常处理类
    • 通过blockHandler指定类中方法
@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler",
                  blockHandlerClass = CustomerBlockHandler.class,
                  blockHandler = "handlerException1")
public CommonResult customerBlockHandler() {
  return new CommonResult(200, "测试自定义处理之未被限流", new Payment(2020L, "serial003"));
}

配置服务降级处理

该接口是请求注册在nacos的payment服务。该接口为了测试降价,当参数为1、2、3时返回正常数据,参数为4时,会抛出IllegalArgumentException异常,其他参数值则会返回空指针异常

@GetMapping("/consumer/fallback/{id}")
//@SentinelResource(value = "fallback") // 1. 无配置情况 直接显示错误页面 这是不友好的,需要配置错误处理
//@SentinelResource(value = "fallback", fallback = "handlerFallback") // 2. 配置fallback 只负责业务异常
//@SentinelResource(value = "fallback", blockHandler = "blockHandler") // 3. 配置blockHandler,只负责Sentinel配置违规
//@SentinelResource(value = "fallback", fallback = "handlerFallback", blockHandler = "blockHandler") //组合使用
@SentinelResource(value = "fallback", fallback = "handlerFallback", blockHandler = "blockHandler",
                  exceptionsToIgnore = {IllegalArgumentException.class}) // 忽略指定异常 不再为它降级 但是和限流无关
public CommonResult<Payment> fallback(@PathVariable("id") 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;
}

public CommonResult handlerFallback(Long id, Throwable e) {
  Payment payment = new Payment(id, null);
  return new CommonResult(444, "业务异常处理方法,exception内容:" + e.getMessage(), payment);
}

public CommonResult blockHandler(Long id, BlockException e) {
  return new CommonResult(445, "sentinel限流 " + e.getClass().getCanonicalName() + "\t服务不可用");
}

通过测试我们得出结论:

- fallback 管运行异常
- blockHandler 管(Sentinel)配置违规

即 fallback做的是服务降级,blockHandler做的是服务限流。

Sentinel 配合 openFeign

  1. 引入依赖
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  1. 主启动类 加注解支持openFeign
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderNacosMain84 {
    public static void main(String[] args) {
        SpringApplication.run(OrderNacosMain84.class, args);
    }
}
  1. openFeign接口
@FeignClient(value = "nacos-payment-provider", fallback = PaymentFallbackService.class)
public interface PaymentService {
    @GetMapping(value = "/paymentSQL/{id}") // 根据类上注解指定的微服务 去请求这里指定的接口
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);
}
  1. 统一降级处理类
@Component
public class PaymentFallbackService implements PaymentService {
    @Override
    public CommonResult<Payment> paymentSQL(Long id) {
        return new CommonResult<>(444, "服务降级返回,-----PaymentFallbackservice", new Payment(id, "error serial"));
    }
}

测试: 当服务出错 或者 服务停用时 ,这个指定的服务降级处理类 生效

问题?

每次重启服务后,测试接口发现服务限流不生效了,然后查看Sentinel控制台,发现配置被清空。所以如何持久化流控配置呢?

之前我们nacos持久化用的是mysql数据库,那么我们Sentinel持久化也可以这样,但是除了我们常用的持久化服务,还可以将我们的限流规则持久化进 Nacos保存。

  1. 引入依赖
<!-- 做持久化用 -->
<dependency>
  <groupId>com.alibaba.csp</groupId>
  <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
  1. 配置数据源,即指定读取nacos的哪个配置文件(json文件)
spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        # 监控台地址
        dashboard: localhost:8888
        # 默认8719,如果被占用会自动从8719开始依次加1,直到找到未被占用的端口
        port: 8719
      # 配置数据源 读取nacos中的流控配置信息
      datasource:
        ds1:
          nacos:
            server-addr: localhost:8848
            dataId: cloudalibaba-sentinel-service
            groupId: DEFAULT_GROUP
            data-type: json
            rule-type: flow
  1. nacos中对应的配置
[
    {
        "resource":"/rateLimit/byUrl",
        "limitApp":"default",
        "grade":1,
        "count":1,
        "strategy":0,
        "controlBehavior":0,
        "clusterMode":false
    }
]

这里每个字段对应了我们sentinel控制台的配置

  • resource 资源名称

  • limitApp 来源应用

  • garde 阈值类型 0表示线程数 1表示QPS

  • count 单机阈值

  • strategy 流控模式 0表示直接 1表示关联 2表示链路

  • controlBehavior 流控效果 0 表示快速失败 1 表示Warm up 2 表示排队等待

  • clusterMode 是否集群

再次重启,请求一次接口就发现,限流规则依然存在,查看Sentinel控制台,可以看到对应的配置规则。

Seata

Seata是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简答易用的分布式事务服务。

  • TC (Transaction Coordinator) - 事务协调者

    维护全局和分支事务的状态,驱动全局事务提交或回滚。

  • TM (Transaction Manager) - 事务管理

    定义全局事务的范围:开始全局事务、提交或回滚全局事务。

  • RM (Resource Manager) - 资源管理器

    管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

启动seata服务之前 需要改下配置文件

conf文件夹下的file.conf文件

​ store 中mode 切换成mysql ,然后将mysql的配置信息改成自己的(账号、密码、数据库名)

store {
  ## store mode: file、db、redis
  mode = "db"

  ## file store property
  file {
    ...
    ...
    ...
  }

  db {
    datasource = "druid"
    ## mysql/oracle/postgresql/h2/oceanbase etc.
    dbType = "mysql"
    driverClassName = "com.mysql.jdbc.Driver"
    url = "jdbc:mysql://127.0.0.1:3306/seata"
    user = "root"
    password = "heling"
  	...
  	...
  	...
  }

  redis {
    ...
    ...
    ...
  }
}

conf文件夹下的registry.conf文件

registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  type = "nacos"

  nacos {
    application = "seata-server"
    serverAddr = "127.0.0.1:8848"
    group = "SEATA_GROUP"
    namespace = ""
    cluster = "default"
    username = ""
    password = ""
  }
}

config {
  # file、nacos 、apollo、zk、consul、etcd3
  type = "file"
  ...
  ...
  ...
  file {
    name = "file.conf"
  }
}

这两个配置都是指定以何种方式读取配置信息,第二个文件指定config配置中 读取的就是第一个配置文件,所以这两个文件实际上只配最后一个文件就行。

初始化数据库

​ 新建数据库 seata ,就是上面配置指定的数据库名

​ 数据库脚本文件位置: https://github.com/seata/seata/blob/1.3.0/script/server/db/mysql.sql

执行此脚本,将生产三个表 global_tablebranch_tablelock_table

新建三个数据库 来模拟业务场景 对应的也是三个微服务

  • 订单微服务 - 对应数据库和表 seata_order.t_order
  • 库存微服务 - 对应数据库和表 seata_order.t_storage
  • 账户微服务 - 对应数据库和表 seata_account.t_account
img

这三个库,每个库下面再建一张表 undo_log ,建表语句见官网http://seata.io/zh-cn/docs/user/quickstart.html

CREATE TABLE `undo_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int(11) NOT NULL,
  `log_created` datetime NOT NULL,
  `log_modified` datetime NOT NULL,
  `ext` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

未完待续 …

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值