java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Springboot Sentinel 限流

Springboot集成Sentinel 组件实现基本限流功能(快速入门)

作者:firechili

Sentinel是阿里巴巴开发的面向云原生微服务的高可用流控防护组件,支持流量控制、熔断降级、系统负载保护等多维度防护,适用于秒杀、消息削峰填谷等场景,本文给大家介绍Springboot集成Sentinel组件实现基本限流功能,感兴趣的朋友跟随小编一起看看吧

概述

Sentinel 是面向云原生微服务的高可用流控防护组件,以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保障服务稳定性。阿里巴巴在近10年双十一大促中成功验证了Sentinel在高并发场景下的可靠性。

核心概念

资源 (Resource)

资源是Sentinel的核心概念,可以是:

规则 (Rule)

围绕资源的实时状态设定的策略:

核心特性

特性描述
丰富的应用场景支持秒杀、消息削峰填谷、集群流量控制、实时熔断等
完备的实时监控提供秒级监控数据,支持500台以下集群汇总
广泛的开源生态支持Spring Cloud/Dubbo/gRPC/Quarkus等框架
SPI扩展机制提供定制规则管理、动态数据源适配等扩展能力

系统架构大概长这样

快速入门:核心库使用

1. 添加Maven依赖

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-core</artifactId>
    <version>1.8.6</version>
</dependency>
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-annotation-aspectj</artifactId>
    <version>1.8.6</version>
</dependency>

2、通过硬编码方式设定流控规则,主要有拦截器和注解两种方式(不够灵活,不推荐)

2.1、使用拦截器对所有请求进行限流拦截

@Component
public class FlowLimitInterceptor implements HandlerInterceptor {
    private static final Logger log = LoggerFactory.getLogger(FlowLimitInterceptor.class);
    private final ObjectMapper objectMapper;
    public FlowLimitInterceptor(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    } 
     // SmallNovel 项目所有的资源,名称只用于标识,建议易于理解即可
    private static final String SMALL_NOVEL_RESOURCE = "SmallNovelResource";
	//静态代码块使规则在类加载时就初始化了
    static {
        // 接口限流规则:所有的请求,限制每秒最多只能通过 2000 个,超出限制匀速排队
        List<FlowRule> rules = new ArrayList<>();
        FlowRule rule1 = new FlowRule();
        rule1.setResource(SMALL_NOVEL_RESOURCE);
        rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // 设置 QPS 限流 2000.
        rule1.setCount(2000);
        rule1.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER);
        rules.add(rule1);
        FlowRuleManager.loadRules(rules);
        // 接口防刷规则 1:所有的请求,限制每个 IP 每秒最多只能通过 50 个,超出限制直接拒绝
        ParamFlowRule rule2 = new ParamFlowRule(SMALL_NOVEL_RESOURCE)
                .setParamIdx(0)
                .setCount(50);
        // 接口防刷规则 2:所有的请求,限制每个 IP 每分钟最多只能通过 1000 个,超出限制直接拒绝
        ParamFlowRule rule3 = new ParamFlowRule(SMALL_NOVEL_RESOURCE)
                .setParamIdx(0)
                .setCount(1000)
                .setDurationInSec(60);
        ParamFlowRuleManager.loadRules(Arrays.asList(rule2, rule3));
    }
    @Override
    public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception {
        String ip = IpUtils.getRealIp(request);
        Entry entry = null;
        try {
            entry = SphU.entry(SMALL_NOVEL_RESOURCE, EntryType.IN, 1, ip);
            return HandlerInterceptor.super.preHandle(request, response, handler);
        } catch (BlockException ex) {
            log.info("IP:{}被限流了!", ip);
            response.setCharacterEncoding(StandardCharsets.UTF_8.name());
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            response.getWriter()
                    .write(错误信息);
        } finally {
            if (entry != null) {
                entry.exit(1, ip);
            }
        }
        return false;
    }
}

然后将拦截器注册到webconfig

