基于Sentinel实现对不同ip进行限流熔断

技术选型
1. Sentinel
  • Sentinel 是阿里巴巴开源的限流、熔断、降级组件,旨在为分布式系统提供可靠的保护机制。
  • 它设计用于解决高并发流量下的稳定性问题,并且支持与 Dubbo、Spring Cloud 等多种框架集成。

Sentinel 的功能:home | Sentinel

  1. 限流:支持基于 QPS(每秒查询数)、并发数量等条件的限流。支持滑动窗口、预热、漏桶等算法。
  2. 熔断降级:支持失败率、慢调用比例等指标触发熔断,并提供自动恢复机制。
  3. 热点参数限流:可以基于特定的参数进行限流,如限制特定用户 ID 的请求频率。
  4. 系统负载保护:可以根据系统的实际负载(如 CPU、内存)动态调整流量。
  5. 丰富的规则配置:通过配置中心或控制台动态调整限流和熔断规则。

优势

  • 功能丰富、提供控制台、更新较频繁、社区活跃、文档清晰,能够快速入门上手。
2. Hystrix

Hystrix 是什么? https://github.com/Netflix/Hystrix

  • Hystrix 是 Netflix 开源的一个限流、熔断和降级库。
  • 它通过熔断器模式在检测到下游服务失败率过高时中断请求,以防止系统资源耗尽。

目前已经停止维护

3、Resilience4j

https://github.com/resilience4j/resilience4j

Resiience4j 是一个轻量级的熔断、限流、隔离、重试库,它设计灵感来源于 Netflix 的 Hystrix 框架,专门设计为响应式编程和 Java 8+风格下的熔断库。

优点: 它很轻量级,没有外部依赖,特别适合响应式编程风格,

缺点: 相比 Sentinel,功能相对较少,尤其在限流功能上不够丰富。

4、Guava RateLimiter

Ratelimiter 是 Guava 提供的一个限流工具,基于令牌桶算法实现,主要用于对系统的流量进行控制。

缺点:它仅支持限流,且功能相对单一,不能处理熔断等复杂场景。适合不需要复杂熔断或隔离功能的小型

项目,主要用于 单机系统 的流量控制。

5、Redisson RRateLimiter

Redisson 是一个基于 Redis 的 Java 驱动程序,它提供了丰富的分布式工具和数据结构,其中包括分布式

锁、计数器、队列、信号量,以及限流(Rate Limiter)等功能。

Redisson 提供了 Ratelimiter 接口来支持限流操作。你可以定义时间窗口内允许的最大请求数,超出限制

的请求将被阳塞或拒绝。它的限流基于 Redis 的计数器来控制访问频率,确保即使在多台服务器之间,也

能有效地限制请求速率。

总结

  • Sentinel 是目前最成熟、功能最强大的分布式限流、熔断、降级组件,适合大规模分布式系统。
  • Resilience4j 专为响应式编程设计,适合轻量级应用和微服务架构。
  • Guava RateLimiter 适合单机环境下的简单限流需求。
  • Redisson RRateLimiter 适合已有 Redis 基础设施的分布式系统,提供高效的分布式限流功能。
  • Hystrix 已经停止维护,建议在新项目中避免使用,但对于遗留系统可以继续维护。

本次基于Sentinel 进行实现

实现
整合

1.下载jar包

Sentinel

2.将jar包放在任意非中文、不包含特殊字符的目录下 启动jar包

java -Dserver.port=8131 -jar sentinel-dashboard-1.8.6.jar

3.访问地址 http://localhost:8131 账号密码都是sentinel

建议 参考官方文档选择版本。由于 Spring Boot 3.0,Spring Boot 2.7~2.4和 2.4以下版本之间变化较大,目前企业级客户老项目相关 Spring Boot 版本仍停留在 Spring Boot 2.4 以下,为了同时满足存量用户和新用户不同需求,社区以 Spring Boot 3.0 和 2.4 分别为分界线,同时维护 2022.x、2021.x、2.2.x 三个分支迭代。

本项目 Spring Boot 用的是 2.7,因此使用 Sentinel starter 的版本 2021.0.5.0。在项目中引入依赖:

<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-sentinel -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    <version>2021.0.5.0</version>
</dependency>

注意没有配合nacos使用的话要在启动项上面加上访问的控制台地址,启动sentinel时要在java启动命令上加

java -Dserver.port=8131 -jar sentinel-dashboard-1.8.6.jar

整合包支持自动将所有的接口根据 ur 路径识别为资源。启动项目后,随便访问一个接口即可在控制台看效果

监听资源的几种方式

1.定义资源 代码自定义

通过代码定义资源更灵活

Entry entry = null;
// 务必保证finally会被执行
try {
  // 资源名可使用任意有业务语义的字符串
  entry = SphU.entry("自定义资源名");
  // 被保护的业务逻辑
  // do something...
} catch (BlockException e1) {
  // 资源访问阻止,被限流或被降级
  // 进行相应的处理操作
} finally {
  if (entry != null) {
    entry.exit();
  }
}

2.通过注解 


