SpringCloud 微服务架构与 Sentinel

注:完整笔记可在 https://github.com/WuSangui571/cloud-demo 中的 README.md 文件浏览,此处发表的是经由 AI 润色过的精简版。

1. Sentinel 概述

随着微服务架构的广泛应用,服务间稳定性日益重要。Spring Cloud Alibaba Sentinel 基于流量控制,提供多维度保护,包括流量路由、熔断降级、系统自适应过载保护和热点流量防护。其核心手段为限流熔断降级

1.1 工作原理

  • 规则定义

    • 自动适配主流框架(Web Servlet、Dubbo、Spring Cloud、gRPC、Spring WebFlux、Reactor),所有 Web 接口视为资源。

    • 编程式:通过 SphU API 定义。

    • 声明式:使用 @SentinelResource 注解。

  • 资源类型

    • 流量控制(FlowRule)

    • 熔断降级(DegradeRule)

    • 系统保护(SystemRule)

    • 来源访问控制(AuthorityRule)

    • 热点参数(ParamFlowRule)

image-20250927182248336.png

2. Sentinel 整合与配置

2.1 启动 Sentinel Dashboard

  1. 下载与启动

java -jar sentinel-dashboard-1.8.8.jar
  1. 访问控制台

    • 浏览器输入 http://localhost:8080,默认用户名和密码均为 sentinel

image-20250927100704537.png

2.2 服务整合 Sentinel

  1. 添加依赖

<dependency>
   <groupId>com.alibaba.cloudgroupId>
   <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>
  1. 配置应用

    • application.yaml 中添加:

spring:
cloud:
  sentinel:
    transport:
      dashboard: localhost:8080
    eager: true
  1. 验证集成

    • 启动服务后,在 Sentinel Dashboard 中查看服务信息。

image-20250927100802605.png

  1. 标记资源

    • 使用 @SentinelResource 注解定义资源,例如:

package com.sangui.order.service.impl;

import com.sangui.order.bean.Order;
import com.sangui.order.service.OrderService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
   @SentinelResource(value = "createOrder")
   @Override
   public Order createOrder(Long productId, Long userId) {
       // 实现逻辑
       return new Order();
  }
}
  1. 测试

    • 访问 http://localhost:8000/create?productId=1&userId=2,在 Dashboard 的“簇点链路”中刷新查看调用详情。

image-20250927102326452.png

3. 异常处理

3.1 自定义 Web 异常处理

  • 默认行为:Web 接口限流时显示 Blocked by Sentinel (flow limiting)

  • 自定义处理

    • 实现 BlockExceptionHandler 接口:

package com.sangui.order.exception;

import com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.sangui.common.JsonUtils;
import com.sangui.common.R;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;

import java.io.PrintWriter;

/**
* @author sangui
* @createTime 2025-09-27
* @description 自定义 Web 异常处理器
* @version 1.0
*/
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {
   @Override
   public void handle(HttpServletRequest request, HttpServletResponse response, String resource, BlockException e) throws Exception {
       response.setContentType("application/json;charset=utf-8");
       PrintWriter writer = response.getWriter();
       R r = R.fail("服务 " + resource + " 被 Sentinel 限制,原因: " + e.getClass().getName());
       writer.write(JsonUtils.toJson(r));
       writer.flush();
       writer.close();
  }
}
  • 效果:限流 /create 接口时,返回:

{
 "code": 500,
 "msg": "服务 /create 被 Sentinel 限制,原因: class com.alibaba.csp.sentinel.slots.block.flow.FlowException",
 "data": null
}

3.2 @SentinelResource 异常处理

  • 默认行为:限流时返回 500 错误。

  • 自定义配置

    • 使用 blockHandlerfallbackdefaultFallback 参数。

    • 示例(blockHandler):

package com.sangui.order.service.impl;

import com.sangui.order.bean.Order;
import com.sangui.order.service.OrderService;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
   @SentinelResource(value = "createOrder", blockHandler = "createOrderFallback")
   @Override
   public Order createOrder(Long productId, Long userId) {
       return new Order();
  }

   public Order createOrderFallback(Long productId, Long userId, BlockException e) {
       Order order = new Order();
       order.setId(-1L);
       order.setTotalAmount(new BigDecimal("0.00"));
       order.setUserId(userId);
       order.setNickName("未知用户");
       order.setAddress("未知地址, " + e.getClass().getName());
       return order;
  }
}

3.3 Feign 异常处理

  • 参考前文 OpenFeign 章节,定义 Fallback 类实现异常处理。

4. 流控规则

