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