//listQuestionBankVOByPag控制台的资源名称
//handleBlockException 限流后走的方法名
//handleFallback 熔断后走的方法名称
@PostMapping("/list/page")
@SentinelResource(value = "listQuestionBankVOByPage",
                  blockHandler = "BlockException",
                  fallback = "Fallback")
public BaseResponse<Question> listQuestionBankVOByPage(
    @RequestBody Question question) {}


public BaseResponse<Question> BlockException(@RequestBody Questiont question) {
    // 限流操作
    return ;
}


public BaseResponse<Question> handleFallback(@RequestBody Question question,
                                                   Throwable ex) {
    // 可以返回本地数据或空数据
    return null;
}

@sentinelResource 注解的配置优先于自动识别的配置。这意味,如果注解中定义了特定的限流或熔断策略,这些策略将覆盖默认的或自动识别的配置。

推荐开发模式:优先使用适配包来自动识别资源,然后能运用注解尽量运用注解最后再选择主动编码定义资源。

定义规则

即限流规则 支持通过代码、控制台(推荐)、配置文件来定义规则。

  1. 代码定义限流规则
private static void initFlowQpsRule() {
    List<FlowRule> rules = new ArrayList<>();
    FlowRule rule1 = new FlowRule();
    rule1.setResource(resource);
    // Set max qps to 20
    rule1.setCount(20);
    rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
    rule1.setLimitApp("default");
    rules.add(rule1);
    FlowRuleManager.loadRules(rules);
}

2.通过控制台定义(推荐)

但通过控制台定义的规则,重启项目后就没了

一般推荐使用控制台来配置规则,但如果希望开发者更快启动和学习项目,可以通过编码定义规则,这样不用搭建控制台、而且每次启动项目都会确保规则被创建。

对某个接口进行限流或熔断

资源:listQuestion 接口

整个接口每秒钟不超过 10 次请求

熔断规则:

如果接口异常率超过 10%,或者慢调用(响应时长>3 秒)的比例大于 20%,触发 60 秒熔断

选择使用注解定义资源(即目标接口)+控制台定义规则

@SentinelResource使用注意事项annotation-support | Sentinel

给需要限流的接口添加@SentinelResource接口定义熔断限流后需要走的操作方法

启动项目,注意需加入JM 参数 -Dcsp.sentinel.dashboard.server=localhost:8131 指定控制台地址和端口。

启动项目后,随便访问个接口可在控制台看到自定义的资源名称即

3.添加规则:对要限流的接口新增限流

添加熔断

测试即可

对不同的IP限流或熔断

每个IP 地址每分钟允许调用的某个接口次数不能超过 60 次。

这是根据根据sentinel的热点限流机制实现的 详情参考:热点限流

何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:

  • 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
  • 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制

注意 ;可以先给要限流的接口使用代码定义出来限流规则和熔断规则 可以避免重新启动需要重新定义规则的问题。

/**
 * Sentinel 限流熔断规则管理器
 */
@Component
public class SentinelRulesManager {
    @PostConstruct
    public void initRules() throws Exception {
        initFlowRules();
       
    }
    /**
     * 初始化限流规则
     */
    public void initFlowRules() {
        // 单 IP 查看题目列表限流规则
        ParamFlowRule rule = new ParamFlowRule(SentinelConstant.listQuestionVOByPage)
        .setParamIdx(0) // 对第 0 个参数限流,即 IP 地址
        .setCount(5) // 每分钟最多 60 次
        .setDurationInSec(40); // 规则的统计周期为 60 秒
        ParamFlowRuleManager.loadRules(Collections.singletonList(rule));
    }
       
  }

而这里我们可以把ip地址作为参数进行统计,限制访问频率过高的即可

方法实现(主要代码)

/**
 * 分页获取题目列表(封装类 - 限流版)
 * @param questionQueryRequest
 * @param request
 * @return
 */
public BaseResponse<Page<QuestionVO>> listQuestionVOByPage(
   @RequestBody QuestionQueryRequest questionQueryRequest,
    HttpServletRequest request) {

    // 基于 IP 限流 从这开始基于ip限流
    String remoteAddr = request.getRemoteAddr();
    Entry entry = null;
    try {
        entry = SphU.entry(SentinelConstant.listQuestionVOByPage, EntryType.IN, 1, remoteAddr);
        // 被保护的业务逻辑
    
       
    } catch (Throwable ex) {
        // 业务异常
        if (!BlockException.isBlockException(ex)) {
            Tracer.trace(ex);
            return ;
        }
        // 降级操作
        if (ex instanceof DegradeException) {
            return handleFallback(questionQueryRequest, request, ex);
        }
        // 限流操作
        return ;
    } finally {
        if (entry != null) {
            entry.exit(1, remoteAddr);
        }
    }
}
/**
 * listQuestionVOByPageSentinel 降级操作:直接返回本地数据
 */
public BaseResponse<Page<QuestionVO>> handleFallback(@RequestBody QuestionQueryRequest questionQueryRequest,Throwable ex) {
    // 可以返回本地数据或空数据
    return ;
}

可以将Sentinel配置规则持续化到本地,这里不做赘述

具体事项方案可参考官方文档 introduction | Sentinel

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值