Sentinel[超详细讲解]-5

发布于:2025-04-02 ⋅ 阅读:(17) ⋅ 点赞:(0)

🚓 主要讲解流控模式 三种方式中的最后一种: 关联🚀

        流量控制成为保障系统稳定性与可靠性的关键一环 🚒 。关联流控(Associated Flow Control)作为其中一项重要技术,能够巧妙地协调不同资源间的调用关系,避免因某个资源的过度使用而引发系统雪崩。本文将以数据库的读写操作为例,深入探讨关联流控的实战应用

 1️⃣ 关联流控原理剖析

关联流控的核心思想:资源A的访问达到阈值时,自动限制关联资源B的访问,防止系统过载。 类比: 主干道(A)拥堵时,限制支路(B)车流,保障整体通行(系统稳定)。

关键点

  1. 触发条件:资源A的访问频率超阈值。
  2. 关联动作:自动对资源B施加限流。
  3. 目的:通过优先级控制(保核心资源),维持系统整体稳定性

2️⃣ 数据库关联流控概要(读 vs 写)

核心问题💘
  • 资源争用:读(read_db)与写(write_db)共享底层存储,高并发写入时,大量读操作会加剧争用,导致:
    • 写操作延迟(数据持久化变慢)
    • 读操作超时(连接池耗尽)
    • 系统崩溃风险(CPU/IO 过载)
关联流控方案🚒
  1. 触发条件
    • 监控 write_db 的并发数/延迟/错误率,超过阈值时触发流控。
  2. 调控策略
    • 限流读操作:降低 read_db 的并发配额(如从 1000 QPS 降至 300 QPS)。
    • 动态降级:返回缓存数据或简化查询(避免全表扫描)。
  3. 恢复机制
    • 当 write_db 负载回落,逐步恢复 read_db 的正常流量。
关键
  • 写优先:保障数据一致性(如订单支付、库存扣减)。
  • 系统稳定:避免雪崩效应,维持服务可用性。
  • 资源平衡:通过牺牲部分读性能(非核心路径),换取整体稳定性。
类比场景🚉

类似高速公路收费站:当货车(写操作)密集通行时,临时关闭部分轿车(读操作)通道,确保货车优先通过,避免整体拥堵。

3️⃣ 代码实战讲解 

1、配置读写资源的关联限流规则

功能➡️ :通过 Sentinel 初始化数据库读写限流规则,实现:

  • 写操作(write_db)限流:QPS ≤ 50
  • 读操作(read_db)关联限流:当 write_db 繁忙时,自动限制 read_db 流量(基础 QPS=100)

实例代码

import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

@Component
public class DbFlowRuleConfig {

    @PostConstruct
    public void initDbFlowRules() {
        List<FlowRule> rules = new ArrayList<>();
        
        // 写操作规则 - 基础限流
        FlowRule writeRule = new FlowRule();
        writeRule.setResource("write_db");
        writeRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        writeRule.setCount(50); // 写操作QPS阈值50
        rules.add(writeRule);
        
        // 读操作规则 - 关联写操作
        FlowRule readRule = new FlowRule();
        readRule.setResource("read_db");
        readRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        readRule.setCount(100); // 读操作基础QPS阈值100
        readRule.setRefResource("write_db"); // 关联写操作资源
        readRule.setStrategy(RuleConstant.STRATEGY_RELATE); // 关联策略
        readRule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
        rules.add(readRule);
        
        FlowRuleManager.loadRules(rules);
    }
}

关键配置 

参数 说明
setRefResource 关联资源(write_db触发读限流)
setStrategy(RELATE) 启用关联流控策略
setCount 基础QPS阈值(读100,写50)

效果:当 write_db QPS > 50,自动降低 read_db 的实际允许流量,优先保障写入。

2、数据库操作服务实现

功能🉑 :集成 Sentinel 注解实现数据库读写操作的限流与降级

  • 读操作:限流时返回提示,降级时返回缓存数据
  • 写操作:限流时返回提示

代码事例

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.stereotype.Service;

@Service
public class DatabaseService {

    // 读数据库操作
    @SentinelResource(value = "read_db", 
                      blockHandler = "readBlockHandler",
                      fallback = "readFallback")
    public String readFromDb(String query) {
        // 模拟数据库读操作
        try {
            Thread.sleep(10); // 模拟IO延迟
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return "查询结果: " + query;
    }
    
    // 写数据库操作
    @SentinelResource(value = "write_db", 
                     blockHandler = "writeBlockHandler")
    public String writeToDb(String data) {
        // 模拟数据库写操作
        try {
            Thread.sleep(20); // 模拟IO延迟
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return "写入成功: " + data;
    }
    
    // 读操作限流处理
    public String readBlockHandler(String query, BlockException ex) {
        return "系统繁忙,读操作被限流,请稍后再试";
    }
    
    // 写操作限流处理
    public String writeBlockHandler(String data, BlockException ex) {
        return "系统繁忙,写操作被限流,请稍后再试";
    }
    
    // 读操作降级处理
    public String readFallback(String query, Throwable t) {
        return "查询降级返回:缓存数据";
    }
}

效果

  • 限流时:返回友好提示,避免用户长时间等待。
  • 降级时:读操作返回缓存数据,保证基本可用性。

3、控制器层暴露接口 

功能🉐 :负责将数据库服务的读写接口暴露给外部 

代码事例

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/db")
public class DabaController {

    @Autowired
    private DatabaseService databaseService;
    
    @GetMapping("/read")
    public String read(@RequestParam String query) {
        return databaseService.readFromDb(query);
    }
    
    @PostMapping("/write")
    public String write(@RequestBody String data) {
        return databaseService.writeToDb(data);
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到