Zuul:构建高可用网关之多维度限流

  • 对请求的目标URL进行限流(例如:某个URL每分钟只允许调用多少次)
  • 对客户端的访问IP进行限流(例如:某个IP每分钟只允许请求多少次)
  • 对某些特定用户或者用户组进行限流(例如:非VIP用户限制每分钟只允许调用100次某个API等)
  • 多维度混合的限流。此时,就需要实现一些限流规则的编排机制。与、或、非等关系。

介绍

spring-cloud-zuul-ratelimit是和zuul整合提供分布式限流策略的扩展,只需在yaml中配置几行配置,就可使应用支持限流

<dependency>
    <groupId>com.marcosbarbero.cloud</groupId> <artifactId>spring-cloud-zuul-ratelimit</artifactId> <version>1.3.4.RELEASE</version> </dependency>

支持的限流粒度

  • 服务粒度 (默认配置,当前服务模块的限流控制)
  • 用户粒度 (详细说明,见文末总结)
  • ORIGIN粒度 (用户请求的origin作为粒度控制)
  • 接口粒度 (请求接口的地址作为粒度控制)
  • 以上粒度自由组合,又可以支持多种情况。
  • 如果还不够,自定义RateLimitKeyGenerator实现。
//默认实现
public String key(final HttpServletRequest request, final Route route, final RateLimitProperties.Policy policy) { final List<Type> types = policy.getType(); final StringJoiner joiner = new StringJoiner(":"); joiner.add(properties.getKeyPrefix()); if (route != null) { joiner.add(route.getId()); } if (!types.isEmpty()) { if (types.contains(Type.URL) && route != null) { joiner.add(route.getPath()); } if (types.contains(Type.ORIGIN)) { joiner.add(getRemoteAddr(request)); } // 这个结合文末总结。 if (types.contains(Type.USER)) { joiner.add(request.getUserPrincipal() != null ? request.getUserPrincipal().getName() : ANONYMOUS_USER); } } return joiner.toString(); }

支持的存储方式

image

  • InMemoryRateLimiter - 使用 ConcurrentHashMap作为数据存储
  • ConsulRateLimiter - 使用 Consul 作为数据存储
  • RedisRateLimiter - 使用 Redis 作为数据存储
  • SpringDataRateLimiter - 使用 数据库 作为数据存储

限流配置

  • limit 单位时间内允许访问的个数
  • quota 单位时间内允许访问的总时间(统计每次请求的时间综合)
  • refresh-interval 单位时间设置
zuul:
  ratelimit:
    key-prefix: your-prefix 
 enabled: true  repository: REDIS  behind-proxy: true  policies:  myServiceId:  limit: 10  quota: 20  refresh-interval: 30  type:  - user 

以上配置意思是:30秒内允许10个访问,并且要求总请求时间小于20秒

效果展示

yaml配置:

zuul:
  ratelimit:
    key-prefix: pig-ratelimite 
 enabled: true  repository: REDIS  behind-proxy: true  policies:  pig-admin-service:  limit: 2  quota: 1  refresh-interval: 3

动态图 ↓↓↓↓↓
image

Redis 中数据结构 注意红色字体
image

总结

  • 可以使用Spring Boot Actuator 提供的服务状态,动态设置限流开关
  • 源码可以参考:https://gitee.com/log4j/pig
  • 用户限流的实现:如果你的项目整合 Shiro 或者 Spring Security 安全框架,那么会自动维护request域UserPrincipal,如果是自己的框架,请登录成功后维护request域UserPrincipal,才能使用用户粒度的限流。未登录默认是:anonymous
**Resilience4j** 和 **Sentinel** 都是用于构建高可用微服务系统的工具,它们都支持限流、熔断等容错机制,但两者在设计理念、功能特性和适用场景上有明显差异。以下是它们在限流和熔断方面的详细对比: --- ### ✅ 一、基本介绍 | 对比项 | Resilience4j | Sentinel | |--------|--------------|----------| | 开发语言 | Java | Java/C++(核心为 Java) | | 出身 | 德国开发者社区 | 阿里巴巴开源项目 | | 支持框架 | Spring Boot、Micronaut、Vert.x 等 | Spring Cloud Alibaba、Dubbo、Zuul、Spring WebFlux 等 | | 是否中心化 | 否(纯客户端) | 是(可选中心化 Dashboard) | | 协议 | Apache License 2.0 | Apache License 2.0 | --- ### ✅ 二、限流能力对比 | 功能 | Resilience4j | Sentinel | |------|--------------|----------| | 限流算法 | 支持令牌桶、滑动窗口计数器 | 支持令牌桶、漏桶、滑动窗口、集群限流 | | 是否支持分布式限流 | ❌(需配合 Redis + Lua 或其他组件实现) | ✅(支持基于集群维度的限流) | | 是否支持 QPS 控制 | ✅(滑动窗口或固定窗口) | ✅(精确到每秒请求数) | | 是否支持热点参数限流 | ❌ | ✅ | | 是否支持运行时动态调整配置 | ❌(需重启或手动更新配置) | ✅(通过 Sentinel Dashboard 实时修改) | --- ### ✅ 三、熔断能力对比 | 功能 | Resilience4j | Sentinel | |------|--------------|----------| | 熔断策略 | 异常比例、响应时间 | 异常比例、异常数、慢调用比例 | | 熔断后恢复机制 | 自动恢复(基于时间窗口) | 自动恢复(基于熔断时长) | | 是否支持事件监听 | ✅(提供熔断状态变化监听) | ✅(可通过 EventObserver 注册监听) | | 是否支持多级熔断策略 | ❌ | ✅(如多个资源不同策略) | | 是否支持自动降级 | ❌(需结合 fallback 手动实现) | ✅(支持自定义 fallback 和 blockHandler) | --- ### ✅ 四、集成生态支持 | 对比项 | Resilience4j | Sentinel | |--------|--------------|----------| | Spring Boot 集成 | 原生支持,使用 `@CircuitBreaker`、`@RateLimiter` 等注解 | 需引入 `spring-cloud-starter-alibaba-sentinel` | | 可视化监控 | ❌(需自行接入 Micrometer 或 Prometheus) | ✅(提供 Sentinel Dashboard) | | 规则持久化 | ❌(默认内存存储) | ✅(支持 Nacos、Zookeeper、Apollo 持久化) | | 是否支持网关限流 | ❌(需自己封装) | ✅(支持 Zuul、Spring Gateway、Nginx 等) | --- ### ✅ 五、性能适用场景对比 | 场景 | 推荐方案 | |------|----------| | 单体应用、轻量级限流/熔断 | ✅ Resilience4j | | 多服务间复杂调用链、需要统一治理 | ✅ Sentinel | | 需要图形化界面管理规则 | ✅ Sentinel | | 需要实时动态配置变更 | ✅ Sentinel | | 使用 Spring WebFlux / Reactor 编程模型 | ✅ Resilience4j(原生支持 RxJava) | | 需要集群限流、热点限流 | ✅ Sentinel | --- ### ✅ 六、代码示例对比 #### 1. Resilience4j 示例(熔断) ```java CircuitBreakerRegistry registry = CircuitBreakerRegistry.ofDefaults(); CircuitBreaker circuitBreaker = registry.circuitBreaker("backendService"); Supplier<String> decoratedSupplier = CircuitBreaker.decorateSupplier(circuitBreaker, () -> { // 调用远程服务 return callRemoteService(); }); String result = Try.ofSupplier(decoratedSupplier).recover(throwable -> "fallback").get(); ``` #### 2. Sentinel 示例(限流+熔断) ```java try { Entry entry = SphU.entry("resourceName"); // 被保护的业务逻辑 doSomething(); entry.exit(); } catch (BlockException e) { // 限流或熔断触发逻辑 System.out.println("被限流或熔断了"); } finally { // 清理资源 } ``` --- ### ✅ 七、总结 | 维度 | Resilience4j | Sentinel | |------|--------------|----------| | 易用性 | 更加简洁,适合单体系统 | 功能强大但稍复杂 | | 可观测性 | 依赖外部监控系统 | 内置 Dashboard | | 分布式支持 | 不支持 | 支持集群限流、热点限流 | | 动态配置 | 不支持 | 支持(通过 Nacos 等) | | 社区活跃度 | 中等 | 非常活跃,文档丰富 | | 适用对象 | Spring Boot 单体或小型微服务 | 中大型微服务架构体系 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值