微服务服务保护:Sentinel 从入门到流控规则实战

一、高并发下的服务雪崩问题

在微服务架构中,服务间通过网络调用,若单个服务故障且大量请求涌入,会导致任务堆积,最终引发服务雪崩(调用链路中某个服务故障,导致整条链路不可用)。

1.1 模拟高并发场景(基础工程搭建)

1.1.1 服务提供者(sentinel-provider)

application.yml

复制代码
server:
  port: 9090
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.209.129:8848
  application:
    name: sentinel-provider

核心服务类(模拟网络延时):

java 复制代码
package com.hg.service;

import com.hg.pojo.User;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {
	@Override
	public User getUserById(Integer id) {
		// 模拟网络延时2秒
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return new User(id,"王粪堆-provider",18);
	}
}
1.1.2 Feign 接口(sentinel_feign)
java 复制代码
package com.hg.feign;

import com.hg.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@FeignClient("sentinel-provider")
public interface UserFeign {
    @RequestMapping(value = "/provider/getUserById/{id}")
    public User getUserById(@PathVariable Integer id);
}
1.1.3 服务消费者(sentinel_consumer)

pom.xml 核心依赖:

XML 复制代码
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <!-- Feign接口依赖 -->
    <dependency>
        <groupId>com.hg</groupId>
        <artifactId>sentinel_feign</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

application.yml(限制 tomcat 线程数):

XML 复制代码
server:
  tomcat:
    max-threads: 10 # 降低tomcat最大并发,模拟资源不足
feign:
  client:
    config:
      default:
        connectionTimeout: 5000 
        readTimeout: 5000    

测试接口

java 复制代码
@RequestMapping(value = "/hello")
public String hello() {
    return "Hello Sentienl!!!";
}
1.1.4 压测验证雪崩雏形
  1. 下载 JMeter,配置线程组(高并发),调用http://127.0.0.1:8080/consumer/getUserById/1
  2. 同时访问http://127.0.0.1:8080/consumer/hello,发现 hello 接口阻塞等待 ------ 服务雪崩雏形出现。

1.2 Sentinel 核心概念与入门

1.2.1 Sentinel 是什么?

Sentinel(分布式系统的流量防卫兵)是阿里开源的服务保护框架,以流量 为切入点,通过流量控制、熔断降级等维度保障服务稳定性。

1.2.2 核心概念
  • 资源:Sentinel 要保护的对象(如接口、方法);
  • 规则:保护资源的策略(流量控制、熔断降级等)。
1.2.3 Sentinel 入门实现(两种方式)
方式 1:抛异常方式(原生 API)

添加依赖

XML 复制代码
<dependency>
	<groupId>com.alibaba.csp</groupId>
	<artifactId>sentinel-core</artifactId>
</dependency>

接口改造 + 限流规则配置

java 复制代码
@RequestMapping(value = "/hello")
public String hello() {
    Entry entry = null;
    try {
        // 定义资源,Sentinel检查规则
        entry = SphU.entry("/consumer/hello");
        return "Hello Sentienl!!!";
    } catch (BlockException e) {
        // 限流兜底逻辑
        e.printStackTrace();
        return "接口被限流了, exception: " + e;
    }finally {
        if (entry != null) {
            entry.exit(); // 必须与entry成对出现
        }
    }
}

// 初始化限流规则
@PostConstruct
public void initFlowQpsRule() {
    List<FlowRule> rules = new ArrayList<FlowRule>();
    FlowRule rule1 = new FlowRule();
    rule1.setResource("/consumer/hello"); // 资源名
    rule1.setGrade(RuleConstant.FLOW_GRADE_QPS); // 限流维度:QPS
    rule1.setCount(2); // QPS阈值2
    rules.add(rule1);
    FlowRuleManager.loadRules(rules); // 加载规则
}
方式 2:注解方式(低侵入)

添加依赖

XML 复制代码
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-annotation-aspectj</artifactId>
</dependency>

开启注解支持 + 接口改造

java 复制代码
// 启动类/配置类中注册Bean
@Bean
public SentinelResourceAspect sentinelResourceAspect(){
    return new SentinelResourceAspect();
}

// 接口层
@RequestMapping(value = "/hello2")
@SentinelResource(value="/consumer/hello2",blockHandler = "blockHandlerMethod")
public String hello2() {
    return "Hello Sentienl2!!!";
}

// 限流兜底方法
public String blockHandlerMethod(BlockException e){
    return "接口被限流了, exception: " + e;
}

// 规则配置(同方式1,仅修改资源名)
@PostConstruct
public void initFlowQpsRule() {
    List<FlowRule> rules = new ArrayList<FlowRule>();
    FlowRule rule1 = new FlowRule();
    rule1.setResource("/consumer/hello2");
    rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
    rule1.setCount(2);
    rules.add(rule1);
    FlowRuleManager.loadRules(rules);
}
1.2.4 Sentinel 控制台接入
  1. 下载启动控制台 :下载地址:https://github.com/alibaba/Sentinel/releases启动命令:java -jar sentinel-dashboard-1.8.1.jar访问地址:http://localhost:8080(默认账号 / 密码:sentinel/sentinel)

  2. 客户端接入控制台

    1)添加依赖:

