Ribbon负载均衡算法
Ribbon共7中负载均衡算法:
1.RoundRobinRule:线性轮询选择服务;
2.RandomRule: 随机选择服务;
3.RetryRule:按照轮询方式选择服务实例,如果返回的是空则在一定时间内不断重试,超过时间依旧没返回实例则返回null;
4.WeightedResponseTimeRule:根据平均响应时间计算服务实例的权重,响应时间越短别选中概率越高。
5.BestAvailableRule:先过滤掉不可用的服务实例,在选择并发量最小的服务实例。
6.AvailabilityFilteringRule:先过滤掉不可用的服务实例,在选择并发量较小的服务实例。
7.ZoneAvoidanceRule:默认的负载均衡策略,根据所在区域和服务性能综合选择服务实例。
Ribbon切换负载均衡算法
在JavaConfig中配置负载均衡的Bean就行
@Bean
public IRule myRule() {
// RandomRule 为随机策略
return new RandomRule();
}
Ribbon自定义负载均衡算法
自定义类继承AbstractLoadBalancerRule 类即可,然后将负载均衡类加入到IRule Bean容器中。
OpenFeign常用注解
1.@FeignClient 对@RequestMapping注解下的接口进行解析,通过动态代理生成实现类,实现负载均衡和服务调用。
2.@EnableFeignClients 开启OpenFeign功能。
3.@RequestMapping
4.@GetMapping 用来映射Get请求
5.@PostMapping 用来映射Post请求
OpenFeign超时控制
默认是1s,超过1s会报错。为避免这种情况,需要进行配置,在消费者的application.yml中进行如下配置:
ribbon:
ReadTimeout: 6000 #建立连接所用的时间,适用于网络状况正常的情况下,两端两端连接所用的时间
ConnectionTimeout: 6000 #建立连接后,服务器读取到可用资源的时间
OpenFeign日志增强
Feign为每一个FeignClient提供 feign.Logger实例,通过它可以对OpenFeign绑定的接口调用情况进行监控。
在消费者中application.yml配置如下:
logging:
level:
#feign 日志以什么样的级别监控该接口
# com.example.service.DeptFeignService是开启 @FeignClient 注解的接口(即服务绑定接口)的完整类名
com.example.service.DeptFeignService: debug
创建一个配置类用来配置日志记录什么内容:
@Configuration
public class ConfigBean {
/**
* OpenFeign 日志增强
* 配置 OpenFeign 记录哪些内容
*/
@Bean
Logger.Level feginLoggerLevel() {
return Logger.Level.FULL;
}
}
Logger.Level级别如下:
NONE:不记录任何信息。
BASIC:只记录请求方法、URL、响应码和执行时间;
HEADERS:除了BASIC记录信息之外,还记录请求和响应的头信息;
FULL:记录所有请求和响应的明细,包括头信息、请求体、元信息等。
SpringCloudGateway核心概念
路由(Route):网关最基本的模块。由一个ID、一个目标URI、一组断言和一组过滤器组成。
断言(Predicate):路由转发的判断条件。通过断言对Http请求进行匹配然后转发到对应服务中。
过滤器(Filter):对请求进行拦截和修改,还可以对它进行上文的响应进行在处理。
注意:路由和断言必须同时声明。
SpringCloudGateway工作流程
1.客户端发送请求到SpringCloudGateway;
2.SpringCloudGateway根据Gateway Handler Mapping找到和请求相匹配的路由,然后将其发送给Gateway Web Mapping。
3.Gateway Web Mapping根据指定的过滤器链将请求发送给指定的服务实例上。
4.过滤器会在请求之前执行也会在请求之后执行。
5.Gateway将请求原路返回给客户端。
Gateway-Predicate断言
注意点:
1.一个路由可以有多个断言;
2.一个路由想转发请求,必须满足所有断言;
3.如果多个路由断言匹配上,则只有第一个会转发请求。
断言 | 示例 | 说明 |
---|---|---|
Path | - Path=/dept/list/** | 当请求路径与 /dept/list/** 匹配时,该请求才能被转发到 http://localhost:8001 上。 |
Before | - Before=2021-10-20T11:47:34.255+08:00[Asia/Shanghai] | 在 2021 年 10 月 20 日 11 时 47 分 34.255 秒之前的请求,才会被转发到 http://localhost:8001 上。 |
After | - After=2021-10-20T11:47:34.255+08:00[Asia/Shanghai] | 在 2021 年 10 月 20 日 11 时 47 分 34.255 秒之后的请求,才会被转发到 http://localhost:8001 上。 |
Between | - Between=2021-10-20T15:18:33.226+08:00[Asia/Shanghai],2021-10-20T15:23:33.226+08:00[Asia/Shanghai] | 在 2021 年 10 月 20 日 15 时 18 分 33.226 秒 到 2021 年 10 月 20 日 15 时 23 分 33.226 秒之间的请求,才会被转发到 http://localhost:8001 服务器上。 |
Cookie | - Cookie=name,c.biancheng.net | 携带 Cookie 且 Cookie 的内容为 name=c.biancheng.net 的请求,才会被转发到 http://localhost:8001 上。 |
Header | - Header=X-Request-Id,\d+ | 请求头上携带属性 X-Request-Id 且属性值为整数的请求,才会被转发到 http://localhost:8001 上。 |
Method | - Method=GET | 只有 GET 请求才会被转发到 http://localhost:8001 上。 |
Gateway-Filter过滤器
分类:
Pre类型:在请求转发到微服务之前对请求进行拦截和修改;
Post类型:对微服务请求响应对响应进行拦截和在处理。
按照作用范围划分:
GatewayFilter:应用在单个路由和一组路由的过滤器;
GlobalFilter:应用在所有路由上的过滤器;
Gateway-StripPrefix过滤配置
如果客户端请求的url是/api/user/query,我们想要在网关请求中去掉/api,那么我们就可以通过StripPrefix来配置。
filter:StripPrefix=1就是去掉/api,如果是StripPrefix=2就是去掉/user。
总结:StripPrefix就是用来去掉请求url中的第几个前缀。
Nacos特性
1.服务注册与发现
2.服务健康监控
3.动态配置服务
4.动态DNS服务
5.服务及元数据管理
Nacos两大组件
1.Nacos Server
2.Nacos Client
Nacos服务注册中心
流程:
1.服务提供者 Nacos Client 启动时,会把服务以服务名(spring.application.name)的方式注册到服务注册中心(Nacos Server);
2.服务消费者 Nacos Client 启动时,也会将自己的服务注册到服务注册中心;
3.服务消费者在注册服务的同时,它还会从服务注册中心获取一份服务注册列表信息,该列表中包含了所有注册到服务注册中心上的服务的信息(包括服务提供者和自身的信息);
4.在获取了服务提供者的信息后,服务消费者通过 HTTP 或消息中间件远程调用服务提供者提供的服务。
Sentinel组成
Sentinel核心库
Sentinel控制台
Sentinel基本概念
资源:被Sentienl保护起来的资源。
规则:围绕资源而设定的规则。
@SentinelResource注解
属性 | 说明 | 必填与否 | 使用要求 |
---|---|---|---|
value | 用于指定资源的名称 | 必填 | - |
entryType | entry 类型 | 可选项(默认为 EntryType.OUT) | - |
blockHandler | 服务限流后会抛出 BlockException 异常,而 blockHandler 则是用来指定一个函数来处理 BlockException 异常的。 |
简单点说,该属性用于指定服务限流后的后续处理逻辑。 | 可选项 |
- blockHandler 函数访问范围需要是 public;
- 返回类型需要与原方法相匹配;
- 参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException;
- blockHandler 函数默认需要和原方法在同一个类中,若希望使用其他类的函数,则可以指定 blockHandler 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
|
| blockHandlerClass | 若 blockHandler 函数与原方法不在同一个类中,则需要使用该属性指定 blockHandler 函数所在的类。 | 可选项 | - 不能单独使用,必须与 blockHandler 属性配合使用;
- 该属性指定的类中的 blockHandler 函数必须为 static 函数,否则无法解析。
|
| fallback | 用于在抛出异常(包括 BlockException)时,提供 fallback 处理逻辑。
fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。 | 可选项 |
- 返回值类型必须与原函数返回值类型一致;
- 方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常;
- fallback 函数默认需要和原方法在同一个类中,若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
|
| fallbackClass | 若 fallback 函数与原方法不在同一个类中,则需要使用该属性指定 blockHandler 函数所在的类。 | 可选项 | - 不能单独使用,必须与 fallback 或 defaultFallback 属性配合使用;
- 该属性指定的类中的 fallback 函数必须为 static 函数,否则无法解析。
|
| defaultFallback | 默认的 fallback 函数名称,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。
默认 fallback 函数可以针对所以类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。 | 可选项 |
- 返回值类型必须与原函数返回值类型一致;
- 方法参数列表需要为空,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常;
- defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
|
| exceptionsToIgnore | 用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。 | 可选项 | - |
Sentinel流量控制
一条流量规则主要由下表中的属性组成,我们可以通过组合这些属性来实现不同的限流效果。
属性 | 说明 | 默认值 |
---|---|---|
资源名 | 流控规则的作用对象。 | - |
阈值 | 流控的阈值。 | - |
阈值类型 | 流控阈值的类型,包括 QPS 或并发线程数。 | QPS |
针对来源 | 流控针对的调用来源。 | default,表示不区分调用来源 |
流控模式 | 调用关系限流策略,包括直接、链路和关联。 | 直接 |
流控效果 | 流控效果(直接拒绝、Warm Up、匀速排队),不支持按调用关系限流。 | 直接拒绝 |
注:QPS 表示并发请求数,换句话说就是,每秒钟最多通过的请求数。
Sentinel 触发限流时,资源会抛出 BlockException 异常,此时我们可以捕捉 BlockException 来自定义被限流之后的处理逻辑。
![image.png](https://img-blog.csdnimg.cn/img_convert/7252a7ea935866e5396a908c3c6afc32.png#clientId=u83fedf90-ce79-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=ueb28fc2b&margin=[object Object]&name=image.png&originHeight=451&originWidth=872&originalType=url&ratio=1&rotation=0&showTitle=false&size=107617&status=done&style=none&taskId=u7cca7091-9058-4588-bed3-596a3b3b890&title=)
![image.png](https://img-blog.csdnimg.cn/img_convert/2654c6f03a8d76a59c008b66dac30241.png#clientId=u83fedf90-ce79-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=uede81bdc&margin=[object Object]&name=image.png&originHeight=556&originWidth=752&originalType=url&ratio=1&rotation=0&showTitle=false&size=44104&status=done&style=none&taskId=u041c42c9-a0f9-43ab-9888-bc1fc164fa1&title=)
![image.png](https://img-blog.csdnimg.cn/img_convert/a52808a7d64031354d43e7ee0b621f92.png#clientId=u83fedf90-ce79-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u92c94b36&margin=[object Object]&name=image.png&originHeight=404&originWidth=727&originalType=url&ratio=1&rotation=0&showTitle=false&size=76842&status=done&style=none&taskId=uefd357b7-b6fe-48ab-9111-f22c9ca6321&title=)
Sentinel熔断降级规则
Sentinel 提供了 3 种熔断策略,如下表所示。
熔断策略 | 说明 |
---|---|
慢调用比例 | |
(SLOW_REQUEST_RATIO) | 选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大响应时间),若请求的响应时间大于该值则统计为慢调用。 |
当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。
经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则再次被熔断。 |
| 异常比例 (ERROR_RATIO) | 当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目且异常的比例大于阈值,则在接下来的熔断时长内请求会自动被熔断。
经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。 |
| 异常数 (ERROR_COUNT) | 当单位统计时长内的异常数目超过阈值之后会自动进行熔断。
经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。 |
Sentinel 熔断降级中共涉及 3 种状态,熔断状态的之间的转换过程如下图。
![image.png](https://img-blog.csdnimg.cn/img_convert/6a8bd2dde0cd0f274b6c33f1cd3e3906.png#clientId=u83fedf90-ce79-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u01c72d43&margin=[object Object]&name=image.png&originHeight=344&originWidth=486&originalType=url&ratio=1&rotation=0&showTitle=false&size=30342&status=done&style=none&taskId=u91aea0b7-b978-4b8d-b48f-c2d04313d98&title=)
Sentinel 实现熔断降级过程
- 在项目中,使用 @SentinelResource 注解的 fallback 属性可以为资源指定熔断降级逻辑(方法)。
- 通过 Sentinel 控制台或代码定义熔断规则,包括熔断策略、最小请求数、阈值、熔断时长以及统计时长等。
- 若单位统计时长(statIntervalMs)内,请求数目大于设置的最小请求数目且达到熔断标准(例如请求超时比例、异常数、异常比例达到阈值),Sentinel 熔断器进入熔断开启状态(OPEN)。
- 处于熔断开启状态时, @SentinelResource 注解的 fallback 属性指定的降级逻辑会临时充当主业务逻辑,而原来的主逻辑则暂时不可用。当有请求访问该资源时,会直接调用降级逻辑使请求快速失败,而不会调用原来的主业务逻辑。
- 在经过一段时间(在熔断规则中设置的熔断时长)后,熔断器会进入探测恢复状态(HALF-OPEN),此时 Sentinel 会允许一个请求对原来的主业务逻辑进行调用,并监控其调用结果。
- 若请求调用成功,则熔断器进入熔断关闭状态(CLOSED ),服务原来的主业务逻辑恢复,否则重新进入熔断开启状态(OPEN)。
使用 @SentinelResource 注解的 blockHandler 属性时,需要注意以下事项:
- 返回值类型必须与原函数返回值类型一致;
- 方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常;
- fallback 函数默认需要和原方法在同一个类中,若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
分布式事务相关概念
分布式事务主要涉及以下概念:
- 事务:由一组操作构成的可靠、独立的工作单元,事务具备 ACID 的特性,即原子性、一致性、隔离性和持久性。
- 本地事务:本地事务由本地资源管理器(通常指数据库管理系统 DBMS,例如 MySQL、Oracle 等)管理,严格地支持 ACID 特性,高效可靠。本地事务不具备分布式事务的处理能力,隔离的最小单位受限于资源管理器,即本地事务只能对自己数据库的操作进行控制,对于其他数据库的操作则无能为力。
- 全局事务:全局事务指的是一次性操作多个资源管理器完成的事务,由一组分支事务组成。
- 分支事务:在分布式事务中,就是一个个受全局事务管辖和协调的本地事务。
我们可以将分布式事务理解成一个包含了若干个分支事务的全局事务。全局事务的职责是协调其管辖的各个分支事务达成一致,要么一起成功提交,要么一起失败回滚。此外,通常分支事务本身就是一个满足 ACID 特性的本地事务。
Seata 整体工作流程
Seata 对分布式事务的协调和控制,主要是通过 XID 和 3 个核心组件实现的。
XID:
XID 是全局事务的唯一标识,它可以在服务的调用链路中传递,绑定到服务的事务上下文中。
核心组件:
- TC(Transaction Coordinator):事务协调器,它是事务的协调者(这里指的是 Seata 服务器),主要负责维护全局事务和分支事务的状态,驱动全局事务提交或回滚。
- TM(Transaction Manager):事务管理器,它是事务的发起者,负责定义全局事务的范围,并根据 TC 维护的全局事务和分支事务状态,做出开始事务、提交事务、回滚事务的决议。
- RM(Resource Manager):资源管理器,它是资源的管理者(这里可以将其理解为各服务使用的数据库)。它负责管理分支事务上的资源,向 TC 注册分支事务,汇报分支事务状态,驱动分支事务的提交或回滚。
Seata 的整体工作流程如下:
- TM 向 TC 申请开启一个全局事务,全局事务创建成功后,TC 会针对这个全局事务生成一个全局唯一的 XID;
- XID 通过服务的调用链传递到其他服务;
- RM 向 TC 注册一个分支事务,并将其纳入 XID 对应全局事务的管辖;
- TM 根据 TC 收集的各个分支事务的执行结果,向 TC 发起全局事务提交或回滚决议;
- TC 调度 XID 下管辖的所有分支事务完成提交或回滚操作。
@GlobalTransactional 注解:
在分布式微服务架构中,我们可以使用 Seata 提供的 @GlobalTransactional 注解实现分布式事务的开启、管理和控制。
当调用 @GlobalTransaction 注解的方法时,TM 会先向 TC 注册全局事务,TC 生成一个全局唯一的 XID,返回给 TM。
@GlobalTransactional 注解既可以在类上使用,也可以在类方法上使用,该注解的使用位置决定了全局事务的范围,具体关系如下:
- 在类中某个方法使用时,全局事务的范围就是该方法以及它所涉及的所有服务。
- 在类上使用时,全局事务的范围就是这个类中的所有方法以及这些方法涉及的服务。