We want to connect the people who have knowledge to the people who need it, to bring together people with different perspectives so they can understand each other better, and to empower everyone to share their knowledge.
Bandwidth b = Bandwidth.classic(100, Refill.intervally(100, Duration.ofSeconds(5))); //Bandwidth b = Bandwidth.classic(100, Refill.intervally(100, Duration.ofMinutes(10))); Bucket bk = Bucket.builder().addLimit(b).build(); //then if(bk.tryConsume(1)) { //stuff } else { throw }
RateLimiterConfig config = RateLimiterConfig.custom() .limitRefreshPeriod(Duration.ofSeconds(5)) .limitForPeriod(100) .timeoutDuration(Duration.ofSeconds(1)) .build(); RateLimiterRegistry rateLimiterRegistry = RateLimiterRegistry.of(config); RateLimiter rateLimiterWithCustomConfig = rateLimiterRegistry .rateLimiter("name2", config); CheckedRunnable restrictedCall = RateLimiter .decorateCheckedRunnable(rateLimiterWithCustomConfig, this::doStuff); //then Try.run(restrictedCall).onFailure(this::throwEx)
public class EzyActionFrame5Seconds extends EzyActionFrame { public EzyActionFrameSecond() { this(Integer.MAX_VALUE); } public EzyActionFrameSecond(long maxActions) { super(maxActions); } public EzyActionFrameSecond(long maxActions, long startTime) { super(maxActions, startTime); } @Override protected final int getExistsTime() { return 5000; } @Override public final EzyActionFrame nextFrame() { return new EzyActionFrame5Seconds(maxActions, endTime); } }
frame[1]> EzyActionFrame5Seconds: 2022-10-14 15-39-19.701 -> 2022-10-14 15-39-24.701, actions: 0, maxActions: 5, tooManyRequest: false add 1 actions frame[1]> EzyActionFrame5Seconds: 2022-10-14 15-39-19.701 -> 2022-10-14 15-39-24.701, actions: 1, maxActions: 5, tooManyRequest: false add 2 actions frame[1]> EzyActionFrame5Seconds: 2022-10-14 15-39-19.701 -> 2022-10-14 15-39-24.701, actions: 3, maxActions: 5, tooManyRequest: false add 7 actions frame[1]> EzyActionFrame5Seconds: 2022-10-14 15-39-19.701 -> 2022-10-14 15-39-24.701, actions: 10, maxActions: 5, tooManyRequest: true add 8 actions frame[1]> EzyActionFrame5Seconds: 2022-10-14 15-39-19.701 -> 2022-10-14 15-39-24.701, actions: 18, maxActions: 5, tooManyRequest: true add 5 actions frame[1]> EzyActionFrame5Seconds: 2022-10-14 15-39-19.701 -> 2022-10-14 15-39-24.701, actions: 23, maxActions: 5, tooManyRequest: true add 6 actions frame[2]> EzyActionFrame5Seconds: 2022-10-14 15-39-24.701 -> 2022-10-14 15-39-29.701, actions: 6, maxActions: 5, tooManyRequest: true add 2 actions frame[2]> EzyActionFrame5Seconds: 2022-10-14 15-39-24.701 -> 2022-10-14 15-39-29.701, actions: 8, maxActions: 5, tooManyRequest: true add 4 actions frame[2]> EzyActionFrame5Seconds: 2022-10-14 15-39-24.701 -> 2022-10-14 15-39-29.701, actions: 12, maxActions: 5, tooManyRequest: true add 2 actions frame[2]> EzyActionFrame5Seconds: 2022-10-14 15-39-24.701 -> 2022-10-14 15-39-29.701, actions: 14, maxActions: 5, tooManyRequest: true add 4 actions frame[2]> EzyActionFrame5Seconds: 2022-10-14 15-39-24.701 -> 2022-10-14 15-39-29.701, actions: 18, maxActions: 5, tooManyRequest: true add 8 actions frame[3]> EzyActionFrame5Seconds: 2022-10-14 15-39-29.701 -> 2022-10-14 15-39-34.701, actions: 8, maxActions: 5, tooManyRequest: true
public class EzyCompositeActionFrame { private final int seconds; private long totalActions; private final long maxActions; private final List inSecondFrames; public EzyCompositeActionFrame(int seconds, long maxActions) { this.seconds = seconds; this.maxActions = maxActions; this.inSecondFrames = new ArrayList<>(); } public synchronized boolean addActions(int actions) { final long currentTime = System.currentTimeMillis(); final long minStartTime = currentTime - seconds; final Iterator iterator = inSecondFrames.iterator(); while (iterator.hasNext()) { final EzyActionFrame frame = iterator.next(); if (frame.getStartTime() < minStartTime) { iterator.remove(); } else { break } } EzyActionFrame currentFrame = null for (EzyActionFrame frame : inSecondFrames) { if (frame.isValid()) { currentFrame = frame; break } } if (currentFrame == null) { currentFrame = new EzyActionFrameSecond(maxActions, currentTime); inSecondFrames.add(currentFrame); } currentFrame.addActions(actions); totalActions = inSecondFrames.stream().mapToLong(EzyActionFrame::getActions).sum(); return totalActions > maxActions; } public synchronized boolean isInvalid() {return totalActions > maxActions;} @Override public String toString() { final long startTime = inSecondFrames.isEmpty() ? System.currentTimeMillis() : inSecondFrames.get(0).startTime; final long endTime = startTime + seconds; final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss.SSS"); return df.format(startTime) + " -> " + df.format(endTime) + ", actions: " + totalActions + ", maxActions: " + maxActions + ", tooManyRequest: " + isInvalid(); } public static void main(String[] args) throws Exception { final EzyCompositeActionFrame frame = new EzyCompositeActionFrame(3, 4); System.out.println(frame); while (true) { final int actions = ThreadLocalRandom.current().nextInt(1, 10); System.out.println("add " + actions + " actions"); frame.addActions(actions); System.out.println(frame); Thread.sleep(1000); } } }
if(frame.isInvalid()) it should be if(frame.isValid()), right? But even so, the result is not my expectation.
package com.example.ratelimiting; import lombok.Getter; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class EzyCompositeActionFrame { private final int seconds; private long totalActions; private final long maxActions; private final List<EzyActionFrame> inSecondFrames; public EzyCompositeActionFrame(int seconds, long maxActions) { this.seconds = seconds; this.maxActions = maxActions; this.inSecondFrames = new ArrayList<>(); } public synchronized boolean addActions(int actions) { final long currentTime = System.currentTimeMillis(); final long minStartTime = currentTime - seconds; final Iterator<EzyActionFrame> iterator = inSecondFrames.iterator(); while (iterator.hasNext()) { final EzyActionFrame frame = iterator.next(); if (frame.getStartTime() < minStartTime) { iterator.remove(); } else { break; } } EzyActionFrame currentFrame = null; for (EzyActionFrame frame : inSecondFrames) { if (frame.isValid()) { currentFrame = frame; break; } } if (currentFrame == null) { currentFrame = new EzyActionFrameSecond( maxActions, currentTime ); inSecondFrames.add(currentFrame); } currentFrame.addActions(actions); totalActions = inSecondFrames .stream() .mapToLong(EzyActionFrame::getActions) .sum(); return totalActions > maxActions; } public synchronized boolean isInvalid() { return totalActions > maxActions; } @Override public String toString() { final long startTime = inSecondFrames.isEmpty() ? System.currentTimeMillis() : inSecondFrames.get(0).startTime; final long endTime = startTime + seconds; final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss.SSS"); return df.format(startTime) + " -> " + df.format(endTime) + ", actions: " + totalActions + ", maxActions: " + maxActions + ", tooManyRequest: " + isInvalid(); } @Getter static abstract class EzyActionFrame { protected final long endTime; protected final long startTime; protected final long maxActions; protected volatile long actions; public EzyActionFrame(long maxActions) { this(maxActions, System.currentTimeMillis()); } public EzyActionFrame(long maxActions, long startTime) { this.maxActions = maxActions; this.startTime = startTime; this.endTime = startTime + getExistsTime(); } protected abstract int getExistsTime(); public boolean addActions(long actions) { return (this.actions += actions) > maxActions; } public boolean isExpired() { return System.currentTimeMillis() > endTime; } public boolean isInvalid() { return actions > maxActions; } public boolean isValid() { return !isInvalid(); } public abstract EzyActionFrame nextFrame(); @Override public String toString() { SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss.SSS"); return getClass().getSimpleName() + ": " + df.format(startTime) + " -> " + df.format(endTime); } } static class EzyActionFrameSecond extends EzyActionFrame { public EzyActionFrameSecond() { this(Integer.MAX_VALUE); } public EzyActionFrameSecond(long maxActions) { super(maxActions); } public EzyActionFrameSecond(long maxActions, long startTime) { super(maxActions, startTime); } @Override protected final int getExistsTime() { return 1000; } @Override public final EzyActionFrame nextFrame() { return new EzyActionFrameSecond(maxActions, endTime); } } public static void main(String[] args) throws Exception { final EzyCompositeActionFrame frame = new EzyCompositeActionFrame(3, 4); // 1st request comes (second ~0.5) Thread.sleep(500); System.out.println("add 1st actions"); frame.addActions(1); System.out.println(frame); // 2nd request comes (second ~1) Thread.sleep(450); System.out.println("add 2nd actions"); frame.addActions(2); System.out.println(frame); // 3th request comes (second ~2) Thread.sleep(1000); System.out.println("add 3th actions"); frame.addActions(3); System.out.println(frame); // 4th request comes (second ~3) Thread.sleep(1000); System.out.println("add 4th actions"); frame.addActions(4); System.out.println(frame); // 5th request comes (second ~4) Thread.sleep(1000); System.out.println("add 5th actions"); frame.addActions(5); System.out.println(frame); // 6th request comes (second ~4.1) Thread.sleep(100); System.out.println("add 6th actions"); frame.addActions(6); System.out.println(frame); // 7th request comes (second ~4.2) Thread.sleep(100); System.out.println("add 7th actions"); frame.addActions(7); System.out.println(frame); // 8th request comes (second ~4.3) Thread.sleep(100); System.out.println("add 8th actions"); frame.addActions(8); System.out.println(frame); } }
add 1st actions 2022-10-14 19-39-13.346 -> 2022-10-14 19-39-13.349, actions: 1, maxActions: 4, tooManyRequest: false add 2nd actions 2022-10-14 19-39-13.914 -> 2022-10-14 19-39-13.917, actions: 2, maxActions: 4, tooManyRequest: false add 3th actions 2022-10-14 19-39-14.927 -> 2022-10-14 19-39-14.930, actions: 3, maxActions: 4, tooManyRequest: false add 4th actions 2022-10-14 19-39-15.940 -> 2022-10-14 19-39-15.943, actions: 4, maxActions: 4, tooManyRequest: false add 5th actions 2022-10-14 19-39-16.953 -> 2022-10-14 19-39-16.956, actions: 5, maxActions: 4, tooManyRequest: true add 6th actions 2022-10-14 19-39-17.063 -> 2022-10-14 19-39-17.066, actions: 6, maxActions: 4, tooManyRequest: true add 7th actions 2022-10-14 19-39-17.172 -> 2022-10-14 19-39-17.175, actions: 7, maxActions: 4, tooManyRequest: true add 8th actions 2022-10-14 19-39-17.280 -> 2022-10-14 19-39-17.283, actions: 8, maxActions: 4, tooManyRequest: true
add 1st actions 2022-10-14 19-39-13.346 -> 2022-10-14 19-39-13.349, actions: 1, maxActions: 4, tooManyRequest: false add 2nd actions 2022-10-14 19-39-13.914 -> 2022-10-14 19-39-13.917, actions: 2, maxActions: 4, tooManyRequest: false add 3th actions 2022-10-14 19-39-14.927 -> 2022-10-14 19-39-14.930, actions: 3, maxActions: 4, tooManyRequest: false add 4th actions 2022-10-14 19-39-15.940 -> 2022-10-14 19-39-15.943, actions: 4, maxActions: 4, tooManyRequest: false add 5th actions 2022-10-14 19-39-16.953 -> 2022-10-14 19-39-16.956, actions: 5, maxActions: 4, tooManyRequest: false add 6th actions 2022-10-14 19-39-17.063 -> 2022-10-14 19-39-17.066, actions: 6, maxActions: 4, tooManyRequest: false add 7th actions 2022-10-14 19-39-17.172 -> 2022-10-14 19-39-17.175, actions: 7, maxActions: 4, tooManyRequest: false add 8th actions 2022-10-14 19-39-17.280 -> 2022-10-14 19-39-17.283, actions: 8, maxActions: 4, tooManyRequest: true
import lombok.Getter; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class EzyCompositeActionFrame { private final int seconds; private volatile long totalActions; private final long maxActions; private final List inSecondFrames; public EzyCompositeActionFrame(int seconds, long maxActions) { this.seconds = seconds; this.maxActions = maxActions; this.inSecondFrames = new ArrayList<>(); } public synchronized boolean addActions(int actions) { final long currentTime = System.currentTimeMillis(); final long minStartTime = currentTime - seconds * 1000L final Iterator iterator = inSecondFrames.iterator(); while (iterator.hasNext()) { final EzyActionFrame frame = iterator.next(); if (frame.getStartTime() < minStartTime) { iterator.remove(); } else { break } } EzyActionFrame currentFrame = null for (EzyActionFrame frame : inSecondFrames) { if (frame.isValid()) { currentFrame = frame; break } } if (currentFrame == null) { currentFrame = new EzyActionFrameSecond(maxActions, currentTime); inSecondFrames.add(currentFrame); } currentFrame.addActions(actions); totalActions = inSecondFrames.stream().mapToLong(EzyActionFrame::getActions).sum(); return totalActions > maxActions; } public synchronized boolean isInvalid() {return totalActions > maxActions;} @Override public String toString() { final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss.SSS"); return df.format(System.currentTimeMillis()) + ", frames: " + inSecondFrames.size() + ", actions: " + totalActions + ", maxActions: " + maxActions + ", tooManyRequest: " + isInvalid(); } @Getter static abstract class EzyActionFrame { protected final long endTime; protected final long startTime; protected final long maxActions; protected volatile long actions; public EzyActionFrame(long maxActions) {this(maxActions, System.currentTimeMillis());} public EzyActionFrame(long maxActions, long startTime) { this.maxActions = maxActions; this.startTime = startTime; this.endTime = startTime + getExistsTime(); } protected abstract int getExistsTime() public boolean addActions(long actions) {return (this.actions += actions) > maxActions;} public boolean isExpired() {return System.currentTimeMillis() > endTime;} public boolean isInvalid() {return actions > maxActions;} public boolean isValid() {return !isInvalid();} public abstract EzyActionFrame nextFrame() @Override public String toString() { SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss.SSS"); return getClass().getSimpleName() + ": " + df.format(startTime) + " -> " + df.format(endTime); } } static class EzyActionFrameSecond extends EzyActionFrame { public EzyActionFrameSecond() {this(Integer.MAX_VALUE);} public EzyActionFrameSecond(long maxActions) {super(maxActions);} public EzyActionFrameSecond(long maxActions, long startTime) {super(maxActions, startTime);} @Override protected final int getExistsTime() {return 1000} @Override public final EzyActionFrame nextFrame() {return new EzyActionFrameSecond(maxActions, endTime);} } public static void main(String[] args) throws Exception { final EzyCompositeActionFrame frame = new EzyCompositeActionFrame(3, 4); // 1st request comes (second ~0.5) Thread.sleep(500); System.out.println("add 1st actions"); frame.addActions(1); System.out.println(frame); // 2nd request comes (second ~1) Thread.sleep(450); System.out.println("add 2nd actions"); frame.addActions(2); System.out.println(frame); // 3th request comes (second ~2) Thread.sleep(1000); System.out.println("add 3th actions"); frame.addActions(3); System.out.println(frame); // 4th request comes (second ~3) Thread.sleep(1000); System.out.println("add 4th actions"); frame.addActions(4); System.out.println(frame); // 5th request comes (second ~4) Thread.sleep(1000); System.out.println("add 5th actions"); frame.addActions(5); System.out.println(frame); // 6th request comes (second ~4.1) Thread.sleep(100); System.out.println("add 6th actions"); frame.addActions(6); System.out.println(frame); // 7th request comes (second ~4.2) Thread.sleep(100); System.out.println("add 7th actions"); frame.addActions(7); System.out.println(frame); // 8th request comes (second ~4.3) Thread.sleep(100); System.out.println("add 8th actions"); frame.addActions(8); System.out.println(frame); } }
2.2K Point(s)
1.2K Point(s)
313 Point(s)
178 Point(s)
138 Point(s)
Input your email to receive reset password link, or if you remember your password, you can click