redisson的rratelimiter防恶意穿透需满足三要素:一是在鉴权后、业务前统一拦截(如handlerinterceptor)调用tryacquire();二是使用ratetype.per_client并动态构造含用户标识的name(如"user_rate_limiter:"+userid);三是规避redis故障时默认返回true的陷阱,须加连接状态校验或降级开关。

Redisson 的 RRateLimiter 能有效防恶意穿透,但前提是它被正确初始化、参数设对、且调用时机不绕过限流逻辑。 直接在 Controller 层用 tryAcquire() 是最常见却最容易失效的用法——攻击者只要跳过该层(比如直连服务内部 RPC、伪造 token 绕过网关鉴权),限流就形同虚设。
为什么 tryAcquire() 放在业务入口前才真正防穿透
恶意穿透的本质是绕过常规请求路径。比如:攻击者不走 API 网关,而是通过内网调用下游服务;或利用未鉴权的健康检查端点批量刷接口。此时限流若只挂在某个 HTTP 接口上,等于守门人只站在正门,后窗大开。
- 必须把
RRateLimiter.tryAcquire()放在**认证鉴权之后、业务逻辑执行之前**的统一拦截点,例如 Spring 的HandlerInterceptor.preHandle()或自定义注解切面 - 如果用网关限流(如 Spring Cloud Gateway + Redis),要确保所有流量(含内部服务间调用)都强制经过网关——这在微服务中往往不现实
- 避免在 Service 层多个地方分散调用
tryAcquire(),否则容易漏掉分支路径,也难统一管理策略
RateType.PER_CLIENT 是防单用户刷的关键配置
全局限流(RateType.OVERALL)适合保护系统总容量,但对“某用户疯狂调用同一接口”无能为力。防穿透必须绑定真实身份维度,否则 IP 可伪造、token 可复用、设备 ID 可模拟。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 用
RateType.PER_CLIENT时,RRateLimiter内部会自动将客户端标识(如userId、appId)拼入 Redis Key,实现隔离计数 - 务必确保传入
getRateLimiter(String name)的name包含可区分主体的变量,例如"user_rate_limiter:" + userId,而不是写死的字符串 - 注意:如果业务用 JWT,且未在解析后校验签名有效性,攻击者可篡改 payload 中的
userId字段来绕过限流
令牌桶参数设置不当会导致误杀或放行
trySetRate(RateType, rate, rateInterval, RateIntervalUnit) 这四个参数共同决定防御粒度。设得太松,刷子照常跑;设得太紧,正常用户点两下就触发限流。
-
rate=100、rateInterval=1、RateIntervalUnit.SECONDS表示每秒最多 100 次——这对登录接口就是灾难,但对消息推送可能太保守 - 突发流量容忍靠的是令牌桶“容量”,即第二个参数
rate实际代表桶大小(不是速率)。Redisson 文档里没明说,但源码中trySetRate的rate参数同时控制生成速率和桶初始容量 - 时间单位选错会差 60 倍:用
RateIntervalUnit.MINUTES却填rateInterval=1,等效于每分钟 1 次,不是每秒 1 次
Redis 连接异常时 tryAcquire() 默认返回 true
这是生产环境最隐蔽的坑:RRateLimiter.tryAcquire() 在 Redis 不可用、超时、连接池耗尽时,不会抛异常,而是静默返回 true ——相当于限流器自动熔断,完全失效。
- 必须主动包装一层 fallback:先判断
redissonClient.isShutdown()或监听连接状态,再决定是否放行 - 更稳妥的做法是加降级开关,例如配置中心下发
rate.limiter.enabled=false,让限流器退化为 NOP 实现 - 不要依赖
tryAcquire(1, timeout, unit)的超时参数来兜底——它只控制等待获取令牌的时间,不解决 Redis 故障场景
真正防穿透不是加一个限流组件就完事,而是要把限流嵌进请求生命周期里最不可绕过的环节,并确保每个参数都在业务语义上站得住脚。Redisson 做对了原子性和集群适配,但怎么用、在哪用、用对没用,全看你怎么把它钉进系统骨架里。










