问题描述
前置模块接收h5请求以及Netty接收socket请求,此时使用Sentinel进行限流,但是限流失效,失效原因是每个接口类中都声明了FlowRule进行降级规则的注册,意味着不同的类在通过loadRules后会进行覆盖更新,导致先加载的限流规则失效,解决办法则是将其抽象为配置类
为什么要使用sentinel限流?
netty中设置workNThreads不足以成为限流数
在Netty框架中,设置workNThreads(即工作线程数量)实际上是配置了EventLoopGroup中的线程数,这决定了Netty可以同时处理多少并发的网络连接。从某种程度上讲,它能够对系统负载有所限制,因为线程数量限制了可以同时执行的任务数量。
然而,将workNThreads作为限流措施是一种非常粗粒度和间接的手段,它并没有直接控制流量本身,而是限制了处理能力。在很多情况下,这不足以作为一个有效的限流策略,因为其它系统资源(如CPU、内存和IO)可能会在达到线程限制之前就已经达到瓶颈。
限流通常指的是通过某种形式控制数据流的速率,以避免过载服务提供者。这通常通过算法实现,如令牌桶或漏桶算法,有时也可以使用队列理论中的模型来平滑流量峰值。限流策略的目的是在保持服务质量的同时,减少对系统资源的请求以防止系统过载。
在使用Netty开发高性能网络应用程序时,实现有效的限流机制通常需要集成类似Sentinel这样的流量控制库,或者自行实现限流逻辑。这些工具和逻辑可以更细粒度地控制到单个请求的处理速率,或是总体的入站连接速率,而不仅仅是通过工作线程的数量来间接控制。
在Netty中调整workNThreads的数量限制了并发处理的能力,它可能对系统的整体负载有一定限制作用,但并不是一个专门为限流设计的机制。使用专业的限流工具或算法可以更加有效和精确地控制流量,而不是仅仅依赖于工作线程数的配置。
限流失效原因
前置模块负责接收h5请求和socket请求,收到请求后做转发处理,调用处理模块进行数据处理;
在前置模块中每个接口类中使用sentinel进行降级处理
每个接口类中都声明了FlowRule进行降级规则的注册
if(rules.size()>0){
FlowRuleManager.loadRules(rules);
}
该方法是更新并非新增,意味着不同的类在通过loadRules后会进行覆盖更新,导致先加载的限流规则失效
解决
统一模块中所有的sentinel限流配置,将其抽象为一个配置类,方便扩展
@Configuration
public class SentinelConfig implements InitializingBean{
@Value("${sentinel.query:30}")
private int queryCount;
@Override
public void afterPropertiesSet() throws Exception{
List<FlowRule> rules = new ArrayList<FlowRule>();
if(queryCount>0){
FlowRule rule = new FlowRule();
rule.setResource(SentinelSourceKey.QUERY.name());//资源类型
rule.setCount(queryCount);
rule.setGrade(RuleConstant.FLOW_GRADE_THREAD);
rule.setControlBehavior(0);
rules.add(rule);
}
//....
if(rules.size>0){
FlowRuleManager.loadRules(rules);
}
}
}