package love.wangqi.tokenbucket; import redis.clients.jedis.Jedis; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static java.util.concurrent.TimeUnit.SECONDS; /** * @author: wangqi * @description: * @date: Created in 2018/8/2 上午7:34 */ public abstract class SmoothRateLimiter extends RateLimiter { String key; String script; double storedPermits = 0; double permitsPerSecond = 1; double maxPermits = 0; double stableIntervalMicros = 0; protected SmoothRateLimiter(SleepingStopwatch stopwatch) { super(stopwatch); } @Override void doSetRate(double permitsPerSecond) { queryWaitMicros(0, null); double stableIntervalMicros = SECONDS.toMicros(1L) / permitsPerSecond; this.stableIntervalMicros = stableIntervalMicros; doSetRate(permitsPerSecond, stableIntervalMicros); } abstract void doSetRate(double permitsPerSecond, double stableIntervalMicros); @Override double doGetRate() { return SECONDS.toMicros(1L) / stableIntervalMicros; } @Override long queryWaitMicros(int permits, Long timeoutMicros) { List<String> keys = Arrays.asList(key, String.valueOf(maxPermits), String.valueOf(permitsPerSecond)); List<String> args = new ArrayList<>(); args.add(String.valueOf(permits)); if (timeoutMicros != null) { args.add(String.valueOf(timeoutMicros)); } try { Jedis redis = getJedis(); Object result = redis.eval(script, keys, args); return (long) result; } catch (Exception e) { e.printStackTrace(); } return 0; } }