Redisベースの分散型ストリーム制限の実装
7125 ワード
本節ではRedisに基づいてシステムの限流制御を実現する.
着信したkeyに対してincr操作を行い、keyが初めて生成された場合、タイムアウト時間ARGVを設定する[1].
ttlは、タイムアウト時間が設定されておらず、長時間存在する場合に、あるkeyが行う保護の判断を防止するためである.
現在のkeyのvalが制限回数ARGVを超えているか否かを判断する[2].
luaスクリプトをロードし、Redis呼び出しのインタフェースを外部に提供します.
AOPのbeforeインプリメンテーションメソッドの実行前のブロックにより,RateLimitを注釈したすべてのメソッドがキャッシュされてストリーム制限される.いったん限流をトリガすると、外に異常が放出される.
ControllerAdviceで対応する異常の処理を行います.
詳細コードhttps://gitee.com/lawlet/shop
Luaスクリプト準備
local val = redis.call('incr', KEYS[1])
local ttl = redis.call('ttl', KEYS[1])
redis.log(redis.LOG_NOTICE, "incr "..KEYS[1].." "..val);
if val == 1 then
redis.call('expire', KEYS[1], tonumber(ARGV[1]))
else
if ttl == -1 then
redis.call('expire', KEYS[1], tonumber(ARGV[1]))
end
end
if val > tonumber(ARGV[2]) then
return 0
end
return 1
着信したkeyに対してincr操作を行い、keyが初めて生成された場合、タイムアウト時間ARGVを設定する[1].
ttlは、タイムアウト時間が設定されておらず、長時間存在する場合に、あるkeyが行う保護の判断を防止するためである.
現在のkeyのvalが制限回数ARGVを超えているか否かを判断する[2].
Redisクライアント
public Long limit(String key) {
return redisClient.eval(key, expire, reqCount);
}
luaスクリプトをロードし、Redis呼び出しのインタフェースを外部に提供します.
AOP
@Before("@annotation(com.snatch.deal.shop.common.annotations.RateLimit)")
public void before(JoinPoint pjp) throws Throwable {
Signature sig = pjp.getSignature();
if (!(sig instanceof MethodSignature)) {
throw new IllegalArgumentException(" ");
}
MethodSignature msig = (MethodSignature) sig;
String methodName = pjp.getTarget().getClass().getName() + "." + msig.getName();
String limitKey = Md5Utils.encrypt(methodName);
if (rateLimiter.limit(limitKey) != 1){
throw new OverLimitException(" ");
}
}
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RateLimit {
String value() default "";
}
AOPのbeforeインプリメンテーションメソッドの実行前のブロックにより,RateLimitを注釈したすべてのメソッドがキャッシュされてストリーム制限される.いったん限流をトリガすると、外に異常が放出される.
統合例外処理
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(OverLimitException.class)
@ResponseBody
public String OverLimitExceptionHandler(OverLimitException ole){
return ole.getMessage();
}
}
ControllerAdviceで対応する異常の処理を行います.
詳細コードhttps://gitee.com/lawlet/shop