nacos(服务注册与发现+配置中心+服务总线)
openFeign(服务调用)+loadBalance(负载均衡)
gatewat(网关)
sentinel(服务降级限流与熔断)
seata(分布式事务)
线程数QPS:每秒的请求数量
流控模式线程数:进入当前方法的线程数也就是请求数 servlet一个请求对于一个线程
直接 关联 链路
直接达到阈值,sentinel给出默认异常提示(blocking… 一句话)
关联
当关联的资源达到阈值时,就限流当前资源
通俗解释来说,比如那我们的程序,现在有testA接口和testB接口,当testA关联的资源testB达到阈值后,就限流testA。例如在一个电商系统中,当支付系统达到阈值,就限流下单系统,防止更多的订单产生的支付打垮了支付系统。
java代码:
package com.example.sentinel.service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class FlowLimitController {
@GetMapping("/testA")
public String testA(){
return "-----testA";
}
@GetMapping("/testB")
public String testB(){
//返回js再次请求,保证QPS超过1,用于演示效果
return "-----testB";
}
}
js代码:
setInterval(function(){
window.location.reload();
},500);
控制台 *** 作:
效果图:
链路
假如某一个服务方法有多个调用来源, 如果我们只想限制来自于某一个来源的的调用路径, 就可以通过链路来限流
理解图:
代码:
@Service
public class TestService {
@SentinelResource("myService")
public String myService() {
return "test service";
}
}
@RestController
public class FlowLimitController {
@Autowired
private TestService testService;
@GetMapping("/testA")
public String testA() {
return "-----testA - " + testService.myService();
}
@GetMapping("/testB")
public String testB() {
return "-----testB - " + testService.myService();
}
}
控制台 *** 作:
此时如果我们访问/testA会发现实际上是不会流控的,这是因为Sentinel 的 CommonFilter 的 web-context-unify 参数默认为true,表示要将调用链路收敛,会导致链路流控效果无效。 我们需要将这个参数设置成true才能取消链路收敛才会生效。
application.properties
spring.cloud.sentinel.web-context-unify=false
server.port=8401
spring.application.name=sentinel-service
spring.cloud.nacos.discovery.server-addr=192.168.43.11:8848
# 配置Sentinel dashboard地址
spring.cloud.sentinel.transport.dashboard=192.168.43.11:31808
# 默认8719端口,被占用会自动从8719+1,直到找到未被占用的端口
spring.cloud.sentinel.transport.port=8719
# 默认为true,表示将调用链路收敛,会导致链路流控效果无效,需要改成false
spring.cloud.sentinel.web-context-unify=false
# 暴露所有端点,给dashboard用
management.endpoint.web.exposure.include=*
效果:
流控效果 快速失败**快速失败:**直接拒绝(RuleConstant.CONTROL_BEHAVIOR_DEFAULT)方式是默认的流量控制方式,当QPS超过任意规则的阈值后,新的请求就会被立即拒绝,拒绝方式为抛出FlowException。这种方式适用于对系统处理能力确切已知的情况下,比如通过压测确定了系统的准确水位时。
warm up**warm up(预热):**即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。
根据codeFactor(冷加载因子,默认3)的值,从阈值/codeFactor,经过预热时长,才达到设置的QPS阈值。
在5秒内最大阈值是3(10/codeFactor),超过5秒,最大阈值为10
控制台:
结果:
排队等待在5秒内狂点 http://localhost:8401/testA,发现超过3次就报错
超过5秒狂点 http://localhost:8401/testA,发现超过3次就不报错,超过10次才报错
**排队等待:**匀速排队(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。
排队等待示意图:
排队等待:匀速排队,让请求以匀速的速度通过,阈值类型必须设置为 QPS ,否则无效。
控制台:
sentinel熔断降级排队等待总结:阈值类型必须为QPS,当QPS达到阈值时,不是立刻拒绝超过阈值的请求,而是让他们进入一个等待队列,等待队列根据一个公式 1000ms/阈值 的结果就是队列匀速放行请求到处理的服务器上,如果
eg:单机阈值设为5,1秒内通过5个,每200ms通过一次。
该限流好比一个漏斗,每隔200ms向漏斗中丢一个令牌,当请求拿到令牌就通过该漏斗,没有拿到令牌就在漏斗中等候令牌(队列的形式),直到请求的等待时间超过100ms(超时时间),该请求原地消失。
如果有高并发的请求进入:按照如上的配置只有第一个请求通过,其余请求全部超时消失
(1)慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。
(2)异常比例 (ERROR_RATIO):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
(3)异常数 (ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。
满足两个条件会触发熔断:
1》单位统计时长请求数大于设置的最小值。下面是每秒钟5个。
2》慢请求达到设置的比例
/**
* 通过此方法模拟慢调用,或不稳定资源(经常出异常)
* AtomicXxx 底层基于CAS算法(乐观锁方式)保证了线程安全和性能
*/
private AtomicInteger atomicInteger = new AtomicInteger(1); //初始值1
@GetMapping("/sentinel05")
public String deSentinel05() throws InterruptedException {
int count = atomicInteger.getAndIncrement();//先取值,再递增
if (count %2 == 0) {
Thread.sleep(200); //模拟耗时
}
return "test Sentinel 05";
}
除了流量控制外,对调用链路中不稳定资源进行熔断降级可以保障高可用。
由于调用关系的复杂性,如果调用链路中的某个资源不稳定,最终会导致请求发生堆积。这里表示熔断策略选择
"慢调用比例"
,表示请求数超过3时
,假如平均响应时间超过200毫秒的有30%
,则对请求进行熔断,熔断时长为10秒钟,10秒以后恢复正常。
异常比例
1》每秒钟请求超过五个
2》异常比例超过50%触发熔断
@GetMapping("/testE")
public JSONResultUtil<String> testE() {
int i = 1 / 0;
return JSONResultUtil.successWithData("testE");
}
异常数模式
异常数模式:当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断
时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错
误)则结束熔断,否则会再次被熔断。
注:统计时间默认为1s 不同版本的sentinel能给你设置的数据不一样
分布式事务seata 概念
Seata处理流程分布式事务处理过程的 ID+三组件模型, ID即Transaction ID XID,全局唯一的事务ID。
三组件:
1.TC (Transaction Coordinator) - 事务协调者
维护全局和分支事务的状态,驱动全局事务提交或回滚。
2.TM (Transaction Manager) - 事务管理器
定义全局事务的范围:开始全局事务、提交或回滚全局事务。 @GlobalTransactional
3.RM (Resource Manager) - 资源管理器
管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交
或回滚。
配置略 配置是否生效如图所示一个TC管理全局,一个XID带着TC,TM,RM。
1.TM向TC申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的XID。
2.XID在微服务调用链路的上下文中传播。
3.RM向TC注册分支事务,将其纳入XID对应的全局事务的管辖。
4.TM向TC发起针对XID的全局提交或回滚决议。
5.TC调度XID下管辖的全部分支事务完成提交或者回滚请求。
以下达订单为例,在Service层的saveOrder方法中需要调用订单服务的保存订单 *** 作,并调用商品服务
中更新库存中的方法
如下图:
使用分布式事务启动日志中出现 Auto proxy of [dataSource] 、Global Transaction Clients are initialized. 表示已
在项目中集成 了seata
在service层需要使用分布式事务的方法上用 @GlobalTransactional注解
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)