SpringCloud
2023-05-11 12:45:46 0 举报
AI智能生成
1
作者其他创作
大纲/内容
第一章
第二章
第三章(微服务)
本章概况:微服务拆分与编写
单体架构
一个归档包(例如war包)包含所有功能的应用程序,我们通常称为单体应用。而架构单体应用的方法论,就是单体应用架构。
优点
架构简单,开发部署方便
缺点
复杂性高、部署慢,频率低、扩展能力受限(内存大小等问题)、阻碍技术创新(更换技术框架麻烦)
微服务
定义
特性
1)每个微服务可独立运行在自己的进程里——单独的Tomcat
2)一系列独立运行的微服务共同构建起整个系统——每个微服务可以独立运行
3)每个服务为独立的业务开发,一个微服务只关注某个特定的功能,例如订单管理、用户管理等;<br>
4)可使用不同的语言与数据存储技术(契合项目情况和团队实力)——java PHP等混用, 不同数据库储存
5)微服务之间通过轻量的通信机制进行通信,例如通过REST API进行调用﹔<br>
6)全自动的部署机制
架构图
优点
1)单个服务更易于开发、维护——每个微服务关注有限业务
2)单个微服务启动较快——单个微服务业务较少
3)局部修改容易部署——每个微服务都单独部署
4)技术栈不受限——重构单个服务风险少,效率高
5)按需伸缩——那个微服务业务可以单独扩展,迁移到更好的服务器上
缺点
1)运维要求高——需要运维多个微服务应用
2)分布式固有的复杂性——网络延迟,分布式事务
3)重复劳动
应用场景
1、大型、复杂的项目
2、有快速迭代的需求
3、访问压力大——微服务是去中心化的,数据库,业务都是拆分的
不适用的场景
1)业务稳定——维护中的项目,需求不变、只改BUG
2)迭代周期长——更新版本慢
微服务拆分
1)业界流行的拆分方法论
领域驱动设计(Domain Driven Design)
1、对需要解决的问题进行建模
2、重视设计建模
学习曲线高
面向对象(by name. / by verb.)
通过状态和行为拆分
2)个人心得<br>
职责划分——规划好职责边界
通用性划分——个人中心、消息中心等
3)合理粒度
拆分的微服务满足业务
团队不会认为微服务拆分的太大
增量迭代——能快速迭代
持续进化——能切换语言
4)小程序的拆分
项目架构
架构图
创建项目
目录
项目流程<br>
第四章(版本兼容整合)
SpringCloud
快速构建分布式系统的工具集
主要功能<br>
SpringCloudAlibaba
是SpringCloud的子项目
致力于提供微服务开发的一站式解决方案<br>
·包含微服务开发的必备组件
·基于Spring Cloud,符合Spring Cloud标准
·阿里的微服务解决方案
主要功能
版本与兼容性
SpringCloud版本命名
SpringBoot的命名
SpringCloud生命周期
Spring Boot、Spring Cloud、Spring Cloud Alibaba的兼容性关系
查看兼容
整合SpringCloud
注意版本兼容
<dependencyManagement><br> <dependencies><br><!-- 整合Spring—cloud--><br> <dependency><br> <groupId>org.springframework.cloud</groupId><br> <artifactId>spring-cloud-dependencies</artifactId><br> <version>Greenwich.SR1</version><br> <type>pom</type><br> <scope>import</scope><br> </dependency><br> <!-- 整合Spring—cloud-alibaba--><br> <dependency><br> <groupId>org.springframework.cloud</groupId><br> <artifactId>spring-cloud-alibaba-dependencies</artifactId><br> <version>0.9.0.RELEASE</version><br> <type>pom</type><br> <scope>import</scope><br> </dependency><br> </dependencies><br><br> </dependencyManagement>
第五章nacos服务发现控制台
服务提供者和服务消费者
服务发现原理(消费者能找到提供者)
类比非实际
风险:服务发现组件压力大, <br> 服务发现组件崩溃
防止
1)定时发送服务信息
2)缓存到本地,直接调用
可能:微服务崩溃
last_heartbeat定时发送信息,某个实例在时间点未发送,<br>服务发现组件回讲status状态改变未down,随后改变本地缓存
Nacos
一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
每个微服务集成nacosclient
版本兼容
ctrl进入、搜索nacos,下载兼容版本
Linux等系统
到bin目录
sh startup.sh -m standalone
windows
1、启动startup.cmd
2、成功输入192.168.31.210:8848/nacos/index.html
3、输入账号密码 nacos nacos进入
讲应用注册到nacos
1、添加依赖
2、写注解——早期版本需要在启动类添加
3、写配置
成功后,到页面查看详细信息
注意:SpinrgBoot、SpringCloud、Spring
为内容中心引入服务发现
服务发现的领域模型<br>
<br>
namespace模型
1、Namespace:默认public,用来实现隔离,比如开发环境,测试环境,生产环境
2、Namespace:默认public,用来实现隔离,比如开发环境,测试环境,生产环境
3、Service: 微服务,比如说用户中心微服务,内容中心微服务。
4、Cluster:指定默认微服务的虚拟划分,比如:北京机房的用户中心微服务集 群Cluster=BJ-User-Center;<br>成都机房的用户中心微服务集群Cluster=CD-User-Center.并且还可以实现,北京的应用优先调用BJ-User-Center
流程
1)nacos中命名空间、新建命名空间
2)创建成功
3)yml配置
元数据
定义
Nacos数据(如配置和服务)描述信息,如服务版本、权重、容灾策略、负载均衡策略、鉴权配置、<br>各种自定义标签 (label),从作用范围来看,分为服务级别的元信息、集群的元信息及实例的元信息。
服务级别
集群级别
实例级别
作用
1、描述微服务信息
2、让微服务调度更加灵活——版本控制
配置(如何设置)
1、nacos控制台编辑以key——value形式
2、java-yml中配置
第六章负载均衡、ribbon
负载均衡
服务器端负载均衡
请求都通过nginx(nginx部署在服务器端),通过负载均衡算法,进行转发
客户端负载均衡<br>
在内容中心中进行负载均衡计算
实现流程
1、所有用户中心实例的请求地址
2、随机算法
随机滁一个下标
3、放入RestTemplate
<br>
测试:启动多个用户中心
多次发送请求,随机调用实例
Ribbon负载均衡
定义
Netflix开源的客户端侧负载均衡器<br>
简化这部分算法的组件
架构演进图
引入
1、依赖包含在SpringCloud中
2、注解
启动类Application中 在RestTemplate加注解LoadBalanced
3、<br>
会将user-center自动转换成用户中在在nacos上的地址,并进行负载算法
组成
列表
内置的负载均衡规则
<br>
细粒度
配置自定义
应用场景
对不同微服务调用实例有不同的负载均衡规则
代码配置(configuration)
1、创建ribbonconfiguration包——必须在启动类包外<br>
创建RibbonConfigUartion类
Spring是主树状上下文,Ribbon有子上下文,不能重叠
后果:配置被所有实例共享,变成全局配置
2、创建用户中心的RIbbonConfiguartion
配置属性方式(yml)
对比<br>
总结<br>
代码和配置属性方式同时存在,优先级在属性配置
尽量使用属性配置,属性方式实现不了的情况下再考虑用弋码配置
在同一个微服务内尽量保持单一性,比如统一使用属性配置,不要两种方式混用,增加定位代码的复杂性
全局配置
支持的配置项
配置类配置config
举例
配置属性yml
饥饿加载
Ribbon默认是懒加载——第一次请求反应慢
开启
细粒度
扩展Ribbon
权重支持
1、在config包中创建NacosWeightedRule类
使用nacos内置的权重负载均衡规则
2、修改RibbonConfiguration<br>
Ribbon内置的规则不支持权重——自定义规则
使用不具备权重的负载均衡原因,springCloud标准
同集群优先
1、config
NacosSameClusterWeightedRule类
2.ribbonConfiguratio
扩展已被作者提交到SpringCloud alibaba新版本可尝试直接使用
基于元数据的版本控制
1、设置元数据
yml中spring-cloud-nacos-discovery-metadata:(key-value形式)
nacos页面控制台设置
2、负载均衡规则中获取实例元数据
在nacosSameClusterWeightedRule类中设置
场景使用
实际需求
https://www.imooc.com/article/288674
深入理解namespace
指定namespace
pulic下的内容中心不能调用dev下的用户中心<br>
调用不能跨namespace,只能调用i相同的namespace实例
现有架构问题
1、代码不可读,对新员工难读懂
2、复杂的url难以维护
3、难以适应快速迭代的需求,参数改变,修改复杂
4、编程体验不统一——restTemplate里面内容无提示
第七章——Feign:帮助实现远程http请求<br>(替换restTemplate)
定义<br>
Feign是Netflix开源的声明式HTTP客户端——帮助实现远程http请求
实现流程
1、加依赖<br>
<dependency><br> <groupId>org.springframework.cloud</groupId><br> <artifactId>spring-cloud-starter-openfeign</artifactId><br> </dependency>
2、注解——启动类上加注解<br>
3、创建包feignclient 、创建类userCenterFeignClient
4、service中
替换restTemplate内容
Feign中整合ribbon,负载均衡配置依然适用
组成
继承特性
不继承:
缺点:1、紧耦合 2、userDto类和user属性有不同,由于json文本转换会报错
优点:控制器和Feign代码相似,抽象出共同的接口,代码重用
日志级别配置
Feign日志级别
细粒度配置自定义
方式
1、yml配置
2、config代码配置<br>
1、@FeignClient注解中添加
2、配置包中创建配置类
如果加了Configuration,要放在启动类包外,防止上下文重叠
3、yml中
全局配置
config配置
启动类上添加,value为feign的配置
yml配置
修改微服务名称为defult
支持的配置项
config配置项
<br>
yml配置项
<br>
总结
对比
Ribbon配置 vs Feign配置
Feign config配置 vs yml配置
全局代码<全局属性<细粒度代码<细粒度属性
建议使用<br>
1、尽量使用属性配置,属性方式实现不了的情况下再考虑用代码配置
2、在同一个微服务内尽量保持单一性,比如统一使用属性配置,不要两种方式混用,增加定位代码的复杂性
多参数请求构造
1、添加配置
有相同feignClient name同名是添加
2、feignClient类
post请求
http://www.imooc.com/article/289000
脱离Ribbon使用——未注册nacos使用
1、创建FeignClient类
必须有name值
2、测试
RestTemplate 对比 Feign
实际应用
原则:尽量用Feign,杜绝使用RestTemplate,使用统一<br>
Feign性能优化
配置连接池<br>
feign——默认urlconnection,支持阿帕奇HttpClient和OkHttpClient
1、加依赖
<dependency><br> <groupId>io.github.openfeign</groupId><br> <artifactId>feign-httpclient</artifactId><br> </dependency>
2、yml
OkHttpClient
<dependency><br> <groupId>io.jsonwebtoken</groupId><br> <artifactId>jjwt-api</artifactId><br> <version>0.10.7</version><br> </dependency>
日志级别
生产环境Basic级别
常见问题
http://www.imooc.com/article/289005
第八章Sentinel、容错<br>(轻量级的流量控制,熔断降级java库)
雪崩效应
定义
对前者的调用失败->请求强制等待->线程强制阻塞(知道请求超时)->计算机资源消耗-><br>高并发积累下,B服务失效 ,形成雪崩效应 =级联效应=级联失效
常见容错方式
1、超时,设置超短的请求时间,释放线程快
2、限流(限制实例高并发请求,减少调用),超过就拒绝
3、仓壁模式
每个控制器拥有独立的线程池,设置大小,超过拒绝
4、断路器模式
https://martinfowler.com/bliki/CircuitBreaker.html<br>
设置一段时间内的错误次数,超过就跳闸,经过一段时间后,半打开,再尝试调用
Sentinel
定义
https://github.com/alibaba/Sentinel
轻量级的流量控制,熔断降级java库——解决雪崩等问题
实现
1、添加依赖<br>
<dependency><br> <groupId>org.springframework.cloud</groupId><br> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId><br> </dependency>
无注解、无配置,加依赖即使用
2、查看效果
添加依赖
<dependency><br> <groupId>org.springframework.boot</groupId><br> <artifactId>spring-boot-starter-actuator</artifactId><br> </dependency>
yml配置<br>
访问
localhost:8080/actuator/sentinel
控制台
搭建
1、下载https://github.com/alibaba/Sentinel/releases<br>
2、window启动 在文件目录下 cmd——java -jar sentinel-dashboard-1.6.2.jar
3、localhost:8080/#/login<br>账号密码:Sentinel
整合
yml配置<br>
懒加载,访问后,控制台才有内容
成功<br>
QPS:每秒查询率
流控规则
Sentinel控制台->簇点链路->新增流控—达到预设值,会限流
流控模式
直接
访问达到阈值,限流
关联
当关联的资源达到阈值,就限流自己<br>
适用于选择优先于读还是写
链路<br>
只记录指定链路上的流量
API级别,test-a test-b都单独计算限流
流控效果
快速失败
直接访问失败,抛异常
Warm Up预热
根据codeFactor(默认3)的值,从阈值/codeFactor,经过预热时长才到达设置的QPS阈值<br>
阈值/3作为最初的预设值,经过预热时间后才达到QPS阈值
应用场景:秒杀服务,让允许的通过的流量缓慢的增加
排队等待
匀速排队,让请求以均匀的速度通过,阈值类型必须设成QPS,否则无效
不会丢弃请求,应对突发流量,平时空闲的场景<br>一秒一次请求,达到预设时间未完成的请求丢弃<br>
降级规则
RT
RT大于一秒,并且在5秒内,通过请求大于等于5次,降级
注意点:默认为4900毫秒
需求大于4900毫秒,需要通过yml修改,控制台修改无效<br>
异常比例
<br>
异常数
<br>
一分钟内统计异常数大于10,降级,10秒后,关闭降级,<br>注意点:时间窗口<60秒可能会出问题,可能连续降级<br>——10关闭降级瞬间,可能异常数仍大于10,继续降级
热点规则
测试代码
配置
窗口时间内,参数索引为0的,QPS达到阈值就会限流
对应索引的参数参数值不是5的话,阈值为1,不是5的话阈值为1000
应用场景
存在热点参数,SQP高
注意点,参数必须是基本类型或者是String,否则不会生效
源码——com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowChecker#passCheck
系统规则<br>
类型
LOAD
◆当系统load1 (1分钟的load )超过阈值,且并发线程数超过系统容量时触发,建议设置为CPU核心数*2.5。<br>(仅对Linux/Unix-like机器生效)
查看uptime<br>
分别是1分钟 5分钟 15分钟内的系统负载
系统容量= maxQps * minRt,·(maxQps :秒级统计出来的最大QPS,minRt :秒级统计出来的最小响应时间)<br>
源码——com.alibaba.csp.sentinel.slots.system.SystemRuleManager#checkBbr
RT
所有入口流量的平均RT达到阈值触发<br>
线程数<br>
所有入口流量的并发线程数达到阈值触发
入口QPS
所有入口流量的QPS达到阈值触发
com.alibaba.csp.sentinel.slots.system.SystemRuleManager#checkSystem
授权规则<br>
/shares/1值允许test微服务访问——黑名单反之
代码配置
控制器内加方法
private void initFlowQpsRule() {<br> List<FlowRule> rules = new ArrayList<>();<br> FlowRule rule = new FlowRule("resourceName");<br> // set limit qps to 20<br> rule.setCount(20);<br> rule.setGrade(RuleConstant.FLOW_GRADE_QPS);<br> rule.setLimitApp("default");<br> rules.add(rule);<br> FlowRuleManager.loadRules(rules);<br> } <br>resourceName 例子/shares/1
测试代码
Sentinel与控制台通信原理分析
控制台发送到微服务
服务发现原理,<br>
控制台和微服务的通信端口
调用APi
获取Api<br>
注册/心跳发送——com.alibaba.csp.sentinel.transport.heartbeat.SimpleHttpHeartbeatSender
通信API——com.alibaba.csp.sentinel.command.CommandHandler的实现类<br>
应用连接控制台的配置项<br>
应用端连接控制台配置
控制台配置
<br>
修改账号密码<br>
启动时
Sentinel API详解
关闭保护防止干扰
测试代码
3个API
SphU
Tracer
ContextUtil
SentinelResource注解详解
重构实现
优化
创建Sentinel包,ControllerBlockHandlerClass类
参数中添加blockHandlerClass
1.6之后——fallbackClass同上
RestTemplate整合Sentinel
启动类中添加注解SentinelRestTemplate
测试代码
@Autowired<br> private RestTemplate restTemplate;<br><br> @GetMapping("/test-rest-template-sentinel/{userId}")<br> public UserDTO test(@PathVariable Integer userId) {<br> return this.restTemplate<br> .getForObject(<br> "http://user-center/users/{userId}",<br> UserDTO.class, userId);<br> }
Sentinl控制台中设置QPS阈值
提供开关
关闭后,控制台没有资源显示
修改异常显示
查看源代码
org.springframework.cloud.alibaba.sentinel.custom.SentinelBeanPostProcessor
Feign整合Sentinel
添加配置即可
限流降级时,自定义处理逻辑
1、fallback包中创建UserCenterFeignClientFallback类
2、FeignClient
3、控制台设置流控规则
触发流控规则,进入userCenterFeignClient方法
获取异常——自定义
feignClient包内创建fallbackfactory包,创建类
FeingClient注解中添加fallbackFactory属性
控制台设置流控阈值
fallbackFactory比fallback更加强大能获取异常
org.springframework.cloud.alibaba.sentinel.feign.SentinelFeign
Sentinel使用总结
<br>
规则持久化
服务器重启,规则不重设
拉模式http://www.imooc.com/article/289402
架构图
实现流程
1、加依赖
<dependency><br> <groupId>com.alibaba.csp</groupId><br> <artifactId>sentinel-datasource-extension</artifactId><br></dependency><br><br>
2、实现代码
Sentinel包下创建类
3、配置
创建目录resources.META-INF.services
创文件com.alibaba.csp.sentinel.init.InitFunc
重启控制台和内容中心
优缺点
优点
·简单易懂
·没有多余依赖(比如配置中心、缓存等)
缺点
·由于规则是用FileRefreshableDataSource定时更新的,所以规则更新会有延迟。如果FileReireshableDataSource定时时间过大,可能长时间延迟;如果FileRefreshableDataSource过小,又会影响性能;
规则存储在本地文件,如果有一天需要迁移微服务,那么需要把规则文件一起迁移,否则规则会丢失。
推模式http://www.imooc.com/article/289464<br>
架构图
实现流程
根据笔记改造流控规则,繁杂
更改后的架包
https://github.com/eacdy/Sentinel-Dashboard-Nacos
使用实例
1、启动
修改后
2、添加配置
优缺点
生产环境使用Sentinel
https://ahas.console.aliyun.com/使用阿里云托管<br>
流程
1、添加依赖<br>
排除掉与Sentinel通信的依赖
2、添加埋点——可以省略,springCloud-alibaba已集成
3、配置参数
集群流控
<br>
架构图
文档——https://github.com/alibaba/Sentinel/wiki/%E9%9B%86%E7%BE%A4%E6%B5%81%E6%8E%A7
扩展
错误页优化
流控和降级显示错误相同
创建类UrlBlockHandler
实现区分来源<br>RequestOriginParser<br>
创建类MyRequestOriginParser
可将origin放在handler中
支持ResfulURL
创建MyUrlcleaner接口
通过现象看本质
源代码commonFilter.java
有默认的配置,可重写修改
总结
配置项总结
http://www.imooc.com/article/289562
本章总结:容错方式
仓壁模式
未完成,但使用控制台配置每个控制器的线程数
第九章-管理员审核分享业务实现<br>(根据文档实现)
流程
1、控制器
2、实体类中的dto
@Data<br>public class ShareAuditDTO {<br> /**<br> * 审核状态<br> */<br> private AuditStatusEnum auditStatusEnum;<br> /**<br> * 原因<br> */<br> private String reason;<br>}<br>
@Getter<br>@AllArgsConstructor<br>public enum AuditStatusEnum {<br> /**<br> * 待审核<br> */<br> NOT_YET,<br> /**<br> * 审核通过<br> */<br> PASS,<br> /**<br> * 审核不通过<br> */<br> REJECT<br>}<br><font color="#ec7270">枚举</font>
3、service
注入private final RocketMQTemplate rocketMQTemplate
创建类
异步实现方法
使用MQ
MQ实现
编写生产者
1、加依赖
注意版本兼容
2、yml配置<br>
不写group启动失败
其他MQ使用文档:https://docs.spring.io/spring-boot/docs/2.1.5.RELEASE/reference/html/boot-features-messaging.html#boot-features-jms<br>
编写消费者user-center中
1、依赖
2、yml<br>
实现代码
dto
创建类AddBonusListener<br>
service
<br>
<br>
MQ<br>
架构演进
适用场景
异步处理——将耗时到不阻塞主流程的业务。
流量削峰填谷<br>
秒杀场景,流量涌入,
使用MQ控制参加人数,超过就丢弃请求或跳转错误页
解耦微服务
A服务调用B服务,B失效,A接口无法正常返回,
使用MQ,A生产消息到MQ,B消费MQ中的消息,不会相互影响
选择
http://www.imooc.com/article/290040<br>ActiveMQ Kafka RabbitMQ <font color="#e74f4c">RocketMQ</font>
RocketMQ
下载教程:http://www.imooc.com/article/290089
下载网址——https://rocketmq.apache.org/download
快速入门——https://rocketmq.apache.org/docs/quickStart/01quickstart/
安装
搭建控制台
http://www.imooc.com/article/290092
启动懒人jar包,输入localhost:17890/#/
术语和概念
进阶
https://git.imooc.com/coding-358/rocketmq-dev-guide/src/master/book.pdf
实现分布式事务
流程
术语
消息状态
实现
数据库加一张表<br>
代码实现流程
AddBonusTransactionListener
service
0 条评论
下一页