현재 제한의 목적은 동시 액세스/요청 속도를 제한하거나 시간 창 내에서 요청 속도를 제한하여 시스템을 보호하는 것입니다. 제한 속도에 도달하면 서비스가 거부 될 수 있습니다.
며칠 전, 나는 단일 응용 프로그램 스트림 제한을 달성하기 위해 Guawa를 사용하려는 계획을 읽었습니다. "Redis in Action"을 참조하여 제다이 버전을 구현하려면 모두 비즈니스 수준의 제한입니다. 실제 시나리오에서 일반적인 현재 제한 전략 :
NGINX 액세스 계층 전류 제한
계정 번호, IP, 시스템 통화 로직 등과 같은 특정 규칙에 따라 Nginx 레벨에서 전류를 제한합니다.
비즈니스 애플리케이션 시스템 현재 한도
비즈니스 코드를 통한 트래픽 제어이 트래픽은 세마포어라고 할 수 있으며,이 트래픽은 자물쇠로 이해 될 수 있으며, 이는 자원이 동시에 액세스 할 수있는 프로세스 수를 제한 할 수 있습니다.
코드 구현
import redis.clients.jedis.jedis; import redis.clients.jedis.jedis.transaction; import redis.clients.jedis.zparams; import java.util.list; import java.util.uuid;/** * @email [email protected] * @data 2017-08 */public classe rediStatic {private static {private static redatic redatic redatic redatic redatic redatic redatic redatic redatic redatic redatic redatic redatic redatic redatic strate "버킷"; 개인 정적 최종 문자열 Bucet_Count = "Bucket_Count"; 개인 정적 최종 문자열 Bucet_Monitor = "Buct_Monitor"; 정적 문자열 arquireTokenFrombucket (Jedis Jedis, int Limit, Long Timeout) {String 식별자 = uuid.randomuuid (). toString (); long now = System.CurrentTimeMillis (); 거래 거래 = jedis.multi (); // semaphore transaction.zremrangebyscore (bucet_monitor.getBytes (), "-inf".getBytes (), string.valueof (now -timeout) .getBytes ()); zparams params = new zparams (); params.weightSbyDouble (1.0,0.0); transaction.zinterstore (버킷, 매개 변수, 버킷, 버킷 _monitor); // 카운터 자체 증가 트랜잭션 .incr (buct_count); List <Object> results = transaction.exec (); 긴 카운터 = (long) results.get (results.size () -1); 트랜잭션 = jedis.multi (); transaction.zadd (bucet_monitor, 지금, 식별자); transaction.zadd (버킷, 카운터, 식별자); Transaction.zrank (버킷, 식별자); 결과 = transaction.exec (); // 요청이 세마포어 긴 순위를 얻었는지 여부를 결정하기 위해 순위를 얻습니다. if (rank <limit) {return Identifier; } else {// 세마포어가 얻어지지 않았으며, 거래를 청소하기 전에 Redis에 넣습니다 = jedis.multi (); transaction.zrem (Bucet_Monitor, 식별자); transaction.zrem (버킷, 식별자); transaction.exec (); } return null; }}
부르다
테스트 인터페이스 호출
@GetMapping ( "/") public void index (httpservletresponse 응답) IoException {jedis jedis = jedispool.getResource (); 문자열 토큰 = redisratelimiter.acquiretokenfrombucket (Jedis, Limit, TimeOut); if (token == null) {response.senderror (500); } else {// 비즈니스 로직을 할 예정} jedispool.returnresource (jedis);}최적화
인터셉터 + 주석으로 코드를 최적화하십시오
인터셉터
@ConfigurationStatic 클래스 WebMvcConfigurer 확장 webmvcconfigureradapter {private logger = loggerfactory.getLogger (webmvcconfigurer.class); @autowired Private Jedispool Jedispool; public void addinterceptors (interceptorregistry registry) {registry.addinterceptor (new handlerinterceptoradapter () {public boolean prehandle (httpservletrequest request, httpservletreponse 응답, 객체 핸들러) 예외 {핸드 메드 핸드 맨드 (handlermethod); Ratelimiter = method.getAntation (ratelimiter.class) {int limit = ratelimit.limit.timeout.timeout (); 타임 아웃); }}정의 주석
/** * @Email [email protected] * @Data 2017-08 * 현재 한도 주석 */@target (eleMentType.Method) @retention (retentionpolicy.runtime) @documentedPublic @interface ratelimiter {int limit () 기본값 5; int timeout () 기본 1000;}
사용
@ratelimiter (Limit = 2, TimeOut = 5000) @GetMapping ( "/test") public void test () {}동시 테스트
도구 : Apache-Jmeter-3.2
참고 : 세마포어 리턴 500, 상태는 빨간색이며 세마포어 리턴 200을 얻은 인터페이스, 상태는 녹색입니다.
제한 요청 세마포어가 2 인 경우 5 개의 스레드가 전송됩니다.
제한 요청 세마포어가 5 인 경우 10 개의 스레드가 전송됩니다.
재료
Reids + Lua를 기반으로 한 구현
요약
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.