微服务服务保护: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 秒(匀速处理),超时请求被丢弃。

相关推荐
candyTong1 小时前
Claude Code Agent Teams:多 Agent 协作的生命周期与实现机制
后端·架构
tq10866 小时前
认知连续性与组织墙的崩塌:AI原生时代的架构重构
人工智能·架构
_code_bear_6 小时前
OpenSpec CLI 与 OPSX 工作流说明
前端·后端·架构
志凌海纳SmartX7 小时前
浅析 kernel bypass 网卡及其在超融合架构的性能表现
架构·网卡·高可用·低延迟·smartx·榫卯超融合
400分7 小时前
吃透RAG核心-----语义检索与关键字检索底层原理
算法·架构
扬帆破浪9 小时前
sidecar崩溃后前端怎么续命 重启策略与状态保留
前端·人工智能·架构·开源·知识图谱
漓漾li10 小时前
每日面试题(2026-05-15)
架构·go·agent
三无推导10 小时前
OpenHuman 开源项目详解:个人 AI 助手架构与核心技术拆解
人工智能·性能优化·架构·开源·ai助手
安当加密11 小时前
AES-256直接加密就够了?微服务架构下的敏感数据加密:信封加密、格式保留加密和字段级加密全解析
微服务·云原生·架构
闵孚龙12 小时前
Claude Code 状态恢复机制全解析:自动压缩后文件、技能、计划与 Agent 上下文如何不断片?
人工智能·架构·claude