@Configuration
public class WebConfig implements WebMvcConfigurer {
    private final FlowLimitInterceptor flowLimitInterceptor;
    public WebConfig(FlowLimitInterceptor flowLimitInterceptor) {
        this.flowLimitInterceptor = flowLimitInterceptor; }
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 流量限制拦截器
        registry.addInterceptor(flowLimitInterceptor)
                .addPathPatterns("/**")
                .order(0);
}
}

2.2、使用spring切面技术配合注解使用Sentinel组件

 配置Sentinel切面

@Configuration
public class SentinelAspectConfig {
    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }
}

使用注解定义受保护资源

@Service
public class OrderService {
    @SentinelResource(
        value = "createOrder", 
        blockHandler = "handleFlowBlock",
        blockHandlerClass = OrderServiceBlockHandler.class
    )
    public String createOrder() {
        // 业务逻辑
        return "订单创建成功";
    }
    // 异常处理函数(可选)
    public String handleException(Throwable ex) {
        return "服务异常: " + ex.getMessage();
    }
}

注意:注解方式埋点不支持 private 方法

实现流控处理逻辑

public class OrderServiceBlockHandler {
    // 流控处理函数需满足:
    // 1. public static修饰
    // 2. 返回类型与原方法相同
    // 3. 参数列表包含原方法所有参数 + BlockException
    public static String handleFlowBlock(BlockException ex) {
        return "请求过于频繁,请稍后重试!触发规则: " + ex.getRule().getResource();
    }
}

初始化流控规则

@Component
public class SentinelRuleInitializer {
    @PostConstruct
    public void initFlowRules() {
        List<FlowRule> rules = new ArrayList<>();
        FlowRule rule = new FlowRule();
        rule.setResource("createOrder");   // 资源名称
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // QPS限流模式
        rule.setCount(2);                 // 阈值:2次/秒
        rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT); 
        rules.add(rule);
        FlowRuleManager.loadRules(rules);
    }
}

高级配置选项

流量控制行为

// 在FlowRule中设置
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP); // 预热模式
rule.setWarmUpPeriodSec(10); // 预热时间(秒)

rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER); // 匀速排队
rule.setMaxQueueingTimeMs(500); // 最大排队时间

熔断降级规则

List<DegradeRule> degradeRules = new ArrayList<>();
DegradeRule degradeRule = new DegradeRule();
degradeRule.setResource("createOrder");
degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT); // 异常数模式
degradeRule.setCount(5); // 异常数阈值
degradeRule.setTimeWindow(30); // 熔断时长(秒)
degradeRules.add(degradeRule);
DegradeRuleManager.loadRules(degradeRules);

最佳实践

3、控制台部署与使用(最推荐的方式)

# 下载控制台JAR包
wget https://github.com/alibaba/Sentinel/releases/download/1.8.6/sentinel-dashboard-1.8.6.jar
# 启动控制台(默认端口8080)
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -jar sentinel-dashboard-1.8.6.jar

控制台功能:

常见问题解决

# 设置日志目录

csp.sentinel.log.dir=/var/log/sentinel

# 日志文件最大数量(默认7)

csp.sentinel.log.max.file.count=14

# 单个日志文件大小(默认300MB)

csp.sentinel.log.max.file.size=1073741824  # 1GB

# 日志输出类型(file 或 console)

csp.sentinel.log.output.type=file

通过系统环境变量配置

# Linux/macOS
export SENTINEL_LOG_DIR=/var/log/sentinel
# Windows
set SENTINEL_LOG_DIR=C:\logs\sentinel  

性能优化建议

Sentinel通过精细化的流量控制和多种防护机制,为微服务架构提供可靠的稳定性保障。建议生产环境结合控制台使用,充分发挥动态配置和实时监控的优势。

到此这篇关于Springboot集成Sentinel 组件实现基本限流功能(快速入门)的文章就介绍到这了,更多相关Springboot Sentinel 限流内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文