教学视频地址:
B站图灵springcloud教学视频(主要的)
b站山硅谷springcloud教学视频
学习代码:
springcloud学习代码资源
其他框架资源
脚手架项目git地址
文章目录
一、为服务架构理论知识
略
二、springcloud简介
- boot与cloud版本对应关系
spring官网cloud与boot的版本对应关系
- 组件
三、springcloud技术栈
1、项目搭建
- 创建springboot工程
pom文件加上
<packaging>pom</packaging>
- 根据版本对应关系加入springcloud-alibaba、springcloud等依赖
版本对应
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.7.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- 子工程项目搭建
创建maven工程(会自动继承父项目)
2、注册中心:Nacos
1、项目部署
- 下载项目(github中)
根据版本对应关系下载对应的版本即可(文件保存位置不可有中文符号)
- 启动项目
因为默认是集群模式,所以需要先修改为单机模式
对启动文件右键编辑,更改模式即可
也可以进行一些其他配置
用户名密码默认都是nacos
2、nacosClient搭建
- 在需要用到nacos的子项目中加入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
- 配置
- 使用resttemplet调用即可
3、nacos基本概念
- 保护阈值:健康实例占比小于保护阈值的时候将会调用非健康实例,以免雪崩
4、集群
- 环境搭建(推荐使用nginx进行负载均衡)
修改properties,配置mysql,运行官方给的sql文件
修改(新建)cluster.config,加入集群的ip和端口
- 理论知识
两种集群方式
负载均衡策略(loadblance实现负载均衡的方式略过)
- 使用
消费方的resttemplet加上注解
修改负载均衡策略
1、方法一:使用配置类
2、使用配置文件
3、服务调用:openfeign
用于代替之前resttemplet的调用方式
1、添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、声明接口
3、启用注解
4、使用
配置项
- 日志配置-配置类
springboot默认的日志级别是info,feign的debug级别的日志就不会输出,所以将feign接口的日志级别改为debug带能看得到feign的日志输出
logging:
level:
com.example.demo.feign: debug
- 日志配置-配置文件
- 契约配置
将feign的原生注解和mvc的注解对应,通常用于版本升级而而做出的代码规范
- 超时时间
- feign自定义拦截器
配置方法一:
方法二:
实现类:
4、配置中心:nacos
-
新建配置文件
DataId公式= ${spring.cloud.config.prefix}-${spring.profiles.active}.${spring.cloud.config.file-extension}
spring.cloud.config.prefix:配置文件前缀
spring.profiles.active:服务环境标识,dev、test、prod
spring.cloud.config.file-extension:配置文件后缀,如yaml、properties等格式
*只有配置的与dataid对应的上才能获取得到nacos上的配置文件 -
导入依赖,写配置文件
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
推荐使用bootstrap.yml全局配置文件
-
在controller上添加,动态刷新注解:@RefreshScope
-
其他配置
通过dataid指定特定的配置文件(一般用于共享配置文件,shared-configs是自己取的名字可以有多个)
-
权限管理
可新建角色,设置权限(会影响配置中心,待解决)
需要修改nacos中conf/application.properties配置文件:
改为true,默认false
5、流控:sentinel
流控是部署在服务提供者上面的
sentinel github官网
有两种使用方式:使用API,使用控制台
略过p43,p44,p45
1、整合springcloudalibaba的控制台
1、从sentinel github官网下载jar包
2、通过java -Dserver.port=8891 -Dsentinel.dashboard.auth.username=admin -Dsentinel.dashboard.auth.password=123 -jar sentinel-dashboard-1.8.1.jar命令运行jar包,账号密码默认都是sentinel,也可以指定端口账户密码
3、添加依赖、配置sentinel控制台地址
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
访问接口之后就可以在sentinel上面显示出来了
2、流控规则
- 流控处理:
使用@SentinelResource(需要依赖,整合在cloud中了,对普通方法也可以流控,不单单是controller):
1、注入bean:
2、在需要流控的接口加上注释(不成功可以尝试重启sentinel或项目本体)
- 流控方式:QPS,线程数
- 全局流控处理
想要让全局异常处理就不能加上这个SentinelResource注解
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
//判断错误类型
if (e instanceof FlowException) {
} else if (e instanceof DegradeException) {
} else if (e instanceof ParamFlowException) {
} else if (e instanceof SystemBlockException) {
} else if (e instanceof AuthorityException) {
}
//返回数据
httpServletResponse.setStatus(500);
httpServletResponse.setCharacterEncoding("utf-8");
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
new ObjectMapper().writeValue(httpServletResponse.getWriter(),"全局处理---出现错误");
}
}
- 流控模式
1、直接模式:访问自己限流自己
2、关联模式:访问关联资源限流自己
3、链路模式:和直接模式一样,但是根据不同的入口资源进行流控(链路的入口资源好像只能限制在同一个项目内,并不可以跨项目)
- 流控效果
1、快速失败:直接丢弃多余请求,直接报错
2、warm up:针对激增流量,会慢慢将求请求放进来,让系统的缓冲层进行预热,直至达到流控阈值,通过预热时长设置请求放进来的速度
3、排队等待:针对脉冲流量,通过设置等待时间让超过阈值的的请求在空闲时间执行,充分利用空闲时间
3、熔断降级
- 慢调用比例:
- 异常比例
- 异常数量
- 整合opoenfeign的熔断(错误处理,提供者出错)
以下配置都是在消费端的
1、添加配置
2、实现服务端接口,加上@Component
3、在服务接口注解中添加fallback类,即实现类
服务端出错后调用的就是消费端实现的方法了
4、热点流控
5、系统规则
针对当前系统的指标进行处理,用于造成压力的原因来自哪里的时候,可以作为一个兜底的方案
6、持久化
1、原始模式:啥也没有
2、拉模式:结合远吗进行扩展
3、推模式:将配置推送到远程配置中心
- 导入依赖
- 在nacos中编写对应配置文件(默认是json格式,各个不同属性可以在文档找到,流控,熔断,热点)
官网配置属性参考
- 编写配置文件
更多属性可以参考(还有他的父类中的属性):
7、sentinel的集群
待定
整合gateway,学完gateway再回来看p60
6、分布式事务组件:seata
seata官网
根据版本对照下载github的zip包:下载地址
1、服务端搭建
- 搭建数据库(新版已经改为yml来配置,参照着文件里的模板来就可以)
1、修改conf中的file.conf
坑:mysql8.0以上还要修改
1、驱动名:com.mysql.cj.jdbc.Driver
2、在数据库连接后面加上:?characterEncoding=utf-8&serverTimezone=UTC
2、创建数据库,运行sql语句(新版在下载的文件中的script-server-db中有) - 整合nacos
1、修改conf中的registry.conf:对应注册中心和配置中心
2、去gihub官网下载项目,在script中找到script\config-center\config.txt
修改(新版的在script中就有config-center)
坑:mysql8.0以上还要修改
1、驱动名:com.mysql.cj.jdbc.Driver
2、在数据库连接后面加上:?characterEncoding=utf-8&serverTimezone=UTC
项目地址
默认分组名也可以
3、运行script\config-center\nacos\nacos-config.sh(将config.txt同步到nacos)
也可以指定参数:
2、客户端搭建
- 1、在有关事务的项目中添加依赖
- 2、在有关事务的项目数据库中新建undolog表
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,
PRIMARY KEY (id),
UNIQUE KEY ux_undo_log (xid,branch_id)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
- 3、配置事务分组、注册中心和配置中心
- 4、在需要分布式事务的方法上面加上@GlobalTransactional就可以了
3、各个模式的原理
不同的模式使用:seata不同模式的原理及实现
saga模式的使用(大概是实现StateMachineEngine状态机中的方法来使用的吧)
- XA
1、过程:两阶段提交(各个服务提交,全局提交)
2、使用前提:需要数据库支持XA协议,即数据库自己就要拥有事务的开始、执行、提交或回滚的能力
3、大致原理:一阶段时调用各个服务自己的事务,全部成功时再全局提交
4、优缺点:一阶段时各个服务全程开启事务,性能低下,但拥有XA协议的强一致性 - AT
1、过程:两阶段提交
2、使用前提:需要支持ACID的关系型数据库,不需要支持XA协议
3、大致原理:需要在各个需要用到全局事务的表中增加一个undoLog表(AT模式下自己定义的回滚表,不是mysql的undoLog)
4、优缺点:由于有了自己的undoLog,各个服务在执行完自己一阶段的任务后可以立马提交,利用全局锁读写分离,一致性相比XA较差,不需要等待其他服务,并发性能较高 - TCC
1、大致原理:完全不依赖数据库的事务实现,全部使用业务代码来处理事务的回滚,即实现执行、回滚、提交三个接口方法即可,可使用额外字段来判断事务隔离性(一般难以实现,几乎没有事务隔离)
2、优缺点:实现繁琐,对业务代码入侵较大,无锁无事务隔离,但性能最好,适合业务简单,性能要求高的场景 - SAGA
1、大致原理:根据调用链路逐级补偿,需要使用状态机?和编写补偿方法
2、优缺点:需要手动实现代码,无锁无隔离,适用于在一致性性要求不高、调用多方业务的分布式场景
7、网关:gateway
1、快速开始
作为网关,一般是放在一个单独的项目当中
- 添加依赖
- 配置
2、整合nacos
- 添加依赖
- 配置
也可以让gateway根据nacos上的服务名自动匹配
3、断言详解
-
内置的断言工厂
直接看文档就可以:gateway文档 -
自定义断言工厂
可以根据AbstractRoutePredicateFactory的实现类来写,内部断言工厂都实现了这个类
@Component
public class MyRoutePredicateFactory
extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {
public MyRoutePredicateFactory() {
super(MyRoutePredicateFactory.Config.class);
}
//从配置文件接受参数
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("myParam");
}
//将需要接收的参数声明在Config类中
@Validated
@Data
@ToString
public static class Config {
private String myParam;
}
@Override
public Predicate<ServerWebExchange> apply(MyRoutePredicateFactory.Config config) {
return new GatewayPredicate() {
//实现具体逻辑
@Override
public boolean test(ServerWebExchange exchange) {
//这个参数只有等于520时才通过
if (config.getMyParam().equals("520") ) {
return true;
} else {
return false;
}
}
};
}
}
4、过滤器详解
-
内置过滤器:gateway过滤器官方文档
-
自定义过滤器
与断言工厂类似,可以从AbstractGatewayFilterFactory进行模仿
@Component
public class MyFilterGatewayFilterFactory
extends AbstractGatewayFilterFactory<MyFilterGatewayFilterFactory.Config> {
public MyFilterGatewayFilterFactory() {
super(MyFilterGatewayFilterFactory.Config.class);
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("myPath");
}
@Override
public GatewayFilter apply(MyFilterGatewayFilterFactory.Config config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//具体实现逻辑
//修改路径
ServerHttpRequest req = exchange.getRequest();
String newPath = req.getURI().getRawPath()+config.myPath;
ServerHttpRequest request = req.mutate().path(newPath).build();
//执行
return chain.filter(exchange.mutate().request(request).build());
}
};
}
@Data
@ToString
public static class Config {
//添加一层路径
private String myPath;
}
}
- 全局过滤器
不用配置,对所有路由生效
1、内置全局过滤器
2、自定义全局过滤器
@Component
public class LogFlobalFilter implements GlobalFilter {
Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//具体逻辑:日志记录请求路径
logger.info(exchange.getRequest().getURI().toString());
//执行
return chain.filter(exchange);
}
}
5、请求日志、跨域处理
开启请求日志(要作为jvm参数):
跨域配置:
6、整合sentinel
可以根据网关、网关中的具体属性进行限流
- 添加依赖
- 配置
- 使用
根据路由id
根据路径分组
- 流控处理
7、集群
利用nginx对多个网关进行分发即可
8、链路追踪:skyWalking
1、服务端搭建
- 修改UI前端端口号
- 持久化
1、修改配置文件(这里使用mysql的方式,但官方建议用elasticsearch)
(这里的数据库连接错了,我的情况应该是远程数据库:jdbc:mysql://139.224.46.237:3307/seata?characterEncoding=utf-8&serverTimezone=UTC),然后在mysql中创建swtest就好,表会自动创建
2、加入jar包
找到本地项目中的mysql jar包,放入aop-libs中
2、使用
在每个服务的jvm参数中加上如下配置:
gateway网关默认不会加入链路追踪,需要将agent中的optional-plugins中gatwayjar包复制到plugins中(版本随便选一个,不行就换,本次选的是apm-spring-cloud-gateway-2.1.x-plugin-8.7.0)
以下是skyWalking的参数含义:
3、自定义链路追踪
1、添加依赖
2、使用
4、性能剖析
方法加上@trace点击分析之后就可以查看路径上是哪个部分占用的时间较多了
5、集成日志
暂时略过,等学了日志框架之后再回来看p92
6、告警
- 默认告警规则
- 自定义钩子告警方法(也有一些内置的钩子方法)
1、修改配置文件:
2、在github的skyWalking项目中搜索alarmMessage这个类,查看对应版本中这个类的属性
@ToString
@Data
public class AlarmMessage {
private int scopeId;
private String scope;
private String name;
private String id0;
private String id1;
private String ruleName;
private String alarmMessage;
// private List<Tag> tags;
private long startTime;
private transient int period;
private transient boolean onlyAsCondition;
}
3、实现具体接收告警的方法
@PostMapping("/receive")
public void receive(@RequestBody List<AlarmMessage> alarmMessageList) {
//接收到消息之后就可以实现具体逻辑了,如将消息通过微信通知开发人员等
HashMap<String, String> map = new HashMap<>();
for (AlarmMessage alarmMessage : alarmMessageList) {
map.put("Name",alarmMessage.getName());
map.put("AlarmMessage",alarmMessage.getAlarmMessage());
}
System.out.println(map.toString());
}
7、集群
- 修改aop配置文件
将standalone改为下面对应的注册中心如nacos,然后把nacos的地址用户名密码填好就可以
- 修改UI配置文件