微服务常见容错方案和Sentinel


1、超时

通过超时来释放资源,这样就不容易被拖死,只要释放够快。

2、限流

通过评估来限制流量,防止微服务被拖死。

3、仓壁模式

资源有对立线程池,拥有自己拒绝策略。资源之间不相互影响。

4、断路器模式

监控错误率或者错误次数达到一定阈值,就跳闸,就认为依赖微服务不可用,监控加开关

 

 

二 使用sentinel进行微服务容错

1、sentinel是什么

轻量级的流量控制、熔断降级java库

https://github.com/alibaba/Sentinel

2、整合sentinel

加依赖

三、整合控制台

 根据自己的sentinel客户端下载对应的控制台版本

下载地址

https://github.com/alibaba/Sentinel/releases

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
启动命令


整合控制台
添加如下配置
spring:
  sentinel:
    dashboard:localhost:9090
然后访问localhost:8081
可以看到如下界面

 

 

 点击簇点链路

并且设计流控规则

 

 

 流控规则有

1、qps

2、线程数

3、还可以根据来源

4、高级配置里面还有关联,关联资源达到一定阈值就限流自己。使用场景就是查询接口不能过快,不能影响修改接口。

5、只记录链路上的流量,就是记录入口流量达到阈值就限流。演示如下

@GetMapping("/test-a")
public void testa(){
testService.commos();
}

@GetMapping("/test-b")
public void testb(){
testService.commos();
}
@Service
@Slf4j
public class TestService {
@SentinelResource("commons")
public void commos() {
log.info("被调用了");
}
}
访问test-a,访问test-b就会在簇点链路中展示资源
编辑流控规则如下

 

 

 必须加上斜杠否则不生效。

 

流控效果

1、快速失效

源码类为com.alibaba.csp.sentinel.slots.block.flow.controller.DefaultController

2、warnup

根据codeFactor,从阈值/codeFactor作为新阈值,经过预热时间才能达到设置的QPS阈值

3、排队

请求排队匀速通过,流控模式不能设置线程数。

 

降级规则

1、RT平均响应时间,默认响应最大时间4900ms,需要修改-Dcsp.sentinel.statistic.max.rt=xxx修改

 

 

 

2、异常比例

 

 

 

3、异常数,分钟数的,时间窗口最好设置大于60s

 

 

 

 

 

 

 

4、sentinel目前没有断路器半开状态
5、热点规则配置如下,试用于某些参数请求qps特别高

 

 

 

源码
com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowChecker#passCheck

 



 

 系统规则

1、load,load1,一分钟电脑负载负载超过阈值且并发线程数超过系统容量时触发,建议设置为CPU核心数*2.5,仅对Linux/Unix like机器生效

2、系统容量=maxQps*minRt

maxQps:秒级统计出来的最大QPS

minRt:秒级统计出来的最小响应时间

相关源代码

com.alibaba.csp.sentinel.slots.block.system.SystemRuleManager#checkBbr
系统RT:所有入口流量的平均RT达到阈值触发
线程数:所有入口流量的并发线程数达到阈值触发
入口QPS:所有入口流量的QPS达到阈值触发
 
com.alibaba.csp.sentinel.slots.block.system.SystemRuleManager#checkSystem

--------------------------------------------------------------------------------
代码配置规则
详情见
https://www.imooc.com/article/289345
@GetMapping("test-add-flow-rule")
public String testHot(){
this.initFlowQpsRule();
return "success";
}

private void initFlowQpsRule() {
List<FlowRule> rules = new ArrayList<>();
FlowRule flowRule = new FlowRule();
flowRule.setCount(20);
flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
flowRule.setLimitApp("default");
rules.add(flowRule);
FlowRuleManager.loadRules(rules);
}

Sentinel控制台与微服务通讯原理
1、集成Sentinel-transport-simple-http,实现了一套微服务注册和发现机制
2、定时拉取监控规则
3、定时推送
源码
com.alibaba.csp.sentinel.transport.heartbeat.SimpleHttpHeartbeatSender
com.alibaba.csp.sentinel.command.CommandHandler的实现类

应用端配置项
sentinel:
transport:
dashboard: localhost:9090
#使用什么 ip
client-ip: 127.0.0.1
heartbeat-interval-ms: 10000
port: 8719
控制台的配置项

配置项         默认值         最小值           描述
server.port 8080   指定端口
csp.sentinel.dashboard.server localhost:8080   指定地址
csp.sentinel.dashboard.auth.username sentinel    
csp.sentinel.dashboard.auth.password sentinel    
server.servlet.session.timeout 30分钟    
project.name     指定程序名称






 Sentinel Api,Sentinel不统计除BlockException或者BlockException的子类

@GetMapping("test-add-flow-api")
public String testAddFlowApi(@RequestParam String a){
Entry entry = null;
try {
entry = SphU.entry("test-add-flow-api");
if(StringUtils.isEmpty(a)){
throw new IllegalArgumentException("a must be not null");
}
return "success";
}catch (BlockException e){
e.printStackTrace();
}finally {
if(entry!=null){
entry.exit();
}
}
return "success";
}
如果需要控制就如下
@GetMapping("test-add-flow-api")
public String testAddFlowApi(@RequestParam String a){
Entry entry = null;
try {
entry = SphU.entry("test-add-flow-api");
if(StringUtils.isEmpty(a)){
throw new IllegalArgumentException("a must be not null");
}
return "success";
}catch (BlockException e){
e.printStackTrace();
}catch (IllegalArgumentException e2){
Tracer.trace(e2);
return "参数非法";
}finally {
if(entry!=null){
entry.exit();
}
}
return "success";
}

针对来源

@GetMapping("test-add-flow-api")
public String testAddFlowApi(@RequestParam String a){
Entry entry = null;
String resource = "test-add-flow-api";
ContextUtil.enter(resource,"");
try {
entry = SphU.entry(resource);
if(StringUtils.isEmpty(a)){
throw new IllegalArgumentException("a must be not null");
}
return "success";
}catch (BlockException e){
e.printStackTrace();
}catch (IllegalArgumentException e2){
Tracer.trace(e2);
return "参数非法";
}finally {
if(entry!=null){
entry.exit();
}
ContextUtil.exit();
}
return "success";
}
使用sentinelResource,优化代码
@GetMapping("test-sentinelResource")
@SentinelResource(value = "test-sentinelResource",blockHandler = "block")
public String testSentinelResource(@RequestParam String a){
if(StringUtils.isEmpty(a)){
throw new IllegalArgumentException("a must be not null");
}
return "success";
}

public String block(String a,BlockException e){
log.warn("限流,或者降级了",e);
return "限流了,或者降级了";
}

源码

com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect

com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspectSupport

RestTemplate整合Sentinel

@Bean
@LoadBalanced
@SentinelRestTemplate
public RestTemplate restTemplate(){
return new RestTemplate();
}
resttemplate:
sentinel:
enabled: false

为Feign整合Sentinel
feign:
sentinel:
enabled: true
上面Feign和RestTemplate访问过的资源都可以添加监控。
@Component
@Slf4j
public class BaiduFallBackFactory implements FallbackFactory<BaiduFeignClient> {
@Override
public BaiduFeignClient create(Throwable throwable) {
return new BaiduFeignClient() {
@Override
public String index() {
log.warn(""+throwable);
return null;
}
};
}
}
打印异常。

如何在生产环境使用sentinel
推拉模式持久化规则
推模式
https://www.imooc.com/article/289402
 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM