Add rate limiting code
This commit is contained in:
33
implementations/java/rate_limiting/FixedWindowCounter.java
Normal file
33
implementations/java/rate_limiting/FixedWindowCounter.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package implementations.java.rate_limiting;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
public class FixedWindowCounter {
|
||||
private final long windowSizeInSeconds; // Size of each window in seconds
|
||||
private final long maxRequestsPerWindow; // Maximum number of requests allowed per window
|
||||
private long currentWindowStart; // Start time of the current window
|
||||
private long requestCount; // Number of requests in the current window
|
||||
|
||||
public FixedWindowCounter(long windowSizeInSeconds, long maxRequestsPerWindow) {
|
||||
this.windowSizeInSeconds = windowSizeInSeconds;
|
||||
this.maxRequestsPerWindow = maxRequestsPerWindow;
|
||||
this.currentWindowStart = Instant.now().getEpochSecond();
|
||||
this.requestCount = 0;
|
||||
}
|
||||
|
||||
public synchronized boolean allowRequest() {
|
||||
long now = Instant.now().getEpochSecond();
|
||||
|
||||
// Check if we've moved to a new window
|
||||
if (now - currentWindowStart >= windowSizeInSeconds) {
|
||||
currentWindowStart = now; // Start a new window
|
||||
requestCount = 0; // Reset the count for the new window
|
||||
}
|
||||
|
||||
if (requestCount < maxRequestsPerWindow) {
|
||||
requestCount++; // Increment the count for this window
|
||||
return true; // Allow the request
|
||||
}
|
||||
return false; // We've exceeded the limit for this window, deny the request
|
||||
}
|
||||
}
|
||||
42
implementations/java/rate_limiting/LeakyBucket.java
Normal file
42
implementations/java/rate_limiting/LeakyBucket.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package implementations.java.rate_limiting;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
public class LeakyBucket {
|
||||
private final long capacity; // Maximum number of requests the bucket can hold
|
||||
private final double leakRate; // Rate at which requests leak out of the bucket (requests per second)
|
||||
private final Queue<Instant> bucket; // Queue to hold timestamps of requests
|
||||
private Instant lastLeakTimestamp; // Last time we leaked from the bucket
|
||||
|
||||
public LeakyBucket(long capacity, double leakRate) {
|
||||
this.capacity = capacity;
|
||||
this.leakRate = leakRate;
|
||||
this.bucket = new LinkedList<>();
|
||||
this.lastLeakTimestamp = Instant.now();
|
||||
}
|
||||
|
||||
public synchronized boolean allowRequest() {
|
||||
leak(); // First, leak out any requests based on elapsed time
|
||||
|
||||
if (bucket.size() < capacity) {
|
||||
bucket.offer(Instant.now()); // Add the new request to the bucket
|
||||
return true; // Allow the request
|
||||
}
|
||||
return false; // Bucket is full, deny the request
|
||||
}
|
||||
|
||||
private void leak() {
|
||||
Instant now = Instant.now();
|
||||
long elapsedMillis = now.toEpochMilli() - lastLeakTimestamp.toEpochMilli();
|
||||
int leakedItems = (int) (elapsedMillis * leakRate / 1000.0); // Calculate how many items should have leaked
|
||||
|
||||
// Remove the leaked items from the bucket
|
||||
for (int i = 0; i < leakedItems && !bucket.isEmpty(); i++) {
|
||||
bucket.poll();
|
||||
}
|
||||
|
||||
lastLeakTimestamp = now;
|
||||
}
|
||||
}
|
||||
42
implementations/java/rate_limiting/SlidingWindowCounter.java
Normal file
42
implementations/java/rate_limiting/SlidingWindowCounter.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package implementations.java.rate_limiting;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
public class SlidingWindowCounter {
|
||||
private final long windowSizeInSeconds; // Size of the sliding window in seconds
|
||||
private final long maxRequestsPerWindow; // Maximum number of requests allowed in the window
|
||||
private long currentWindowStart; // Start time of the current window
|
||||
private long previousWindowCount; // Number of requests in the previous window
|
||||
private long currentWindowCount; // Number of requests in the current window
|
||||
|
||||
public SlidingWindowCounter(long windowSizeInSeconds, long maxRequestsPerWindow) {
|
||||
this.windowSizeInSeconds = windowSizeInSeconds;
|
||||
this.maxRequestsPerWindow = maxRequestsPerWindow;
|
||||
this.currentWindowStart = Instant.now().getEpochSecond();
|
||||
this.previousWindowCount = 0;
|
||||
this.currentWindowCount = 0;
|
||||
}
|
||||
|
||||
public synchronized boolean allowRequest() {
|
||||
long now = Instant.now().getEpochSecond();
|
||||
long timePassedInWindow = now - currentWindowStart;
|
||||
|
||||
// Check if we've moved to a new window
|
||||
if (timePassedInWindow >= windowSizeInSeconds) {
|
||||
previousWindowCount = currentWindowCount;
|
||||
currentWindowCount = 0;
|
||||
currentWindowStart = now;
|
||||
timePassedInWindow = 0;
|
||||
}
|
||||
|
||||
// Calculate the weighted count of requests
|
||||
double weightedCount = previousWindowCount * ((windowSizeInSeconds - timePassedInWindow) / (double) windowSizeInSeconds)
|
||||
+ currentWindowCount;
|
||||
|
||||
if (weightedCount < maxRequestsPerWindow) {
|
||||
currentWindowCount++; // Increment the count for this window
|
||||
return true; // Allow the request
|
||||
}
|
||||
return false; // We've exceeded the limit, deny the request
|
||||
}
|
||||
}
|
||||
33
implementations/java/rate_limiting/SlidingWindowLog.java
Normal file
33
implementations/java/rate_limiting/SlidingWindowLog.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package implementations.java.rate_limiting;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
public class SlidingWindowLog {
|
||||
private final long windowSizeInSeconds; // Size of the sliding window in seconds
|
||||
private final long maxRequestsPerWindow; // Maximum number of requests allowed in the window
|
||||
private final Queue<Long> requestLog; // Log of request timestamps
|
||||
|
||||
public SlidingWindowLog(long windowSizeInSeconds, long maxRequestsPerWindow) {
|
||||
this.windowSizeInSeconds = windowSizeInSeconds;
|
||||
this.maxRequestsPerWindow = maxRequestsPerWindow;
|
||||
this.requestLog = new LinkedList<>();
|
||||
}
|
||||
|
||||
public synchronized boolean allowRequest() {
|
||||
long now = Instant.now().getEpochSecond();
|
||||
long windowStart = now - windowSizeInSeconds;
|
||||
|
||||
// Remove timestamps that are outside of the current window
|
||||
while (!requestLog.isEmpty() && requestLog.peek() <= windowStart) {
|
||||
requestLog.poll();
|
||||
}
|
||||
|
||||
if (requestLog.size() < maxRequestsPerWindow) {
|
||||
requestLog.offer(now); // Log this request
|
||||
return true; // Allow the request
|
||||
}
|
||||
return false; // We've exceeded the limit for this window, deny the request
|
||||
}
|
||||
}
|
||||
36
implementations/java/rate_limiting/TokenBucket.java
Normal file
36
implementations/java/rate_limiting/TokenBucket.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package implementations.java.rate_limiting;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
public class TokenBucket {
|
||||
private final long capacity; // Maximum number of tokens the bucket can hold
|
||||
private final double fillRate; // Rate at which tokens are added to the bucket (tokens per second)
|
||||
private double tokens; // Current number of tokens in the bucket
|
||||
private Instant lastRefillTimestamp; // Last time we refilled the bucket
|
||||
|
||||
public TokenBucket(long capacity, double fillRate) {
|
||||
this.capacity = capacity;
|
||||
this.fillRate = fillRate;
|
||||
this.tokens = capacity; // Start with a full bucket
|
||||
this.lastRefillTimestamp = Instant.now();
|
||||
}
|
||||
|
||||
public synchronized boolean allowRequest(int tokens) {
|
||||
refill(); // First, add any new tokens based on elapsed time
|
||||
|
||||
if (this.tokens < tokens) {
|
||||
return false; // Not enough tokens, deny the request
|
||||
}
|
||||
|
||||
this.tokens -= tokens; // Consume the tokens
|
||||
return true; // Allow the request
|
||||
}
|
||||
|
||||
private void refill() {
|
||||
Instant now = Instant.now();
|
||||
// Calculate how many tokens to add based on the time elapsed
|
||||
double tokensToAdd = (now.toEpochMilli() - lastRefillTimestamp.toEpochMilli()) * fillRate / 1000.0;
|
||||
this.tokens = Math.min(capacity, this.tokens + tokensToAdd); // Add tokens, but don't exceed capacity
|
||||
this.lastRefillTimestamp = now;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user