微服務常見容錯方案和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