4.1 阈值类型

  • QPS(每秒查询率):限制每秒请求数,适用于高频接口。

    • 示例:QPS = 5,表示每秒最多 5 个请求。

  • 并发线程数:限制同时处理线程数,保护资源。

    • 示例:并发数 = 5,超过 5 个线程触发限流。

  • 集群模式

    • 单机均摊:阈值分摊到各节点。

    • 总体阈值:集群共享总阈值。

4.2 流控模式

  • 直接:默认模式,针对资源直接限流。

  • 关联:关联资源超阈值时限流当前资源。

    • 示例:写操作频繁时限制读操作。

  • 链路:针对特定调用路径限流。

    • 配置:spring.cloud.sentinel.web-context-unify: false

    • 示例:/seckill 限流,而 /create 不限流。

image-20250927145633352.png

  • 链路示例

package com.sangui.order.controller;

import com.sangui.order.bean.Order;
import com.sangui.order.service.OrderService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class OrderController {
   @Resource
   private OrderService orderService;

   @GetMapping("/create")
   public Order createOrder(@RequestParam("productId") Long productId,
                            @RequestParam("userId") Long userId) {
       return orderService.createOrder(productId, userId);
  }

   @GetMapping("/seckill")
   public Order seckill(@RequestParam("productId") Long productId,
                        @RequestParam("userId") Long userId) {
       Order order = orderService.createOrder(productId, userId);
       order.setId(Long.MAX_VALUE);
       System.out.println("秒杀操作");
       return order;
  }
}
  • 配置与验证

    • 设置 spring.cloud.sentinel.web-context-unify: false

    • createOrder 资源配置链路限流,入口为 /seckill

    • 访问 /seckill 触发限流,/create 正常。

image-20250927154118029.png

  • 关联示例

    • 写操作 /writeDb 频繁时限制读操作 /readDb

package com.sangui.order.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class OrderController {
   @GetMapping("/writeDb")
   public String writeDb() {
       return "writeDb success";
  }

   @GetMapping("/readDb")
   public String readDb() {
       return "readDb success";
  }
}
  • 效果:频繁访问 /writeDb 后,/readDb 受限。

4.3 流控效果

  • 快速失败:默认,拒绝超限请求。

  • Warm Up:预热模式,初始 QPS 低,逐步升至阈值。

    • 示例:QPS = 5,period = 3s,3 秒内升至 5。

  • 排队等待:按顺序处理,超时丢弃。

    • 示例:timeout = 5s,超过 5 秒拒绝。

  • 压力测试

    • 使用 Postman Runner 配置请求次数和间隔。

image-20250927165229758.png

5. 熔断规则

5.1 工作原理

  • 断路器:监测调用失败,快速切断不稳定资源。

  • 最佳实践:在客户端配置熔断。

image-20250927182717184.png

5.2 熔断策略

  • 慢调用比例

    • 条件:请求数 ≥ 5,RT > 200ms 占比 ≥ 70%(10s 内)。

    • 熔断:30s 后半开状态,探测后决定。

  • 异常比例

    • 条件:请求数 ≥ 5,异常占比 ≥ 80%(5s 内)。

    • 效果:快速失败,避免请求打到目标服务。

  • 异常数

    • 条件:异常数 ≥ 10(任意请求量内)。

    • 效果:类似异常比例,但直接计数。

6. 热点规则

  • 定义:限制高频访问参数(如商品 ID、用户 ID)。

  • 实现

    • 示例:限制用户秒杀 QPS ≤ 1,vvip 用户 6 号无限制,商品 666 号禁止访问。

package com.sangui.order.controller;

import com.sangui.order.bean.Order;
import com.sangui.order.service.OrderService;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class OrderController {
   @Resource
   private OrderService orderService;

   @GetMapping("/seckill")
   @SentinelResource(value = "seckill-order", fallback = "seckillFallback")
   public Order seckill(@RequestParam("productId") Long productId,
                        @RequestParam("userId") Long userId) {
       Order order = orderService.createOrder(productId, userId);
       order.setId(Long.MAX_VALUE);
       return order;
  }

   public Order seckillFallback(Long productId, Long userId, BlockException e) {
       Order order = new Order();
       order.setId(10086L);
       order.setAddress(e.getClass().getName());
       System.out.println("秒杀兜底回调");
       return order;
  }
}
  • 配置

    • 参数 1(userId)阈值 1。

    • 例外:userId = 6 阈值高。

    • 参数 0(productId = 666)阈值 0。

image-20250927174644804.png


  • 微信
  • 赶快加我聊天吧
  • QQ
  • 赶快加我聊天吧
  • weinxin
三桂

发表评论 取消回复 您未登录,登录后才能评论,前往登录