XML 复制代码
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

2)配置 yml:

XML 复制代码
spring:
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080 # 控制台地址

3)访问任意接口(触发 Sentinel 懒加载),即可在控制台看到监控数据。

二、Sentinel 流控规则全解析

流控规则核心参数说明:

参数 说明
资源名 唯一名称,默认请求路径
针对来源 限流调用方(微服务名),默认 default(不区分来源)
阈值类型 QPS(每秒访问次数)/ 线程数(每秒访问线程数)
流控模式 直接(限流当前资源)/ 关联(关联资源阈值触发限流)/ 链路(指定接口触发)
流控效果 快速失败 / Warm Up / 排队等待

2.1 阈值类型

2.1.1 QPS 限流
  • 逻辑:当接口 QPS 达到阈值时,直接限流;
  • 实战步骤
    1. 控制台新增流控规则(资源名:/consumer/getUserById/{id},阈值类型 QPS,阈值 2);
    2. JMeter 高并发调用http://127.0.0.1/consumer/getUserById/1,触发限流。
2.1.2 线程数限流
  • 逻辑:当访问接口的线程数达到阈值时,触发限流(适合慢接口);
  • 实战步骤
    1. 控制台新增流控规则(阈值类型:线程数,阈值 5);
    2. JMeter 模拟多线程调用,线程数超过 5 时触发限流。

2.2 流控模式

2.2.1 直接模式

默认模式,直接对当前资源的 QPS / 线程数限流(上文案例均为直接模式)。

2.2.2 关联模式
  • 逻辑:关联资源达到阈值时,限流当前资源(适合 "应用让步" 场景,如支付接口阈值触发,限流订单接口);
  • 实战步骤
    • 新增测试接口:
java 复制代码
@RequestMapping(value="/test")
public String test(){
    return "test";
}
    • 控制台配置流控规则(资源名:/consumer/getUserById/{id},流控模式:关联,关联资源:/consumer/test,阈值 2);
    • JMeter 高并发调用/consumer/test,触发/consumer/getUserById/{id}限流。
2.2.3 链路模式
  • 逻辑:指定上级接口触发限流(粒度比 "针对来源" 更细);
  • 说明:需配置链路入口,实战中较少用(略)。

2.3 流控效果

2.3.1 快速失败

默认效果,触发限流时直接返回异常(Sentinel 默认提示)。

2.3.2 Warm Up(预热模式)
  • 逻辑 :QPS 阈值从阈值/3开始,经 "预热时长" 逐步升至设定阈值(适合流量突增场景);
  • 实战步骤
    1. 控制台配置(流控效果:Warm Up,预热时长 5 秒,QPS 阈值 6);
    2. 前 5 秒访问接口,QPS 超过 2(6/3)即限流;5 秒后阈值升至 6,可正常访问。
2.3.3 排队等待
  • 逻辑:请求匀速通过,超出阈值的请求排队等待(超时丢弃),保证服务负载均匀;
  • 实战步骤
    1. 控制台配置(流控效果:排队等待,QPS 阈值 1,超时时间 10ms);
    2. 接口添加时间打印:
java 复制代码
@RequestMapping(value = "/getUserById/{id}")
public User getUserById(@PathVariable Integer id) {
    System.out.println("排队等待效果:"+new Date());
    return userFeign.getUserById(id);
}

高并发调用接口,控制台打印日志间隔约 1 秒(匀速处理),超时请求被丢弃。

相关推荐
code bean6 小时前
【LangChain】检索器完全指南:从向量检索到生产级 RAG 架构
java·开发语言·微服务
一水鉴天6 小时前
不确定性问题确定解的 DevOps 九宫格内核 20260612(腾讯元宝)
人工智能·架构
小短腿的代码世界7 小时前
Qt行情协议解析与二进制编解码优化:从FIX到自定义协议的全链路架构
开发语言·qt·架构
是温不嗜温8 小时前
QR 准谐振反激架构:当下中小功率快充的主流选择
架构·电源管理·电源芯片·ac-dc
AI焦点8 小时前
2026年AI应用架构:如何避坑并选对API聚合中转服务?
大数据·人工智能·架构
TOPGO智能8 小时前
AI PC 端侧 AI 实战:知易智能知识管家的全栈架构与踩坑实录
人工智能·架构·高通开发
JGDT_13 小时前
ERP重塑与未来趋势:SAP的实践及大一统格局(上)
大数据·人工智能·安全·架构·开源
小短腿的代码世界13 小时前
Qt对象树析构链与智能指针协同:零泄漏内存管理架构
开发语言·qt·架构
AI科技星13 小时前
数术江湖·全卷合集 - 硬核江湖・数理史诗
android·人工智能·架构·概率论·学习方法
John_ToDebug14 小时前
Chromium 132→148 升级实战:Legacy IPC 消息丢失问题深度解析
c++·chrome·ai·架构