SpringCloud是什么?
分布式结构微服务的一站式解决方案
微服务是什么?
将一个应用拆分成很多个细小的模块,每个模块部署一个服务器,一个服务只做一件事,各个服务器之间互相独立,最大程度降低服务之间的耦合,应用程序组成的所有服务叫微服务
注册中心Nacos
是阿里巴巴开源研发的服务注册中心及配置中心于一体的管理平台
四大功能:
服务发现与健康检查
动态配置管理
动态DNS服务
服务和元数据管理
nacos注册中心:
安装完Nacos之后,在bin中startup.cmd启动Nacos服务器
后台地址 localhost:8848/nacos
在配置文件中指定Nacos注册中心:spring.cloud.nacos.discovery.server-addr: localhost:8848
在启动类上标注@EnableDiscoveryClient表示开启注册发现服务
每个微服务都会注册到Nacos统一管理
nacos配置中心:
bootstrap.yaml配置文件
将配置文件编写在Nacos配置中心,config:server-addr:localhost:8848
先加载bootstrap配置文件,再加载本地application配置文件
@RefreshScope注解标在controoler上,表示支持Nacos动态刷新
在application.yml中配置profiles开发环境,bootstrap.yaml可以动态选择开发环境的配置文件,就不需要修改了,需要先在nacos后台创建配置文件再开启服务器
bootstrap配置文件的命名Data ID:
应用名字-环境名.后缀 例如provider-payment-dev.yaml
Ribbon
负载均衡
多个功能相同的服务器,端口号不同,将用某种方式进行分摊请求服务器,不会每次都请求同一个服务器
有效缓解服务器压力,提高访问效率
Nginx: 服务器级别的负载均衡
每次请求将会先连接服务器,再进行负载均衡计算,获取到计算出的服务器地址进行访问
Ribbon:客户端级别的负载均衡
每次请求都会先进行负载均衡计算,再连接服务器列表,再进行访问
@LoadBalanced表示开启负载均衡,默认采用轮询的方式,标注在RestTemplate模板上
集群之间的应用名字必须一致,端口号不一致
消费者访问提供者集群时,用提供者应用名字替换主机地址访问
自定义负载均衡算法:
创建一个规则类,不能在springboot启动类包下;
将IRue注入到容器中,返回值类型就是对应的负载均衡算法
在启动类上添加@RibbonClient注解 name参数是做负载均衡的服务器名 configuration参数是规则类的字节码
轮询算法原理:
rest接口第几次请求数%服务器集群总数量=实际调用服务器位置下标,每次服务器重启后rest接口计数从1开始
List lists=Discovery.getInstence(服务器名字);
lists.get(index); index就等于上面的余数
OpenFeign
模板化的HTTP客户端,替代原来的RestTemplate,可以隐藏HTTP请求,不需要拼接url和参数,让远程调用变得更加简单,
内部封装了负载均衡和熔断器
怎么用?
远程调用:
@FeignClient标注在自定义接口上,表示当前是微服务框架,在注解中指定需要调用服务的名字
将要调用的服务上的Controller的方法也添加到这个接口里面,并加上请求映射地址,方法标签要一模一样
@EnableFeignClients标注在启动类上,将开启包扫描,将扫描的包路径传入basePackges中,可以传入多个
新建一个Controller,注入Feign客户端接口,调用接口上的方法,实际上就是远程调用,使用起来和本地调用没区别
总结:@Feign+接口+@EnableFeignClients
负载均衡:
默认休眠1秒,如果访问超时就报错,需要在yml中设置超时时间 例如ribbon.ReadTimeout=5000,单位毫秒
默认负载均衡算法是轮询,需要更改算法在yml中配置ribbon.NFL…
熔断器:
底层集成Hystrix,默认关闭,在yml中开启熔断器
feign:
hystrix:
enabled: true
步骤:1.在配置文件中开启熔断器功能
2.创建feign客户端接口的实现类,并实现接口中的方法,方法就是服务降级方法,并添加@component注入到ioc容器
3.在feign客户端接口注解@FeignClient中指定这个实现类的字节码
总结:fallback实现类+@FeignClient中的字节码参数
压缩:需要在配置文件中开启压缩
feign:
compression:
request:
enabled: true #开启请求压缩
response:
enabled: true #开启响应压缩
开启日志
logging:
level:
com: debug #指定包下的日志级别
在配置类中修改日志级别
/**
* Logger.Level.FULL 表示记录所有详细日志
* Logger.Level.NONE 表示不记录日志
*/
@Bean
public Logger.Level level(){
return Logger.Level.FULL;
}
OpenFeign的工作原理:
1.在启动类中添加@EnableFeignClients开启Feign功能
2.服务启动时,会扫描指定包下的Feign客户端,如果没有参数则默认扫描启动类的扫描路径
3.将所有Feign的类扫描到ioc容器中,Feign客户端必须是接口,fallback必须是实现类并且类名的字节码要在Feign客户端注解的参数里面
Gateway
解决客户端的复杂性,只需要一次访问就能访问多个微服务,减少交互次数
每一次请求微服务都会经过网关
网关负责处理安全、监控、权限、跨域问题、反向代理、限流等 类似拦截器
spring:
application:
name: geteway-server
cloud:
gateway:
routes:
- id: user_route #路由名字,唯一id
uri: http://localhost:9001 #路由请求服务的ip,如果是集群lb://服务名字
predicates: #断言,相当于满足条件才放行,在ip后拼接这个路径
- Path=/user/** #路径断言
filters:
- PrefixPath=/user #每次请求添加前缀,访问时就不用写这个前缀了,隐藏url信息,提高安全性
# 配置全局默认过滤器
default-filters:
# 往响应过滤器中加入信息
- AddResponseHeader=X-Response-Default-MyName,meimeikanguolai
自定义过滤器(全局过滤器) GlobalFilter
1.@Component将全局过滤器加入到ioc容器中
2.实现GlobalFilter、Ordered接口
3.GlobalFilter方法是用来过滤的,Ordered方法是用来指定多个过滤器执行顺序的
4.过滤成功才能访问后面的微服务,只需要验证一次就能访问后面所有的微服务,验证失败则返回403状态码,无权限访问
Sentinel
是什么?
阿里巴巴开发的用于服务限流、降级、熔断、系统负载保护等功能的微服务框架
实时监控微服务的健康状态
与hystrix的区别:
hystrix要自己搭建一个微服务
它没有一个完整的页面控制台操作流控、降级、熔断等功能
去哪下?
在github的sentinel官网下载jar包
使用java -jar 运行sentinel,默认端口号是8080
第一次需要访问一次才能显示出服务的状态,因为sentinel采用的是懒加载机制
流控:
QPS 点击次数
线程数 操作资源线程数
流控模式
直接 达到阈值直接失败
关联 与A关联的资源B达到阈值后,就限流自己
链路
流控效果
快速失败 达到阈值就直接降级
Warm Up(预热) 选择预热时长,开始默认是0.3乘阈值,慢慢涨到原来设定的阈值,有一个缓冲过程,可以防止大量请求瞬间打穿服务器
排队等待 匀速排队,而不是一次性大量请求一起处理,而是慢慢处理;单位为毫秒,每时间单位处理一个请求
降级规则:
RT 处理请求时间超出阈值且在时间窗口内通过的请求>=5,满足两个条件触发降级;过了时间窗口期后关闭降级,正常访问
异常比例 当资源每秒请求数>=5且异常比例超过阈值,进入降级状态,异常比例范围是0.0-1.0,如果设置0.5相当于10次请求5次异常触发降级;过了时间窗口期后关闭降级,正常访问
异常数 时间窗口>=60秒 在时间窗口时间内,异常数达到阈值,进入降级;过了时间窗口期后关闭降级,正常访问
热点规则:仅支持QPS
参数索引 Url后面跟着的参数下标
单机阈值 时间窗口内访问次数
窗口时长 时间窗口时长
结合@SentinelResource降级 ,指定sentinel控制台违规兜底(给定了blockHandler参数使用用户自定义的,没有给定用系统默认),java代码出现异常并不降级
@SentinelResource(value = "heat",blockHandler = "heat_block")
@RequestMapping("heat")
public String heat(@RequestParam(value = "h1",required = false) String h1,@RequestParam(value = "h2",required = false) String h2){
return h1+h2;
}
public String heat_block(String h1, String h2, BlockException e){
return "降级了..."+e;
}
参数例外项,当参数达到特定值时可以指定单机阈值;
fallback服务降级,如果同时配了blockHandler,正常请求出异常调用fallback,如果满足sentinel流控规则,那么会调用blockHandler
熔断OpenFeign
激活sentinel对feign的支持
feign:
sentinel:
enable: true
构建一个降级类,@Component加入到spring容器中,实现feign接口,并实现方法,在feign中的@FeignClient注解中配置fallback参数,将降级类的运行时类对象传入即可
流控规则是临时的,服务器关闭流控规则也会删除
如何将sentinel限流规则持久化?
将配置导入nacos中保存
1.导入pom依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
2.配置文件
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
dashboard: localhost:8080
port: 8719
3.在nacos中添加配置文件,名字就算dataId
分布式事务
ACID?
原子性 一致性 隔离性 持久性
本地事务?
在service层设置手动提交,再进行操作数据库,如果都成功就commit提交数据持久化,如果失败就rallback回滚
微服务分布式架构中,每个微服务都会有自己的数据库进行访问,而每个微服务都部署在不同的服务器,这就引出了分布式架构的事务问题
分布式事务就是保证不同数据库之间数据的一致性
分布式事务大致是在微服务之间再套一层事务,例如两个微服务本地事务处理完sql,返回一个成功或者失败的信息,如果都成功,
外面的大事务将会一起提交,如果有1个失败,外面大事务就进行回滚
CPA定理?
c:强一致性
a:可用性
p:分区容错性
如何解决分布式事务的问题? 2pc tcc seata
2pc:分为投票阶段和提交阶段
参与者将自己的提交结果投票给协调者,
协调者收到结果,如果全部成功就进行提交,有一个失败就回滚
缺点就是如果有一个参与者提交数据库响应时间过长,其他参与者和协调者就处于阻塞状态,导致微服务性能会很差
TID-TC-TM-RM 全局ID 、事务参与者、事务管理器、资源管理者
XID:一个全局事务下的唯一标识
TC:seata服务器,负责管理全局事务的提交和回滚
TM:标注@GlobalTransactional注解的服务 事务发起方
RM:事务参与方 分支事务,本地事务
控制本地事务:@Transactional
控制全局事务:@GlobalTransactional
分支事务有多个,一个全局事务控制整个分布式事务,分支事务全部提交成功,TC就将这个全局事务提交,如果有一个分支事务提交失败,
就直接回滚
分布式事务底层实现原理:
TM向TC申请发起全局事务,对应的RM分支事务会加入到全局事务中来,在分支事务里执行sql前,seata会生成一个beforeimage镜像文件,里面记录了执行sql前后的数据。在全局事务提交前会根据RM是否都统一提交事务,如果都统一提交那么TM提交请求给TC,TC申请提交全局事务;如果本地事务有一个需要回滚,那么全局事务就要回滚,此时seata会根据之前生成的镜像文件,生成一个反向sql语句,只要数据没有被脏读,那么就会执行这个反向sql语句进行回滚,并且删除镜像文件里面的数据。此时就好像没有执行过开始那条sql一样