Nacos
Nacos 作为服务注册中心
github下载Nacos并运行,Nacos默认以集群模式启动,需要手动指定单机版
./startup.cmd -m standalone
访问
localhost:8848/nacos
访问控制台页面,默认的用户名和密码都是nacos
需要注册的服务引入依赖(服务提供者和服务消费者)
1
2
3
4<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>配置文件
1
2
3
4
5spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848Nacos集成了Ribben,直接使用RestTemplate进行访问url即可具有负载均衡功能
nacos控制台展示所有注册的服务即表示成功
Nacos作为服务注册的中心可以满足AP和CP模型,可以进行切换,只需要发送特定的post请求进行修改
ip:port/nacos/v1/ns/operator/switches?entry=serverMode&value=CP
Nacos 作为服务配置中心
基础配置
依赖
1
2
3
4<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>配置文件bootstrap.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21server:
port: 3377
spring:
profiles:
active: dev
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
config:
server-addr: localhost:8848 #Nacos作为配置中心地址
file-extension: yml #指定yaml格式的配置
group: DEV_GROUP #组名称,默认为DEFAULT_GROUP
namespace: 7a901d46-e75e-4e6a-b186-5980cca4249b #命名空间namespace,默认会走public组
# 配置中心对应配置文件的dataId格式:
# ${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
# 这里对应的dataId为:nacos-config-client-dev.yml在Nacos配置中心添加配置文件
点击发布后,nacos会自动通知每个注册配置中心的微服务更新配置,不需要再手动发送请求更新
需要更新代码中的属性则需要标注
@RefreshScope
在对应类上
分类配置
情景:分布式系统的多环境、多项目配置管理
Nacos使用的是三层定位配置文件的规则,以便更方便的管理不同环境和不同项目
Nacos配置文件的定位顺序
NameSpace:新建namespace如图所示
如果不指定id的话会自动生成id,如
acdd62bc-3159-452e-aab1-24c4657e8fde
GroupId
DataId
1 | spring: |
Sentinel
Sentinel流量控制
github下载sentinel的jar包,直接以springboot方式运行即可,默认的前端监控页面端口为8080
阈值类型:
按QPS:限制每秒请求数
按线程数:限制正在执行的线程数
流控模式:
直接:API达到限流条件时,直接限流
关联:当关联的资源达到阈值时,就限流自己
链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流)(API级别的针对来源)
流控效果:
快速失败:直接失败,抛异常
warmUp:根据coldFactor(冷加载因子,默认3)的值,从阈值/codeFacotor,经过预热时长,才达到设置的QPS阈值
排队等待:匀速排队,让请求以匀速的速度通过,阈值类型必须设置为QPS,否则无效
Sentinel默认的拦截消息都是Blocked by Sentinel (flow limiting)
Sentinel熔断降级
降级策略:
RT:平均响应时间,以ms为单位,当单位统计时长内请求书目大于设置的最小请求数(默认5个/s)并且RT大于所设阈值就会熔断
RT在高版本为慢调用比例,在RT的基础上根据设置的慢调用阈值计算出慢调用的比例,根据比例设置的阈值计算熔断
异常比例:异常的比例大于阈值会自动进行熔断,同时应该满足最小请求数的限制
异常数:当单位统计时长(默认1min)内的异常数目超过阈值之后
热点key
仅支持QPS模式,根据指定的参数索引(对应的是参数在方法名上指定的位置)来进行拦截
- 参数例外项:可以对这个参数的某一个参数值单独进行限流配置,比如一些热点话题已经预热完毕时可以将限流阈值设置高一些
系统规则
系统规则相当于整个系统外部的把关门禁,当拦截生效时整个服务都将不能正确响应
@SentinelResource
注解的使用
@SentinelResource不支持private方法
这里类似于Hystrix中的HystrixCommand
注解,可以指定对应的限流处理方法注意与FallBack区分,指定的对应方法只能处理限流的响应,业务代码抛出的RuntimeException则不能处理
blockHandler参数指定处理对应的限流、熔断等配置的响应的方法(只处理BlockException)
FallBack参数指定处理业务类异常的方法(RuntimeException)
注意:要使@SentinelResource注解生效,在Sentinel控制台指定限流策略时资源名必须设置成@SentinelResource设定的value值,设置资源名为url路径则只会响应默认的
Blocked by Sentinel (flow limiting)
单独业务方法
1
2
3
4
5
6
7
8
9
10
11
//指定对应的限流处理方法
public String testHotKey( String p1,
String p2){
return "testHotKey-------";
}
//这里处理限流方法的参数必须在原方法的基础上添加一个BlockException参数
public String deal_testHotKet(String p1, String p2, BlockException e) {
return "----限流响应----";
}分离业务类处理
限流处理类
1
2
3
4
5
6
7
8
9
10
11
12//不需要注入
public class Customerhandler {
//限流处理
public CommonResult handlerException(BlockException exception) {
return new CommonResult(444,"处理限流策略,global handlerException",new Payment(2020L,"serial003"));
}
//业务类异常处理
public CommonResult handleFallback(Throwable e) {
return new CommonResult(444,"处理业务异常,global handleFallback",new Payment(2020L,"serial003"));
}
}业务类
1
2
3
4
5
6
7
8
//指定业务异常处理方法名
public String testA(){
return "testA-------";
}
Sentinel持久化
默认情况下,当注册到Sentinel的服务关闭/重启后sentinel的持久化规则会自动清除
可以使用Nacos等配置中心方式来持久化配置,但是笔者感觉这种方式还是不太合理,需要自己手动编写json来保存到nacos,通过sentinel的控制页面设定的配置还是不能保存,等待后续版本优化吧。。。
Seata
TC (Transaction Coordinator) - 事务协调者,一般是seata服务器
维护全局和分支事务的状态,驱动全局事务提交或回滚。
TM (Transaction Manager) - 事务管理器,一般是上游标注
@GlobalTransactional
的服务定义全局事务的范围:开始全局事务、提交或回滚全局事务。
RM (Resource Manager) - 资源管理器,所有管理具体sql的事务机制
管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
Seata安装部署
SeataServer
修改配置文件file.conf,将存储方式改为db
建库建表,建表sql在对应的readme文件里面有提示,执行即可
修改registry.conf,配置nacos为注册中心
![VJLU0
A
4SJA5VT2O3XC$N.png每一个需要用到分布式事务的客户端数据库都需要单独建表(尽量从官网上取最新的sql)
1
2
3
4
5
6
7
8
9
10
11
12
13CREATE TABLE IF NOT EXISTS `undo_log`
(
`branch_id` BIGINT NOT NULL COMMENT 'branch transaction id',
`xid` VARCHAR(128) NOT NULL COMMENT 'global transaction id',
`context` VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',
`rollback_info` LONGBLOB NOT NULL COMMENT 'rollback info',
`log_status` INT(11) NOT NULL COMMENT '0:normal status,1:defense status',
`log_created` DATETIME(6) NOT NULL COMMENT 'create datetime',
`log_modified` DATETIME(6) NOT NULL COMMENT 'modify datetime',
UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDB
AUTO_INCREMENT = 1
DEFAULT CHARSET = utf8 COMMENT ='AT transaction mode undo table';
SeataClient
<dependency> <groupId>io.seata</groupId> <artifactId>seata-spring-boot-starter</artifactId> <version>1.4.2</version> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>endency>
1
2
3
4
5
6
7
+ 推荐使用Nacos配置SeataClient,具体配置方式请依照官方文档[Seata 快速开始](https://seata.io/zh-cn/docs/user/quickstart.html)
+ 需要开启分布式事务的方法(一般是上游调用下游服务的业务方法)添加注解即可生效
```java
@GlobalTransactional(name = "transactionNameA", rollbackFor = Exception.class)
回滚原理
一二阶段提交事务
一阶段:TM标志
@GlobalTransactional
开启分布式事务,各个RM执行sql逻辑,并向TC提交执行结果![9`8%F0C{XWQ(
9(OCPLG6.png](https://cdn.jsdelivr.net/gh/lan5th/pics/blog_images/20220722212759.png)RM事务执行逻辑
执行之前,生成beforeImage,作为修改前数据的快照
执行sql逻辑
执行之后,生成afterImage,作为修改后数据的快照
生成行锁
二阶段:TC根据汇总到的RM执行结果执行提交逻辑
全部执行成功:通知所有RM删除beforeImage和afterImage,提交事务
有事务执行失败:通知所有RM执行补偿还原机制,根据beforeImage和AfterImage来还原数据
如果afterImage和当前数据没有差异,则直接还原
如果修改和还原之间数据已经由其他sql进行了改变,则无法正常还原,等待运维人员操作。
不论是否执行成功,最终都会删除afterImage、beforeImage和行锁