현재 리미터 알고리즘
현재 Token Bucket Algorithm과 Leaky Bucket Algorithm의 두 가지 일반적인 전류 리미터 알고리즘이 있습니다. 주요 차이점은 누출 된 버킷 알고리즘이 요청 속도와 부드러운 버스트 요청을 강제로 제한 할 수 있다는 것입니다. 토큰 버킷 알고리즘은 평균 속도를 제한 할 때 일정량의 버스트 요청을 허용합니다.
다음은 인터넷에서 발견 된 두 가지 알고리즘 다이어그램이며,이 두 알고리즘의 특성과 쉽게 구별 할 수 있습니다.
누출 버킷 알고리즘
토큰 버킷 알고리즘
인터페이스의 경우 특정 수의 버스트 요청이 일반적으로 처리 될 수 있으며 평균 속도 만 제한하려면 토큰 버킷 알고리즘이 더 일반적입니다.
토큰 버킷 알고리즘 도구 ratelimiter
가장 일반적으로 사용하는 토큰 버킷 알고리즘 구현 클래스는 Google Guava의 Ratelimiter입니다. Guava는 토큰 버킷 알고리즘뿐만 아니라 캐시, 새로운 컬렉션 클래스, 동시 공구 클래스, 문자열 처리 클래스 등을 구현합니다. 강력한 도구 세트입니다.
Ratelimiter API는 동시 프로그래밍 네트워크에서 Guava Ratelimiter의 도입을 볼 수 있습니다.
Ratelimiter 소스 코드 분석
기본적으로 Ratelimiter의 가장 핵심 속성은 2 개의 NextFreeticketMicros입니다. 다음 번에는 토큰 시간을 얻을 수 있으며 StoredPermits 버킷의 토큰 수를 얻을 수 있습니다.
토큰을 얻는 지 결정 :
토큰을 얻을 때마다 버킷의 토큰 수에 따라 다음 번에 토큰을 얻기 위해 가장 빠른 시간을 계산하십시오. 자원을 얻을 수 있는지 여부를 결정할 때는 NextFreeticketMicros를 현재 시간과 비교하십시오.
토큰 작동 :
토큰을 얻으려면 NextFreeticketMicros와 현재 시간을 기반으로 새로운 토큰의 수를 계산하고 현재 토큰 버킷 토큰 번호를 작성하고 NextFreeticketMicros를 다시 계산하십시오. 버킷에 토큰이있는 경우 현재 시간을 작성 하고이 요청에 의해 얻은 토큰 수를 줄입니다.
Java의 AQS 클래스와 마찬가지로 Ratelimiter의 핵심은 Tryacquire 방법입니다.
Public Boolean TryAcquire (int remits, long timeout, timeUnit init) {// 최대 대기 시간을 얻으려고 노력합니다. 긴 시간 초과 시간을 얻으십시오. // 얻은 리소스 수가 올바른 checkPermits (허가)인지 확인합니다. 긴 소도로; // 잠금 동기화 (mutex ()) {// 현재 시간 긴 nowmicros = stopwatch.readmicros (); // 시간 초과 시간 내에 리소스를 얻을 수 있는지 판단합니다. } else {// 리소스를 얻고, 자원을 다시 계산하고, 현재 스레드 microstowait = randinggetwaitlength (허가, nowmicros)에 필요한 수면 시간을 반환 할 수 있습니다. }} // Sleep STOPWATCH.SLEEFMICROSUNINGURPRUBTILY (Microstowait); 진실을 반환하십시오. }토큰을 얻는 지 결정 :
Private Boolean Canacquire (Long Nowmicros, 긴 시간 초
Ratelimiter 기본 구현 클래스 QueryEarliestavailable
토큰을 받고 필요한 대기 시간 조작을 계산하십시오.
최종 Long RemandgetWaitlength (int remits, long nowmicros) {// 다음에 긴 MomentAvailable = ReserveArearliestAvailable (허가, Nowmicros)을 얻을 시간을 얻습니다. // 현재 스레드가 MAX를 반환하는 데 필요한 수면 시간을 계산합니다 (MomentAvailable -Nowmicros, 0);} 최종 Long ReserveArearliestAvailable (int requestmits, long nowmicros) {// 버킷 저장소의 토큰 수를 다시 계산합니다 (nowmicros). 긴 returnValue = NextFreeticketMicros; // 이번에 소비 된 토큰의 수 Double StoredPermitStospend = min (requiremits, this.StordPermits); // 다음 번에 얻을 시간을 다시 계산하십시오. NextFreeticketMicros Double FreshPermits = EmplingPermits- StoredPermitStend; Long WaitMicros = StoredPermitStowaitTime (this.StordPermits, StoredPermitStospend) + (Long) (FreshPermits * stableInterValmicros); this.nextfreeticketmicros = longmath.saturatedAdd (NextFreeticketMicros, Waitmicros); // 버킷의 토큰 수를 줄입니다. return returnValue; }간단한 스프링 MVC 전류 제한 인터셉터를 구현하십시오
핸들러 인터셉터 구현, 생성자에서 ratelimiter current limiter를 만듭니다.
public simpleratelimitinterceptor (int rate) {if (rate> 0) globalratelimiter = ratelimiter.create (rate); 그렇지 않으면 새로운 runtimeexception을 던지십시오 ( "속도는 0보다 클수록");}한계 속도가 초과했는지 여부를 결정하려면 전류 제한기의 TryAcquire 메소드를 호출하십시오.
public boolean prehandle (httpservletrequest request, httpservletreponse 응답, 객체 핸들러)은 예외를 {if (! globalRatelimiter.tryacquire ()) {loggerutil.log (request.getRequesturi ()+"요청을 초과합니다"); 거짓을 반환합니다. } true를 반환합니다. }Dispatcher-Servlet.xml에서 현재 한계 인터셉터를 구성하십시오
<mvc : interceptors> <!-전류 한계 인터셉터-> <mvc : interceptor> <mvc : 매핑 경로 = "/**"/> <bean> <생성자-아그 인덱스 = "0"value = "$ {totalrate}"/> </bean> </mvc : interceptor> </mvc : intercepsors>스프링 MVC의 복잡한 버전 전류 제한 인터셉터
속성을 사용하여 인터셉트 된 URL 표현식 -> 속도 속도로 전달합니다.
<mvc : interceptor> <mvc : 매핑 경로 = "/**"/> <ean> <!-단일 URL 전류 제한-> <속성 이름 = "urlproperties"> <props> <prop key = "/get/{id}"> 1 </prop> <prop key = "/post"> 2 </prop> </propps> </bean> 각 URL 표현식에 대해 해당 ratelimiter current Limiter를 만듭니다. URL 표현식은 org.springframework.web.servlet.mvc.condition.patternsrequestCondition으로 캡슐화됩니다. PatternSrequestCondition은 SpringMVC의 Dispatcherservlet에서 요청 및 컨트롤러와 일치하는 클래스입니다. 요청이 이러한 URL 표현식을 준수하는지 여부를 결정할 수 있습니다.
인터셉터 프리 핸들 방법에서
// 현재 요청 경로 String LookUpPath = urlPathHelper.getLookUpPathForRequest (request); // 모든 URL 표현식에 해당하는 PatternSrequestCondition (PatternSrequestCondition PatternSrequestCondition : urlratemap.keyset ()) {string> 일치하는 <string> PattersSrequestCondition.getMatchingPatterns (LookUpPath); if (! matches.isempty ()) {// 일치가 성공하면 해당 전류 리미터의 토큰을 가져옵니다. if (urlratemap.get (patternsRequestCondition) .tryAcquire ()) {loggerutil.log (lookuppath + "requested tw" + joiner.on ( ").). 리미터 "); } else {// Token loggerutil.log를 얻지 못했습니다 (LookupPath + "요청은" + joiner.on ( ",")을 초과합니다 (PatternSrequestCondition.getPatterns ()) + "현재 리미터 속도"); 거짓을 반환합니다. }}}특정 구현 클래스
Github를 참조하십시오
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.