鍒嗗竷寮忛珮骞跺彂绯荤粺涓繚鎶ょ郴缁熷父鐢ㄧ殑涓夌宸ュ叿锛氱紦瀛樸€侀檷绾с€侀檺娴併€傛煇澶╂繁澶滐紝鍙戠幇鍏徃瀹℃牳鍚庡彴绯荤粺鏁版嵁搴揅PU鍗犵敤鐜囪揪鍒?6%浠ヤ笂銆傜粡杩囨帓鏌ワ紝鍙戠幇鏈変汉浣跨敤鑴氭湰鎭舵剰璁块棶鎴戜滑鐨勭郴缁熴€傛甯告儏鍐典笅璋冪敤娆℃暟鍦ㄦ瘡绉?娆″乏鍙筹紝浣嗘牴鎹洃鎺х郴缁熷彂鐜帮紝鎭舵剰璇锋眰鐨勬帴鍙f瘡绉掕皟鐢ㄦ鏁扮害涓?0娆★紝涓旇皟鐢ㄧ殑鎺ュ彛涓烘參閫熸帴鍙o紝瀵艰嚧CPU鍗犵敤椋欏崌銆備负浜嗕繚鎶ょ郴缁燂紝闄や簡缂撳瓨鍜岄檷绾т箣澶栵紝鎴戜滑閫氳繃闄愭祦鏉ラ檺鍒惰繖绉嶆伓鎰忚姹傦紝淇濊瘉姝e父鐢ㄦ埛鐨勪娇鐢紝鎶靛尽鎭舵剰璇锋眰銆傪煃撻檺娴佷粈涔堟槸闄愭祦锛熼檺娴佹槸闄愬埗鍒拌揪绯荤粺鐨勫苟鍙戣姹傛暟锛屼繚璇佺郴缁熷彲浠ユ甯稿搷搴旈儴鍒嗙敤鎴疯姹傦紝瀵逛簬瓒呰繃闄愬埗鐨勬祦閲忥紝閫氳繃鎷掔粷鏈嶅姟鏉ヤ繚璇佹暣涓郴缁熺殑鍙敤鎬с€傛寜闄愭祦鑼冨洿鍙垎涓哄崟鏈洪檺娴佸拰鍒嗗竷寮忛檺娴侊紱鎸夌収闄愭祦鏂瑰紡鍙互鍒嗕负璁℃暟鍣紝婊戝姩绐楀彛锛屾紡妗堕檺鍒朵护鐗屾《闄愭祦馃崁Counter璁℃暟鍣ㄦ槸鏈€绠€鍗曠殑闄愭祦绠楁硶锛屽師鐞嗘槸锛氬湪涓€娈垫椂闂村唴锛岀粺璁¤姹傛暟锛屾瘮杈冨垽鏂槸鍚﹂檺娴佺殑闃堝€硷紝涓€鏃﹁揪鍒版椂闂翠复鐣岀偣锛岃鏁板櫒娓呴浂銆傛瘮濡傞檺鍒跺湪1绉掑唴璇锋眰50娆°€傞檺娴侀€昏緫锛?.鍦ㄧ▼搴忎腑璁剧疆涓€涓彉閲廲ount銆傚綋鏈夎姹傚埌鏉ユ椂锛屾垜浼氬湪杩欎釜鏁板瓧涓婂姞1锛屽悓鏃惰褰曡姹傛椂闂淬€?銆佸綋涓嬩竴涓姹傚埌鏉ユ椂锛屽垽鏂璫ount鐨勮鏁板€兼槸鍚﹁秴杩囪瀹氶鐜?0锛屾湰娆¤姹傜殑鏃堕棿涓庣涓€娆¤姹傜殑鏃堕棿鏄惁鍦?绉掍互鍐呫€?銆佸鏋滃湪1绉掍互鍐咃紝瓒呰繃浜嗚缃殑棰戠巼锛岃瘉鏄庤姹傝繃澶氾紝鍚庣画鐨勮姹傚皢琚嫆缁濄€?.濡傛灉璇锋眰涓庣涓€娆¤姹傜殑闂撮殧澶т簬璁℃暟鍛ㄦ湡锛屼笖璁℃暟鍊间粛鍦ㄩ檺娴佽寖鍥村唴锛屽垯閲嶆柊璁℃暟銆備笉瓒筹細Borderlinecase澶勭悊锛屽亣璁剧敤鎴峰湪绗竴绉掔殑鏈€鍚庡嚑姣鍙戦€佷簡40涓姹傦紝褰?绉掑悗璁℃暟鍣ㄦ竻闆跺悗锛屼粬鍦ㄤ笅涓€绉掔殑鍓嶅嚑姣鍙堝彂閫佷簡40涓姹傘€傜浉褰撲簬杩炵画1绉掑彂閫?0澶氫釜璇锋眰锛屼絾鏄垜浠殑闄愭祦涓嶉檺銆傪煂规粦鍔ㄧ獥鍙f粦鍔ㄧ獥鍙f槸璁℃暟鍣ㄧ殑涓€涓复鐣岀偣缂洪櫡銆傛墍璋撴粦鍔ㄧ獥鍙o紙Slidingwindow锛夊氨鏄竴绉嶆祦閲忔帶鍒舵妧鏈€傝繖涓瘝鍑虹幇鍦═CP鍗忚涓€傛粦鍔ㄧ獥鍙e垝鍒嗗浐瀹氱殑鏃堕棿鐗囷紝闅忕潃鏃堕棿鐨勬帹绉昏€岀Щ鍔ㄣ€傜粺璁″浐瀹氭暟閲忕殑鍙互绉诲姩鐨勬牸瀛愶紝鍒ゆ柇闃堝€笺€傞檺娴侀€昏緫锛?銆佽鏁板櫒鍏跺疄鏄竴涓粦鍔ㄧ獥鍙o紝鍙槸鍙湁涓€涓猵ane銆?銆佷负浜嗚闄愭祦鏇村噯纭紝鎴戜滑鍙渶瑕佸垝鍒嗘洿澶氱殑绐楁牸鍗冲彲銆備负浜嗘洿绮剧‘锛屾垜浠笉鐭ラ亾搴旇璁剧疆澶氬皯涓獥鏍笺€?.鏍煎瓙鐨勫灏戝奖鍝嶄簡婊戝姩绐楀彛绠楁硶鐨勭簿搴︼紝杩樻湁鏃堕棿鐗囩殑姒傚康锛屼笉鑳戒粠鏍规湰涓婅В鍐充复鐣岀偣闂銆備笉瓒筹細涓嶈兘浠庢牴鏈笂瑙e喅涓寸晫鐐归棶棰樸€傪煂兼紡妗剁畻娉曪紙LeakyBucket锛夛紝鍘熺悊鏄竴涓浐瀹氬閲忕殑婕忔《锛屼互鍥哄畾鐨勯€熺巼娴佸嚭姘存淮銆傜敤杩囨按榫欏ご鐨勪汉閮界煡閬擄紝姘撮緳澶翠竴寮€涓€鍏筹紝姘村氨浼氬線涓嬫祦锛屾淮鍒版按妗堕噷锛屾紡姘存《灏辨槸姘存《涓嬮潰鏈夋紡姘达紝璁╂按娴佸嚭鏉ャ€傚鏋滄按榫欏ご寮€寰楀お澶э紝姘寸殑娴侀噺灏变細澶ぇ锛岃繖鍙兘浼氬鑷存按妗惰婊℃按锛岀劧鍚庢孩鍑恒€傛紡妗剁畻娉曟湁浠ヤ笅鐗圭偣锛?.婕忔《鏈夊浐瀹氱殑瀹归噺锛屽嚭姘寸巼鏄竴涓浐瀹氱殑甯告暟锛堟祦鍑鸿姹傦級2.濡傛灉妗舵槸绌虹殑锛屾病鏈夋按婊撮渶瑕佹祦鍑?.姘存按婊村彲浠ヤ互浠绘剰閫熺巼娴佸叆婕忔《锛圛nflowrequest锛?.濡傛灉娴佸叆鐨勬按婊磋秴杩囨《鐨勫閲忥紝鍒欐祦鍏ョ殑姘存淮婧㈠嚭锛堟嫆缁濇柊鐨勮姹傦級涓嶈冻锛氭紡妗堕檺鍒朵笉鏂祦鍑洪€熺巼锛堝嵆娴佸嚭閫熺巼鏄竴涓浐瀹氱殑甯告暟鍊硷級锛屾墍浠ユ渶澶ч€熺巼灏辨槸鍑烘按閫熺巼锛屼笉浼氬嚭鐜扮獊娴併€傪煂讳护鐗屾《浠ょ墝妗剁畻娉曪紙TokenBucket锛夋槸缃戠粶娴侀噺鏁村舰锛圱rafficShaping锛夊拰閫熺巼闄愬埗锛圧ateLimiting锛変腑鏈€甯哥敤鐨勭畻娉曘€傞€氬父锛屼护鐗屾《绠楁硶鐢ㄤ簬鎺у埗鍙戦€佸埌缃戠粶鐨勬暟鎹噺骞跺厑璁稿彂閫佺獊鍙戞暟鎹€傛紡妗剁畻娉曞叿鏈変互涓嬬壒鐐癸細1.浠ょ墝浠ュ浐瀹氶€熺巼鏀惧叆浠ょ墝妗?.妗朵腑鏈€澶氬瓨鍌˙涓护鐗屻€傚綋妗舵弧鏃讹紝鏂板姞鍏ョ殑浠ょ墝琚涪寮冩垨鎷掔粷3.濡傛灉妗朵腑浠ょ墝灏戜簬N涓紝浠ょ墝涓嶄細琚垹闄わ紝璇锋眰灏嗚鑺傛祦锛堜涪寮冩垨闃诲绛夊緟锛夈€傛垜浠湁涓€涓浐瀹氱殑妗讹紝妗朵腑瀛樻斁鐫€浠ょ墝锛坱oken锛夈€傚紑濮嬫椂妗舵槸绌虹殑锛岀郴缁熸寜鐓у浐瀹氱殑鏃堕棿锛堥€熺巼锛夊悜妗朵腑娣诲姞浠ょ墝锛岀洿鍒版《涓殑浠ょ墝鏁伴噺婊′簡锛屽浣欑殑璇锋眰灏嗚涓㈠純銆傚綋涓€涓姹傝繘鏉ユ椂锛屼粠妗朵腑绉婚櫎涓€涓护鐗岋紝鎷掔粷璇锋眰鎴栬€呭鏋滄《鏄┖鐨勫垯闃诲銆傚厑璁镐竴瀹氱▼搴︾殑绐佸彂娴侀噺鏄瘮杈冨ソ鐨勯檺娴佺畻娉曫煃婁笂闈粙缁嶄簡闄愭祦绠楁硶鐨勫疄鐜帮紝涓嬮潰浠嬬粛鍑犵甯歌鐨勯檺娴佺畻娉曠殑浣跨敤馃崌鍩轰簬Redis鐨勮鏁板櫒闄愭祦瀹氫箟闄愭祦娉ㄨВ@Inherited@Documented@Target({ElementType.FIELD,ElementType.TYPE,ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public@interfaceAccessLimit{/***鎸囧畾鏃堕棿鑼冨洿鍐呯殑璇锋眰娆℃暟*/intmaxCount()榛樿50锛?***RequestNumberofsecondsinthespecifiedtimerangeoftimes(redisdataexpirationtime)*/intsecond()default1;}闄愭祦鏂归潰@Slf4j@Aspect@ComponentpublicclassAccessLimitAspect{@ApolloJsonValue("${app.service.limit.teacherId:[]}")privateListteacherIds;@AutowiredprivateRedissonClientredissonClient;@Autowired绉佷汉HttpServletRequesthttpServletRequest;@SneakyThrows@Around("@annotation(accessLimit)")publicObjectdoLimit(ProceedingJoinPointproceedingJoinPoint,AccessmitployString=emmitployString){httpServletRequest.getHeader("employeeId");log.info("employeeId:{}",employeeId);鏂█.notNull(employeeId,"employeeId涓嶈兘涓虹┖锛?);if(teacherIds.contains(employeeId)){log.info("璇锋眰闄愬埗寮€濮?employeeId{}",employeeId);//鑾峰彇娉ㄨВ鍐呭淇℃伅intseconds=accessLimit.second();intmaxCount=accessLimit.maxCount();//瀛樺偍閿甋tringkey=employeeId;//璁块棶娆℃暟Integercount=redissonClient.get(key);log.info("璁块棶娆℃暟锛歿}",count);if(null==count||-1==count){redissonClient.set(key,1,seconds,TimeUnit.SECONDS);}if(count=maxCount){log.warn("璇锋眰杩囦簬棰戠箒锛岃绋嶅悗鍐嶈瘯");杩斿洖绌哄€硷紱}log.info("璇锋眰闄愰缁撴潫锛宔mployeeId{}",employeeId);}杩斿洖缁х画ingJoinPoint.proceed();}}馃崓鍩轰簬redis鐨勫懡浠ゆ爤闄愬埗娴佸畾涔夋潈闄愭敞瑙Inherited@Documented@Target({ElementType.FIELD,ElementType.TYPE,ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public@interfaceAccessLimit{}闄愬埗娴佸垏闈Slf4j@Aspect@ComponentpublicclassAccessLimitAspect{@ApolloJsonValue("${app.service.limit.teacherId:[]}")privateListteacherIds;@AutowiredprivateRedissonClientredissonClient;@Autowired绉佷汉HttpServletRequesthttpServletRequest;@SneakyThrows@Around("@annotation(accessLimit)")publicObjectdoLimit(ProceedingJoinPointproceedingJoinPoint,AccessLimitaccessLimit){StringemployeeId=httpServletRequest.getHeader("employeeId");log.info("employeeId锛歿}",employeeId);Assert.notNull(employeeId,"employeeId涓嶈兘涓虹┖锛?);if(teacherIds.contains(employeeId)){log.info("璇锋眰闄愬埗寮€濮?employeeId{}",employeeId);//浣跨敤redisson闄愭祦鍣ㄩ檺鍒舵瘡绉?0涓姹俁RateLimiterlimiter=redissonClient.getRateLimiter("limit_teacher");limiter.trySetRate(RateType.OVERALL,50,1,RateIntervalUnit.SECONDS);limiter.acquire();log.info("requestlimitend,employeeId{}",employeeId);}returnproceedingJoinPoint.proceed();}@Around("@within(cn.tinman.clouds.jojoread.admin.limit.AccessLimit)")publicObjectlimit(ProceedingJoinPointjoinPoint){MethodSignaturesignature=(MethodSignature)joinPoint.getSignature();//鏂规硶涓婄殑闄嶇骇娉ㄨВ浼樺厛浜庣被涓婄殑AccessLimitlimit=AnnotationUtils.findAnnotation(signature.getMethod(),AccessLimit.class);if(Objects.isNull(limit)){limit=AnnotationUtils.findAnnotation(joinPoint.getTarget().getClass(),AccessLimit.class);}Assert.notNull(limit,"@AccessLimit蹇呴』涓嶆槸benull!");returndoLimit(joinPoint,limit);}}馃崚鍩轰簬Guava鐨勪护鐗屾《闄愭祦锛堝崟鏈猴級锛岄檺鍒禥PS涓?锛屽嵆姣?00ms浜х敓涓€涓猼okenRateLimiterrateLimiter=RateLimiter.create(2);for(inti=0;i<10;i++){Stringtime=LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_TIME);System.out.println(time+":"+rateLimiter.tryAcquire());Thread.sleep(250);}绋嬪簭姣?50姣鑾峰彇涓€娆′护鐗岋紝鍥犳涓ゆ鑾峰彇涓彧鏈変竴娆℃垚鍔?8:19:06.797557:true18:19:07.061419:false18:19:07.316283:true18:19:07.566746:false18:19:07.817035:true18:19:08.072483:false馃嵃闄愭祦涓昏搴旂敤鍦烘櫙鎬荤粨涓猴細鐢靛晢绯荤粺绉掓潃娲诲姩锛堢壒鍒槸6.18銆佸弻11銆佸弻12绛夛級锛屼娇鐢ㄩ檺娴侀槻姝娇鐢ㄦ伓鎰忚蒋浠跺埛鍗曪紱鍩虹api鎺ュ彛闄愭祦锛氭瘮濡傚ぉ姘斾俊鎭幏鍙栵紝IP瀵瑰簲鍩庡競鎺ュ彛锛岀櫨搴︺€佽吘璁瓑鎻愪緵鐨勫熀纭€鎺ュ彛锛岄兘鏄€氳繃闄愭祦瀹炵幇涔嬮棿鐨勭洿鎺ヨ浆鎹㈠厤璐瑰拰浠樿垂銆傜郴缁熷箍娉涜皟鐢ㄧ殑api鎺ュ彛锛岀綉缁溿€佸唴瀛樼瓑璧勬簮娑堣€椾弗閲嶏紝闇€瑕佸悎鐞嗛檺娴併€傞櫎浜嗗鏈嶅姟鍣ㄨ繘琛岄檺娴侊紝鎴戜滑杩樺彲浠ュ瀹瑰櫒杩涜闄愭祦锛屾瘮濡俆omcat銆丯ginx绛夐檺娴佹墜娈点€俆omcat鍙互璁剧疆鏈€澶х嚎绋嬫暟锛坢axThreads锛夛紝褰撳苟鍙戣秴杩囨渶澶х嚎绋嬫暟鏃朵細鎺掗槦绛夊緟鎵ц锛汵ginx鎻愪緵浜嗕袱绉嶉檺娴佹柟寮忥細涓€绉嶆槸鎺у埗閫熺巼锛屼竴绉嶆槸鎺у埗骞跺彂杩炴帴鏁般€傞檺娴佺畻娉時edis瀹炵幇闄愭祦guava鐨勪护鐗屾《闄愭祦