SpringCloud Alibaba
SpringCloud Alibaba 入门简介
为什么会出现SpringCloud Alibaba
- Spring Cloud Netflix项目进入维护模式
- SpringCloud NetFlix Projects Entering Maintenance Mode
- 什么是维护模式
SpringCloud Alibaba带来了什么
- 是什么
- 能干嘛
- 服务限流降级:默认支持 WebServlet、WebFlux, OpenFeign、RestTemplate、Spring Cloud Gateway, Zuul, Dubbo 和 RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控
- 服务注册与发现:适配Spring Cloud服务注册与发现标准,默认集成了Ribbon的支持
- 分布式配置管理:支持分布式系统中的外部化配置,配置更改时自动刷新
- 消息驱动能力:基于Spring Cloud Stream为微服务应用构建消息驱动能力
- 分布式事务:使用 @GlobalTransactional 注解, 高效并且对业务零侵入地解决分布式事务问题
- 阿里云对象存储:阿里云提供的海量、安全、低成本、高可靠的云存储对象。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据
- 分布式任务调度:提供秒级、精准、高可靠、高可用的定时(基于Cron表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有Worker(schedulerx-client)上执行
- 阿里云短信服务:覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道
- 组件
- Sentinel:把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性
- Nacos:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台
- RocketMQ:一款开源的分布式消息系统,基于高可用分布式集群技术、提供低延时的、高可靠的消息发布与订阅服务
- Dubbo:Apache Dubbo是一款高性能的Java RPC框架
- Seata:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案
- Alibaba Cloud ACM:一款在分布式架构环境中对应用配置进行集中管理和推送的应用配置中心产品
- Alibaba Cloud OSS:阿里云对象存储服务(Object Storage Service,简称OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据
- Alibaba Cloud ScheduleX:阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于Cron表达式)任务调度服务
- Alibaba Cloud SMS:覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道
SpringCloud alibaba学习资料获取
Spring Cloud Alibaba Nacos服务注册和配置中心
Nacos简介
-
为什么叫Nacos
- 前四个字母分别是Naming和Configuration的前两个字母,最后的s为Service
-
是什么
-
一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台
-
Nacos:Dynamic Naming and Configuration Service
-
Nacos就是注册中心+配置中心的组合--->Nacos=Eureka + Config + Bus
-
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。
-
-
能干嘛
- 替代Eureka做服务注册中心
- 替代Config做服务配置中心
-
去哪下
-
各种注册中心比较
安装并运行Nacos(官网下载)
Nacos作为服务注册中心演示
-
cloudalibaba-provider-payment9001,cloudalibaba-provider-payment9002
-
-
cloudalibaba-consumer-nacos-order83
-
-
注册进了Nacos
-
为什么nacos支持负载均衡:依赖中整合了ribbon
- 83访问9001/9002,轮询负载OK
各种注册中心比较
-
Nacos支持CAP中 AP和CP模式的切换
-
Nacos全景图所示
-
Nacos和CAP
-
Nacos支持AP和CP模式的切换
Nacos作为服务配置中心演示
-
Nacos作为配置中心-基础配置
- cloudalibaba-config-nacos-client3377
- why配置两个
- application.yml
- bootstrap
- 在Nacos中添加配置信息
- 理论:Nacos中的dataid的组成格式与SpringBoot配置文件中的匹配规则
- 实操
- 配置新增
- Nacos界面配置对应
- 理论:Nacos中的dataid的组成格式与SpringBoot配置文件中的匹配规则
- 自带动态刷新:修改下Nacos中的yaml配置文件,再次调用查看配置的接口,就会发现配置已经刷新
-
Nacos作为配置中心-分类配置
-
问题:多环境多项目管理
-
Nacos的图形化管理界面
-
配置管理
-
命名空间
-
-
Namespace+Group+Data ID三者关系?为什么这么设计
-
Case
-
DataID方案
- 指定spring.profile.active和配置文件的DataID来使不同环境下读取不同的配置
- 默认空间+默认分组+新建dev和test两个DataID
- 新建dev配置DataID
- 新建test配置DataID
- 通过spring.profile.active属性就能进行多环境下配置文件的读取
-
Group方案
-
-
在config下增加一条group的配置即可。可配置为DEV_GROUP或TEST_GROUP
-
-
Namespace方案
- 新建dev/test的Namespace
- 回到服务管理-服务列表查看
- 按照域名配置填写
-
-
Nacos集群和持久化配置(**)
官方说明
-
官网架构图
-
官网架构翻译,真是情况
- 说明
- 需配置mysql数据,nacos.io/zh-cn/docs/…
- 说明
Nacos持久化配置解释
-
Nacos默认自带的是嵌入式数据库derby,github.com/alibaba/nac…
-
derby到MySQL切换配置步骤
-
nacos-server-1.1.4\nacos\conf目录下找到sql脚本,执行脚本nacos-mysql.sql
-
nacos-server-1.1.4\nacos\conf目录下找到application.properties
# db mysql spring.datasource.platform=mysql db.num=1 db.url.0=jdbc:mysql://127.0.0.1:3306/nacosconfig?serverTimezone=UTC&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true db.user=root db.password=123456 -
启动nacos,可以看到是个全新的空记录界面,以前是记录进derby
-
Linux版Nacos+MySQL生产环境配置
-
预计1个nginx+3个nacos注册中心+1个mysql
-
搭建步骤参考:www.jianshu.com/p/ad12f28c4…
-
集群配置步骤(**)
-
测试
- 微服务cloudalibaba-provider-payment9002启动注册进nacos集群
-
高可用小总结
SpringCloud Alibaba Sentinel实现熔断与限流
Sentinel简介
-
是什么
- Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性
- 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等
- 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况
- 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel
- 完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等
- Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性
-
能干嘛
-
怎么玩
- 服务使用中的各种问题
- 服务雪崩
- 服务降级
- 服务熔断
- 服务限流
- 服务使用中的各种问题
安装Sentinel控制台
- Sentinel组件由两部分构成
- 安装步骤
- 官网下载,sentinel-dashboard-x.x.jar
- 运行命令: java -jar sentinel-dashboard-x.x.jar
- 访问sentinel管理界面
- http://localhost:8080
- 登录账号密码均为sentinel
初始化演示工程
- cloudalibaba-sentinel-service8401
- 启动Nacos8848成功
- 启动Sentinel8080
- 启动8401微服务后查看sentienl控制台
- 第一次访问,空白页
- Sentinel采用的懒加载说明,执行一次访问即可
- 效果图:
流控规则
-
基本介绍
-
-
进一步介绍
-
-
-
流控模式
-
直接(默认)
-
系统默认,直接->快速失败
-
配置及说明
-
测试
- 快速点击访问http://localhost:8401/testA
- 结果;Blocked by Sentinel (flow limiting)
- 思考:是否应该加一个类似fallback的兜底方法?
-
-
关联
-
是什么
- 当关联的资源达到阈值时,就限流自己
- 当与A关联的资源B达到阈值后,就限流自己
- B惹事,A挂了
- 应用场景: 比如支付接口达到阈值,就要限流下订单的接口,防止一直有订单
-
postman模拟并发密集访问testB
-
配置规则
-
postman里新建多线程集合组
-
将访问地址添加进新线程组 -- save as 选择对应的collection
-
-
大批量线程高并发访问B,导致A失效了
-
-
-
链路
- 链路流控模式指的是,当从某个接口过来的资源达到限流条件时,开启限流;它的功能有点类似于针对 来源配置项,区别在于:针对来源是针对上级微服务,而链路流控是针对上级接口,也就是说它的粒度 更细
-
-
流控效果
-
直接--->快速失败(默认的流控处理),直接失败,抛出异常
-
预热
-
说明:公式:阈值除以coldFactor(默认值为3),经过预热时长后才会达到阈值
-
官网:
-
默认coldFactor为3,即请求QPS从threshold(阈值)/3开始,经预热时长逐渐升至设定的QPS阈值。
-
限流冷启动:github.com/alibaba/Sen…
-
源码
-
配置
-
测试:多次点击http://localhost:8401/testB 结果:刚开始不行,后续慢慢OK
-
应用场景
-
-
排队等待
-
匀速排队,阈值必须设置为QPS
-
官网
-
-
降级规则
-
基本介绍
-
-
进一步说明
-
Sentinel的断路器是没有半开状态的
- 半开的状态系统自动去检测是否请求有异常,没有异常就关闭断路器恢复使用,有异常则继续打开断路器不可用。具体可以参考Hystrix
- hystrix
-
-
降级策略实战
-
RT:平均响应时间
- 是什么
- jmeter压测--->1秒钟打入10个请求
- 结论
- 是什么
-
异常比例
-
是什么
-
配置
-
jmeter压测,结论
-
-
异常数
-
是什么
-
异常数是按照分钟统计的
-
配置+测试
-
-
热点key限流(**)
-
基本介绍
-
-
承上启下复习start
-
@SentinelResource等同于@HystrixCommand
-
源码:
com.alibaba.csp.sentinel.slots.block.BlockException -
配置
- @SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")
- 不添加blockHandler方法,会把异常打到前台页面,提示不友好
- 方法testHostKey里面第一个参数只要QPS超过每秒1次,马上降级处理,并且用了我们自己定义的降级提示
-
参数例外项
-
上述案例演示了第一个参数p1,当QPS超过1秒1次点击后马上被限流
-
特殊情况:
-
普通:超过1秒钟一个后,达到阈值1后马上被限流
-
特例:我们期望p1参数当它是某个特殊值时,它的限流值和平时不一样.
例如当p1的值等于5时,它的阈值可以达到200
-
-
配置
-
-
测试结果:
- 当p1等于5的时候,阈值变为200
- 当p1不等于5的时候,阈值就是平常的1
-
前提:热点参数的注意点,参数必须是基本类型或者String
-
其他:存在异常
系统规则
- 是什么:github.com/alibaba/Sen…
- 各项配置参数说明
- 配置全局QPS
@SentinelResource
-
按资源名称限流+后续处理
-
启动Nacos成功
-
启动Sentinel成功
-
修改cloudalibaba-sentinel-service8401
-
业务类RateLimitController
-
配置
表示1秒钟内查询次数大于1,就跑到我们自定义的处流,限流
-
测试结果:1秒钟点击1下,OK
超过上述问题,疯狂点击,返回了自己定义的限流处理信息,限流发送--->进入blockHandler配置的方法
-
额外问题:此时关闭微服务8401看看,Sentinel控制台,流控规则消失了,临时/持久?
-
-
按照URL地址限流+后续处理
- 通过访问的URL来限流,会返回Sentinel自带默认的限流处理信息
- 业务类RateLimitController
- 配置
- 测试结果
-
上面兜底方案面临的问题
-
客户自定义限流处理逻辑
- 创建customerBlockHandler类用于自定义限流处理逻辑
- 自定义限流处理类
- 业务类指定处理方法
- 测试结果:业务与异常处理结构,
blockHandlerClass指定异常处理类和blockHandler指定该类中具体处理方法
-
更多注解属性说明
-
-
注意
-
Sentinel主要有三个核心API
- SphU定义资源
- Tracer定义统计
- ContextUtil定义了上下文
-
服务熔断功能
sentinel整合ribbon+openFeign+fallback(**)
Ribbon系列
-
启动nacos和sentinel
-
提供者9003/9004
-
消费者84
-
-
只配置fallback,处理运行时异常
-
只配置blockHandler,blockHandler只负责sentinel控制台配置违规
-
fallback和blockHandler都配置
-
忽略属性 exceptionToIgnore
Feign系列
* 修改84模块,Fegin组件一般是在消费侧
* yml 添加 feign配置
* 主启动添加@EnableFeignClients启动Feign的功能
* 业务类
* 测试84调用9003/9004,此时故意关闭9003和9004微服务提供者,**84消费自动降级**,不会被耗死
熔断框架比较
规则持久化
-
是什么:一旦我们重启应用,Sentinel规则将消失,生产环境需要将配置规则进行持久化
-
怎么玩:将限流配置规则持久化进Nacos保存,只要刷新8401某个rest地址,sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,针对8401上Sentinel上的流控规则持续有效
-
步骤
-
修改cloudalibaba-sentinel-service8401
-
yml :添加数据源配置
cloud: nacos: discovery: #Nacos服务注册中心地址 server-addr: localhost:8848 sentinel: transport: #配置Sentinel dashboard地址 dashboard: localhost:8080 port: 8719 #默认8719,假如被占用了会自动从8719开始依次+1扫描。直至找到未被占用的端口 datasource: ds1: nacos: server-addr: localhost:8848 dataId: cloudalibaba-sentinel-service groupId: DEFAULT_GROUP data-type: json rule-type: flow -
添加Nacos业务规则配置
[ { "resource": "/rateLimit/byUrl", "limitApp": "default", "grade": 1, "count": 1, "strategy": 0, "controlBehavior": 0, "clusterMode": false } ] -
启动8401后刷新sentinel发现业务规则有了
-
重新启动8401再看sentinel,多次调用,流控配置重新出现了,持久化验证通过
-
SpringCloud Alibaba Seata处理分布式事务
分布式事务问题
-
分布式前
- 单机单库没这个问题
- 从
1:1 -> 1:N -> N: N
-
分布式之后
-
一句话:一次业务操作需要跨多个数据源或需要跨多个系统进行远程调用,就会产生分布式事务问题
Seata简介
-
是什么
- Seata是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务
- 官网:seata.io/zh-cn/
-
能干嘛
-
一个典型的分布式事务过程:
-
分布式事务处理过程一个ID+三组件模型
- Transaction ID XID 全局唯一的事务ID
- 三组件:
- Transaction Coordinator(TC):事务协调器,维护全局事务的运行状态,负责协调并驱动全局事务的提交或回滚;
- Transaction Manager(TM) :控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议;
- Resource Manager(RM) :控制分支事务,负责分支注册,状态汇报,并接收事务协调器的指令,驱动分支(本地)事务的提交和回滚;
-
处理过程
-
-
-
去哪下:发布说明:github.com/seata/seata…
-
怎么玩
- Spring 本地@Transactional
- 全局@GlobalTransactional
Seata-Server安装
- 官网下载稳定版本:github.com/seata/seata…
- 解压到指定目录并修改conf目录下的file.conf配置文件
- 先备份原始file.conf文件
- 主要修改:自定义事务组名称+事务日志存储模式为db+数据库连接信息
- file.conf,主要修改service模块和store模块两个模块
- 在seata库里建表
- 修改\conf目录下的registry.conf配置文件,将seata注册进nacos
- 先启动Nacos端口号8848
- 再启动seata-server
订单/库存/账户业务数据库准备
-
以下演示都需要先启动Nacos后启动Seata,保证两个都OK
-
分布式事务业务说明:三个服务 订单服务、库存服务、账户服务。当用户下单时,会在订单服务中创建一个订单,然后通过远程调用库存服务来扣减下单商品的库存,再通过远程调用账户服务来扣减用户账户里面的余额,最后在订单服务中修改订单状态为已完成
该操作跨越三个数据库,有两次远程调用,很明显会有分布式事务问题
下订单-->扣库存-->减账户(余额)
-
创建业务数据库
-- seata_order: 存储订单的数据库 CREATE DATABASE seata_order; -- seata_storage:存储库存的数据库 CREATE DATABASE seata_storage; -- sseata_account: 存储账户信息的数据库 CREATE DATABASE seata_account; -
按照上述3库分别建对应业务表
-
seata_order库下建t_order表
CREATE TABLE t_order( `id` BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, `user_id` BIGINT(11) DEFAULT NULL COMMENT '用户id', `product_id` BIGINT(11) DEFAULT NULL COMMENT '产品id', `count` INT(11) DEFAULT NULL COMMENT '数量', `money` DECIMAL(11,0) DEFAULT NULL COMMENT '金额', `status` INT(1) DEFAULT NULL COMMENT '订单状态:0:创建中; 1:已完结' ) ENGINE=INNODB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8; SELECT * FROM t_order; -
seata_storage库下建t_storage表
CREATE TABLE t_storage( `id` BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, `product_id` BIGINT(11) DEFAULT NULL COMMENT '产品id', `'total` INT(11) DEFAULT NULL COMMENT '总库存', `used` INT(11) DEFAULT NULL COMMENT '已用库存', `residue` INT(11) DEFAULT NULL COMMENT '剩余库存' ) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; INSERT INTO seata_storage.t_storage(`id`,`product_id`,`total`,`used`,`residue`) VALUES('1','1','100','0','100'); SELECT * FROM t_storage; -
seata_account库下建t_account表
CREATE TABLE t_account( `id` BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'id', `user_id` BIGINT(11) DEFAULT NULL COMMENT '用户id', `total` DECIMAL(10,0) DEFAULT NULL COMMENT '总额度', `used` DECIMAL(10,0) DEFAULT NULL COMMENT '已用余额', `residue` DECIMAL(10,0) DEFAULT '0' COMMENT '剩余可用额度' ) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; INSERT INTO seata_account.t_account(`id`,`user_id`,`total`,`used`,`residue`) VALUES('1','1','1000','0','1000') SELECT * FROM t_account; -
按照上述3库分别建对应的回滚日志表
-
订单-库存-账户3个库下都需要建各自的回滚日志表
-
drop table `undo_log`; 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; -
-
-
订单/库存/账户业务微服务准备
- 业务需求:下订单->减库存->扣余额->改(订单)状态
- 新建订单Order-Module:
cloudalibaba-seata-order-service2001 - 新建库存Storage-Module:
cloudalibaba-seata-storage-service2002 - 新建账户Account-Module:
cloudalibaba-seata-account-service2003 - 本地用的Seata1.2与视频中0.9配置差异较大。建议参考:blog.csdn.net/sinat_38670…
- 数据库文件及配置文件资源地址:github.com/seata/seata…
Test
- 下订单->减库存->扣余额->改(订单)状态
- 数据库初始情况
- 正常下单
- 超时异常,没加@GlobalTransactional
- AccountServiceImpl添加超时
- 故障情况:当库存和账户余额扣减后,订单状态并没有设置为已经完成,没有从零改为1。而且由于feign的重试机制,账户余额还有可能被多次扣减
- 超时异常,添加@GlobalTransactional
- AccountServiceImpl添加超时
- OrderServiceImpl@GlobalTransactional
- 下单后数据库数据并没有任何改变,记录都添加不进来
Seata原理
-
再看TC/TM/RM三大组件
- 分布式事务执行流程(**)
- TM开启分布式事务(TM向TC注册全局事务记录)
- 换业务场景,编排数据库,服务等事务内资源(RM向TC汇报资源准备状态)
- TM结束分布式事务,事务一阶段结束(TM通知TC提交/回滚分布式事务)
- TC汇总事务信息,决定分布式事务是提交还是回滚
- TC通知所有RM提交/回滚资源,事务二阶段结束。
- 分布式事务执行流程(**)
-
AT模式如何做到对业务的无侵入
-
是什么
-
一阶段加载
-
二阶段提交
-
二阶段回滚
-
-
debug:观察数据库回滚细节
-
总结