1. 简介
为什么会出现?
SpringCloud Netflix进入维护模式,意味着不再向模块添加新的功能和组件
能干嘛?
服务降级限流、服务注册与发现、分布式配置管理、消息驱动能力、阿里云对象存储、分布式任务调度
2. Nacos服务注册配置中心
2.1 安装
介绍
Nacos是注册中心+配置中心的组合,即Nacos = Eurake + Config + Bus
下载
https://github.com/alibaba/nacos/releases/download/1.1.4/nacos-server-1.1.4.zip
解压,进入bin目录,双击sartup.cmd启动!访问 http://localhost:8848/nacos:
2.2 Nacos服务注册中心
2.2.1 服务提供者注册
-
新建module:cloudalibaba-provider-payment9001
-
POM
-
父POM
-
子POM
<dependencies> <!--SpringCloud ailibaba nacos --> <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>
-
-
YML
server: port: 9001 spring: application: name: nacos-payment-provider cloud: nacos: discovery: server-addr: localhost:8848 #配置Nacos地址 management: endpoints: web: exposure: include: '*'
-
主启动
@SpringBootApplication @EnableDiscoveryClient public class PaymentMain9001 { public static void main(String[] args) { SpringApplication.run(PaymentMain9001.class,args); } }
-
业务类
@RestController public 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; } }
-
新建9002:效果如下:
2.2.2 消费者注册和负载
-
新建Module:cloudalibaba-consumer-nacos-order83
-
POM
<dependencies> <!--SpringCloud ailibaba nacos --> <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>
-
YML
server: port: 83 spring: application: name: nacos-order-consumer cloud: nacos: discovery: server-addr: localhost:8848 #消费者将要去访问的微服务名称(注册成功进nacos,的微服务提供者) service-url: nacos-user-service: http://nacos-payment-provider
-
主启动类
@EnableDiscoveryClient @SpringBootApplication public class PaymentMain9002 { public static void main(String[] args) { SpringApplication.run(PaymentMain9002.class,args); } }
-
业务类
@Configuration public class ApplicationContextConfig { @Bean @LoadBalanced public RestTemplate getRestTemplete(){ return new RestTemplate(); } }
@RestController@Slf4jpublic class OrderNacosController { @Resource private RestTemplate restTemplate; @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); }}
-
测试
http://localhost:83/consumer/payment/nacos/13 实现了负载均衡
2.2.3 服务注册中心对比
Nacos支持AP和CP的切换:
2.3 Nacos配置中心
2.3.1 基础配置
-
新建module:cloudalibaba-config-nacos-client3377
-
POM
<dependencies> <!--nacos-config--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <!--SpringCloud ailibaba nacos --> <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>
-
YML
Nacos同springcloud-config一样,在项目初始化时,要保证先从配置中心进行配置拉取,拉取配置之后,才能保证项目的正常启动。springboot中配置文件的加载是存在优先级顺序的,bootstrap优先级高于application。-
bootstrap
#naco配置 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: yaml #指定yamL格式的配置 # $fspring.application.name}-${spring.profile.active]}.${spring.cLoud.nacos,config.file-extension}
-
application
spring: profiles: active: dev #表示开发环境
-
-
主启动类
@EnableDiscoveryClient @SpringBootApplication public class NacosConfigClientMain3377 { public static void main(String[] args) { SpringApplication.run(NacosConfigClientMain3377.class,args); } }
-
业务类
@RestController @RefreshScope //支持nacos动态刷新 public class ConfigClientController { @Value("${config.info}") private String configInfo; @GetMapping("/config/info") public String getConfigInfo(){ return configInfo; } }
-
在NACOS中添加配置信息
配置规则:Nacos中的dataid的组成格式及与SpringBoot配置文件中的匹配规则
-
自带动态刷新
2.3.2 分类配置
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,就是微服务的实例。
DataId配置方案
-
指定spring.profile.active和配置文件的DatalD来使不同环境下读取不同的配置
-
默认空间+默认分组+新建dev和test两个dataid,通过spring.profile.active属性就能进行多环境下配置文件的读取,测试:
想切换哪个环境就换成哪个环境
group分组方案
namespace空间方案
2.4 Nacos集群持久化配置
集群架构说明
- 默认Nacos使用嵌入式数据库实现数据的存储。所以,如果启动多个默认配置下的Nacos节点,数据存储是存在一致性问题的。为了解决这个问题,Nacos采用了集中式存储的方式来支持集群化部署,目前只支持MySQL的存储。
持久化切换配置
-
Nacos默认自带的是嵌入式数据库derby
-
derby到mysql切换配置步骤
-
nacos的conf目录下找到sql脚本:nacos-mysql.sql,在数据库中执行
-
nacos的conf目录下找到application.properties:在最后添加以下内容
spring.datasource.platform=mysql db.num=1 db.url.O=jdbc:mysql://127.0.0.1:3306/nacos_config? characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true db.user=root db.password=admin
-
最后进入nacos测试,发布配置文件,发现在数据库中有:
-
2.5 Nacos的Linux安装
- 下载地址:https://github.com/alibaba/nacos/releases/download/1.4.1/nacos-server-1.4.1.tar.gz(1.4.1版本)
- 在opt目录中解压即可
2.6 集群配置(上)
-
在Linux上Mysql数据库配置,跟在windows上一致,需要新建nacos_config库并生成表
-
application.properties配置,跟windows上一致
-
Linux服务器上nacos集群配置cluster.conf
-
梳理出三台不同nacos集群的服务端口号:3333、4444、5555(cluster.conf)
-
-
编辑nacos的启动脚本startup.sh,使他能够接受不同的启动端口:
2.7 集群配置(下)
测试:启动3333、4444、5555,启动nginx,测试网址:http://192.168.200.130:1111/nacos/#/login,登录密码均为nacos!
(一定要注意如果访问失败很有可能是端口号没有打开!!!)
新建一条配置测试:
微服务cloudalibaba-provider-payment9002注册进nacos集群:
修改配置文件:
server:
port: 9002
spring:
application:
name: nacos-payment-provider
cloud:
nacos:
discovery:
#server-addr: localhost:8848 #配置Nacos地址
#换成nginx的1111端口,做集群
server-addr: 192.168.200.130:1111
management:
endpoints:
web:
exposure:
include: '*'
3. Sentinel熔断与限流
3.1 简介
是什么
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel以流量为切入点,从流量控
制、熔断降级、系统负载保护等多个维度保护服务的稳定性。一句话,优化版的Hystrix。
特征
- 丰富的应用场景:Sentinel承接了阿里巴巴近10年的双十一大促流量的核心场景,例如秒杀(即突
发流量控制在系统容量可以承受的范围)、裆息削峰填谷、集群流量控制、实时熔断下游不可用应
用等。 - 完备的实时监控:Sentinel同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器
秒级数据,甚至500台以下规模的集群的汇总运行情况。 - 广泛的开源生态:Sentinel提供开箱即用的与其它开源框架/库的整合模块,例如与Spring Cloud.
Dubbo、gRPC的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入Sentinel,
完善的SPI扩展点: Sentinel提供简单易用、完善的SPI扩展接口。您可以通过实现扩展接口来快
速地定制逻辑。例如定制规则管理、适配动态数据源等。
3.2 下载运行
-
下载地址:https://github.com/alibaba/Sentinel/releases/download/1.7.0/sentinel-dashboard-1.7.0.jar
-
sentinel分为两部分:
- 核心库(Java客户端)不依赖任何框架/库,能够运行于所有Java运行时环境,同时对Dubbo /
Spring Cloud等框架也有较好的支持。 - 控制台(Dashboard)基于Spring Boot开发,打包后可以直接运行,不需要额外的Tomcat等应用
容器。
- 核心库(Java客户端)不依赖任何框架/库,能够运行于所有Java运行时环境,同时对Dubbo /
-
安装:
-
在目录下命令行中输入:java -jar .\sentinel-dashboard-1.7.0.jar
-
输入localhost:8080,进入sentinel页面,用户名密码均为sentinel
-
3.3 Sentinel初始化监控
新建一个Module:cloudalibaba-sentinel-service8401
-
POM
<dependencies> <!-- alibaba sentinel --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-sentinel</artifactId> </dependency> <!-- sentinel-datasource-nacos 后续做持久化用到--> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!--SpringCloud ailibaba nacos --> <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>
-
YML
server: port: 8401 spring: application: name: cloudalibaba-sentinel-service cloud: nacos: discovery: server-addr: localhost:8848 sentinel: transport: #配置sentinel dashboard地址 dashboard: localhost:8080 #默认8719端口,假如被占用会自动从8719端口+1,直至找到未被占用的端口 port: 8719 management: endpoints: web: exposure: include: '*'
-
主启动
@EnableDiscoveryClient @SpringBootApplication public class MainApp8401 { public static void main(String[] args) { SpringApplication.run(MainApp8401.class,args); } }
-
业务类FlowLimitController
@RestController public class FlowLimitController { @GetMapping("testA") public String testA(){ return "---------testA"; } @GetMapping("testB") public String testB(){ return "---------testB"; } }
启动Sentinel和微服务8401,查看控制台:
Sentinel执行的是懒加载机制,执行一次访问即可!http://localhost:8401/testA或http://localhost:8401/testB:
3.4 流控规则
基本介绍
-
资源名∶唯一名称,默认请求路径
-
针对来源: Sentinel可以针对调用者进行限流,填写微服务名,默认default(不区分来源)
-
阈值类型/单机阈值:
- QPS(每秒钟的请求数量)︰当调用该api的QPS达到阈值的时候,进行限流
- 线程数:当调用该api的线程数达到阈值的时候,进行限流
-
是否集群:不需要集群
-
流控模式:
- 直接:api达到限流条件时,直接限流
- 关联:当关联的资源达到阈值时,就限流自己
- 链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流)【api级别的针对来源】
-
流控效果
- 快速失败:直接失败,抛异常
- Warm up:根据codeFactor(冷加载因子,默认3)的值,从阈值/codeFactory,经过预热时长,才达到设置的QPS阈值
- 排队等待:匀速排队,让请求以匀速的速度通过,阈值类型必须设置为QPS,否则无效
3.4.1 流量模式1:直接
QPS直接失败
表示1s内查询超过1次就是失败!
线程数直接失败
QPS:如果超过阈值,其余的请求直接拒绝,御敌于国门之外
线程数直接失败:如果超过阈值,其余的请求无法访问,报错,但是并没有拒绝,关门打狗!
3.4.2 流控模式2:关联
简介
当关联的资源达到阈值时,就限流自己,即当与A关联的资源B达到阀值后,就限流A自己,B惹事,A挂了
Postman模拟并发访问testB:
此时A又挂了:
3.4.3 流控模式3:链路
介绍
多个请求调用了同一个微服务
3.4.4 流控效果1:预热
介绍
-
快速失败:默认的流控效果,直接提示失败消息!
-
公式:阈值除以coldFactory(默认值为3),经过预热时长以后才会达到阈值!
-
默认coldFactory为3,即请求QPS从threshod/3开始,经预热时长逐渐升高设定的QPS阈值
-
应用:秒杀系统在开启的瞬间,会有很多流量上来,很有可能把系统打死,预热方式就是把为了保护系统,可慢慢的把流量放迸来,慢慢的把阀值增长到设置的阀值。
3.4.5 流控效果2:排队等待
介绍
匀速排队,让请求以均匀的速度通过,阀值类型必须设成QPS,否则无效。(漏桶算法)
3.5 降级规则
简介
- RT(平均响应时间,秒级)
平均响应时间超出阈值且在时间窗口内通过的请求>=5,两个条件同时满足后触发降级,窗口期过后关闭断路器,RT最大4900(更大的需要通过-Dcsp.sentinel.statistic.max.rt=XXXX才能生效) - 异常比列(秒级):QPS >=5且异常比例超过阈值时,触发降级;时间窗口结束后,关闭降级
- 异常数(分钟级):异常数超过阈值时,触发降级;时间窗口结束后,关闭降级
- Sentinel的断路器是没有半开状态的!
3.5.1 降级策略1:RT
3.5.2 降级策略2:异常比例
3.5.3 降级策略3:异常数
异常数:当资源近1分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若tiiewindow小于60s,则结束熔断状态后仍可能再进入熔断状态。
3.6 热点规则
介绍
- 热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
- 自定义服务降级从**@HystrixCommand到@SentinelResource**
配置实现
-
Controller
@RestController public class FlowLimitController { @GetMapping("/testHotKey") @SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey") //随便叫啥都可以,只是为了编码的统一和规范和上面一直 public String testhotKey(@RequestParam(value = "p1",required = false) String p1, @RequestParam(value = "p1",required = false) String p2){ return "------testHotKey"; } public String deal_testHotKey(String p1, String p2, BlockException exception){ return "兜底┭┮﹏┭┮"; //sentinel默认提示为Blocked by sentinel (flow Limiting) } }
-
新增热点限流规则:方法testHotkey中的第一个参数只要QPS超过每秒1次,马上降级处理
-
测试:
-
如果,没有使用兜底方法,即去掉了blockHandler = “deal_testHotKey”,当QPS超过阈值,直接调到ERROR PAGE,对用户不友好!
参数例外项
-
在上述的情况下,当p1参数在1s内的QOS超过某个阈值的时候,p1马上就会被限流,现在我们期望,当p1是某个特殊值的时候,它的限流值和平时不太一样,例如当p1值为5的时候,它的阈值可以达到200,这就要用到参数例外项了。
-
配置:当p1为5的时候,限流阈值为200,当不为5的时候,限流阈值为1!
-
当方法中出现异常的时候,无论是否违背热点规则,都无法进行兜底了。
@SentinelResource处理的是Sentinel控制台配置的违规情况,有blockHandler方法配置的兜底处理,但运行时异常他不管,即它只管配置出错,运行出错该走异常走异常!
3.7 系统规则
介绍
-
系统保护规则是从应用级别的入口流量进行控制,从单台机器的load、CPU使用率、平均RT、入口
QPS和并发线程数等几个维度监控应用指标,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳
定性。 -
系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流星指的是进入
应用的流量((EntryType.IN ),比如Web服务或Dubbo服务端接收的请求,都属于入口流量。 -
系统规则支持以下的模式:
- Load自适应(仅对Linux/Unixlike机器生效)∶系统的load1作为启发指标,进行自适应系统
保护。当系统load1超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触
发系统保护(BBR 阶段)。系统容量由系统的maxQps * minRt估算得出。设定参考值一般是
CPu cores* 2.5。 - CPU usage (1.5.0+版本)︰当系统CPU使用率超过阈值即触发系统保护(取值范围0.0-
1.0),比较灵敏。 - 平均RT:当单台机器上所有入口流量的平均RT达到阈值即触发系统保护,单位是毫秒。
- 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
- 入口QPS:当单台机器上所有入口流量的QPS达到阈值即触发系统保护。
- Load自适应(仅对Linux/Unixlike机器生效)∶系统的load1作为启发指标,进行自适应系统
-
配置:
testA、testB每秒QPS大于1的时候,都会直接失败,对整个系统的所有服务都是这样!
3.8 @SentinelResource
按资源名称限流+后续处理
修改8401:
-
POM:
<!-- 引入自己定义的api通用包,可以使用payment支付Entity --> <dependency> <groupId>com.atguigu.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>${project.version}</version> </dependency>
-
业务类:
@RestController public class RateLimitController { @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 服务不可用"); } }
-
配置
-
问题:关闭8401,sentinel控制台,流控规则消失了!
按url地址限流+后续处理
问题:
- 系统默认的,没有体现我们自己的业务要求。
- 依照现有条件,我们自定义的处理方法又和业务代码耦合在一块,不直观。
- 每个业务方法都添加—个兜底的,那代码膨胀加剧。
- 全局统—的处理方法没有体现。
3.8.1 自定义限流处理
-
创建CustomerBlockHandler类用于自定义限流处理逻辑
public class CustomerBlockHandler { public static CommonResult handerException(BlockException exception){ return new CommonResult(4444,"按客户自定义,global handerException ---- 1"); } public static CommonResult handerException2(BlockException exception){ return new CommonResult(4444,"按客户自定义,global handerException ---- 2"); } }
-
RateLimitController
//customerblockhandler @GetMapping("/rateLimit/customerBlockHandler") @SentinelResource(value = "customerBlockHandler", blockHandlerClass = CustomerBlockHandler.class, blockHandler = "handerException2") public CommonResult customerBlockHandler(){ return new CommonResult(200,"按客户自定义测试ok",new Payment(2020L,"serial003")); }
-
限流后测试:
3.8.2 更多注解说明:
三个核心API:
- Sphu定义资源
- Trace定义统计
- ContextUtil定义上下文
3.9 服务熔断
- 新建provider9003、9004,消费者Order84
- 实现Sentinel + ribbon + openFeign + fallback
服务熔断无配置
如果程序运行出错,直接404
只配置fallback
程序运行出错,直接调用fallback指定的方法内容返回。
只配置BlockHandler
当程序运行出错,会用BlockHnadler来兜底!
两种都配置
在没被限流降级时,调用fallback,在被限流降级之后,调用blockhandler!
exceptionToIngore
如果这样配置了,就不走fallback了!
熔断框架对比
3.10 Sentinel持久化规则
介绍
一旦我们重启应用,sentinel规则将消失,生产环境需要将配置规则进行持久化,因此将限流配置规则持久化进Nacos保存,只要刷新8401某个rest地址,sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,针对8401上sentinel上的流控规则持续有效
步骤
修改8401步骤:
-
POM
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency>
-
YML
server: port: 8401 spring: application: name: cloudalibaba-sentinel-service cloud: nacos: discovery: server-addr: localhost:8848 sentinel: transport: #配置sentinel dashboard地址 dashboard: localhost:8080 #默认8719端口,假如被占用会自动从8719端口+1,直至找到未被占用的端口 port: 8719 datasource: ds1: nacos: server-addr: localhost:8848 dataId: cloudalibaba-sentinel-service groupId: DEFAULT_GROUP data-type: json rule-type: flow management: endpoints: web: exposure: include: '*'
-
新建nacos业务规则配置:
resource:资源名称;
limitApp:来源应用;
grade:阈值类型,0表示线程数,1表示QPS;
count:单机阈值;
strategy:流控模式,0表示直接,1表示关联,2表示链路;
controlBehavior:流控效果,0表示快速失败,1表示Warm Up,2表示排队等待;
clusterMode:是否集群。 -
启动8401,发现Sentinel控制台有流控规则了!关闭8401,发现流控规则没有了,重启8401并多次刷新,流控规则又回来了!!!!!!!!!
4. Seata处理分布式事务
4.1 分布式事务问题由来
背景
单体应用被拆分成微服务应用,原来的三个模块被拆分成三个独立的应用,分别使用三个独立的数据源,业务操作需要调用三个服务来完成。此时每个服务内部的数据一致性由本地事务来保证,但是全局的数据一致性问题没法保证。
总结
一次业务操作需要跨多个数据源或需要跨多个系统进行远程调用,就会产生分布式事务问题!
4.2 Seata
简介
Seata是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务!
分布式事务模型:1个ID+三组件
-
1个ID:Transaction ID ------ XID 即全局唯一的事务ID
-
三组件概念:
- Transaction Coordinator (TC):事务协调者,维护全局和分支事务的状态,驱动全局事务提交或回滚。
- Transaction Manager ™:事务管理器,定义全局事务的范围:开始全局事务、提交或回滚全局事务。
- Resource Manager(RM):资源管理器,管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
-
处理过程:
- TM向TC申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的XID;
- XID在微服务调用链路的上下文中传播;
- RM向TC注册分支事务,将其纳入XID对应全局事务的管辖;
- TM向TC发起针对XID的全局提交或回滚决议;
- TC调度XID下管辖的全部分支事务完成提交或回滚请求。
4.3 Seata Serve安装
-
下载地址:https://github.com/seata/seata/releases/download/v1.0.0/seata-server-1.0.0.zip
-
安装:
-
解压并修改conf目录下的file.conf配置文件!主要修改:自定义事务组名称+事务日志存储模式为db+数据库连接信息
-
service模块
-
store模块
-
-
-
mysql5.7新建数据库seata
-
seata里面新建表:建表的db_store.sql在**\seata-server-0.9.0\seata\conf**目录里面
drop table if exists `global_table`; create table `global_table` ( `xid` varchar(128) not null, `transaction_id` bigint, `status` tinyint not null, `application_id` varchar(32), `transaction_service_group` varchar(32), `transaction_name` varchar(128), `timeout` int, `begin_time` bigint, `application_data` varchar(2000), `gmt_create` datetime, `gmt_modified` datetime, primary key (`xid`), key `idx_gmt_modified_status` (`gmt_modified`, `status`), key `idx_transaction_id` (`transaction_id`) ); drop table if exists `branch_table`; create table `branch_table` ( `branch_id` bigint not null, `xid` varchar(128) not null, `transaction_id` bigint , `resource_group_id` varchar(32), `resource_id` varchar(256) , `lock_key` varchar(128) , `branch_type` varchar(8) , `status` tinyint, `client_id` varchar(64), `application_data` varchar(2000), `gmt_create` datetime, `gmt_modified` datetime, primary key (`branch_id`), key `idx_xid` (`xid`) ); drop table if exists `lock_table`; create table `lock_table` ( `row_key` varchar(128) not null, `xid` varchar(96), `transaction_id` long , `branch_id` long, `resource_id` varchar(256) , `table_name` varchar(32) , `pk` varchar(36) , `gmt_create` datetime , `gmt_modified` datetime, primary key(`row_key`) );
-
修改seata-server-0.9.0\seata\conf目录下的registry.conf配置文件:指明注册中心为nacos及修改连接信息
-
测试:先启动nacos,再启动seata server.bat,成功!
-
怎么玩?
本地@Transactional
全局@GlobalTransactional
Seata的分布式交易解决方案:
4.4 Seata原理
AT模式如何做到对业务的无侵入
-
一阶段加载:在一阶段,Seata会拦截“业务SQL",
解析SQL语义,找到“业务SQL"要更新的业务数据,在业务数据被更新前,将其保存成"before image” ,执行“业务SQL"更新业务数据,在业务数据更新之后,其保存成“after image" ,最后生成行锁。
以上操作全部在一个数据库事务内完成,这样保证了一阶段操作的原子性。 -
二阶段回滚:即Seata就需要回滚一阶段已经执行的“业务SQL",还原业务数据。回滚方式便是用"before image"还原业务数据;但在还原前要首先要校验脏写,对比”数据库当前业务数据”和"after image",如果两份数据完全一致就说明没有脏写, 可以还原业务数据,如果不一致就说明有脏写,出现脏写就需要转人工处理。
二阶段提交:因为“业务SQL"在一阶段已经提交至数据库,所以Seata框架只需将一阶段保存的快照数据和行锁删掉,完成数据清理即可。
转载:https://blog.csdn.net/lyyrhf/article/details/116333876