当前位置: 首页 > 后端技术 > Java

Sentinel滑窗限流算法

时间:2023-04-01 14:23:11 Java

研究sentinel实现的核心算法com.alibaba.cspsentinel-core1.8。3官方说明Listrules=newArrayList<>();FlowRulerule=newFlowRule();rule.setResource("HelloWorld");//设置限制qps为20rule。setCount(20);rule.setGrade(RuleConstant.FLOW_GRADE_QPS);rules.add(rule);FlowRuleManager.loadRules(rules);try(Entryentry=SphU.entry("HelloWorld")){//你的业务逻辑在这里。System.out.println("helloworld");}catch(BlockExceptione){//处理被拒绝的请求。e.printStackTrace();}//try-with-resourcesautoexit为了看核心实现,也为了更直观的理解,这里我们将一秒分为两个窗口,即每个窗口的slidingWindowSize为500,对源码做了一些增删改查:privatestaticlongslidingWindowSize=500L;privateAtomicReferenceArray数组=newAtomicReferenceArray<项目>(2);privateReentrantLocklock=newReentrantLock();私人长许可每秒;//设置每秒允许的qps入口方法publicbooleanentry(){try{longcurrentTimeMillis=System.currentTimeMillis();intindex=findSlidingWindowIndex(currentTimeMillis);longslidingWindowStart=findSlidingWindowStart(currentTimeMillis);Itemitem=currentItem(index,slidingWindowStart);如果(项目==空){返回真;}if(accumulatedPassQps(1-index,item)>permitsPerSecond){returnfalse;}item.passIncrement();返回真;}catch(Exceptionex){返回真;}}累计已经通过的qpsprivatelongaccumulatedPassQps(intindex,Itemitem){Itemother=array.get(index);if(other==null||(Math.abs(other.getSlidingWindowStart()-item.getSlidingWindowStart())>slidingWindowSize)){returnitem.passValue();}返回other.passValue()+item.passValue();}当前是哪个时间窗口privateItemcurrentItem(intindex,longslidingWindowStart){while(true){Itemprevious=array.get(index);if(previous==null){Itemitem=newItem(slidingWindowStart);如果(array.compareAndSet(index,null,item)){返回项目;}else{Thread.yield();}}elseif(slidingWindowStart==previous.getSlidingWindowStart()){returnprevious;}elseif(slidingWindowStart>previous.getSlidingWindowStart()){if(lock.tryLock()){try{returnprevious.reset(slidingWindowStart);}最后{lock.unlock();}}else{Thread.yield();}}else{返回空值;}}}privatelongfindSlidingWindowStart(longtimeMillis){returntimeMillis-timeMillis%slidingWindowSize;}privateintfindSlidingWindowIndex(longtimeMillis){return(int)((timeMillis/slidingWindowSize)%2);}Item封装的内容privatelongslidingWindowStart;私人LongAdderaccu;publicItemreset(longslidingWindowStart){this.slidingWindowStart=slidingWindowStart;精确重置();归还这个;}publiclongpassValue(){returnaccu.sum();}publicvoidpassIncrement(){accu.increment();}publiclonggetSlidingWindowStart(){returnslidingWindowStart;}