十道Java限流器面試題和答案
1. 什么是速率限制?
速率限制是指對用戶在一定時間段內(nèi)向系統(tǒng)發(fā)出的請求次數(shù)進行控制,以保證系統(tǒng)的穩(wěn)定性和資源的公平分配。
2. 如何使用Java實現(xiàn)基本的限流器?
可以使用令牌桶或滑動日志方法。
public class RateLimiter {
private final long maxRequests;
private long lastRequestTime = System.currentTimeMillis();
private long currentRequests = 0;
public RateLimiter(long maxRequestsPerSecond) {
this.maxRequests = maxRequestsPerSecond;
}
public synchronized boolean allowRequest() {
long currentTime = System.currentTimeMillis();
if (currentTime - lastRequestTime > 1000) {
lastRequestTime = currentTime;
currentRequests = 0;
}
if (currentRequests < maxRequests) {
currentRequests++;
return true;
}
return false;
}
}
3. 令牌桶算法如何實現(xiàn)速率限制?
系統(tǒng)以一定的頻率向桶里放入令牌。每個請求都要消耗一個令牌。如果桶里沒有令牌,請求就會被拒絕。
4. 如何在速率限制中使用Redis?
Redis,憑借其原子操作和過期鍵,可以在分布式系統(tǒng)中高效地跟蹤記錄請求次數(shù)或令牌數(shù)量。
Redis 可用于限制速率
5. 如何處理分布式速率限制?
使用一個集中式存儲,如Redis,或一個分布式配置系統(tǒng),如ZooKeeper,來協(xié)調(diào)多個實例之間的速率限制。
Redis 可處理分布式速率限制
ZooKeeper 可處理分布式速率限制
6. 有狀態(tài)和無狀態(tài)限流器有什么區(qū)別?
有狀態(tài)的限流器會保存狀態(tài)(比如請求次數(shù)),而無狀態(tài)的限流器只根據(jù)當(dāng)前的數(shù)據(jù)做出決策,不存儲過去的信息。
無狀態(tài)的限流器不會在請求之間保留任何狀態(tài),也就是說它不會記住之前的請求。它只是根據(jù)當(dāng)前請求的信息做出決策。無狀態(tài)限流器的一種常用方法是使用JWT(JSON Web Token)或類似的令牌,令牌里面包含了必要的信息。
下面是使用JWT的簡單示例:
- 客戶端請求訪問并接收一個JWT,其中包含過期時間和允許的最大請求數(shù)。
- 對于每個請求,客戶端發(fā)送JWT。
- 服務(wù)器驗證JWT,并檢查過期時間和已發(fā)出的請求數(shù)。
- 如果客戶端在時間范圍內(nèi)超過了請求數(shù),服務(wù)器拒絕請求。
下面是基本的實現(xiàn):
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.Claims;
public class StatelessRateLimiter {
private static final String SECRET_KEY = "mySecretKey";
private static final int MAX_REQUESTS = 10;
private static final int ONE_HOUR = 3600000;
public String generateToken() {
long expirationTime = System.currentTimeMillis() + ONE_HOUR;
return Jwts.builder()
.setSubject("rateLimitToken")
.claim("requests", 0)
.setExpiration(new Date(expirationTime))
.signWith(SignatureAlgorithm.HS512, SECRET_KEY)
.compact();
}
public boolean allowRequest(String token) {
try {
Claims claims = Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
int requests = claims.get("requests", Integer.class);
if (requests < MAX_REQUESTS) {
claims.put("requests", requests + 1);
return true;
}
return false;
} catch (Exception e) {
return false;
}
}
}
這是一個簡化的例子。在實際場景中,你需要處理令牌的更新,確保令牌的安全存儲,并管理其他安全方面。這里使用的JWT庫是jjwt
。
7. 如何用Java實現(xiàn)一個滑動窗口限流器?
用一個列表或雙端隊列來存儲請求的時間戳。保證在每個時間窗口內(nèi)的請求次數(shù)不超過限制。
import java.util.Deque;
import java.util.LinkedList;
public class SlidingWindowRateLimiter {
private final Deque<Long> timestamps;
private final int maxRequests;
private final long windowSizeInMillis;
public SlidingWindowRateLimiter(int maxRequests, long windowSizeInMillis) {
this.timestamps = new LinkedList<>();
this.maxRequests = maxRequests;
this.windowSizeInMillis = windowSizeInMillis;
}
public synchronized boolean allowRequest() {
long currentTime = System.currentTimeMillis();
// 移除當(dāng)前窗口外的時間戳
while (!timestamps.isEmpty() && timestamps.peekFirst() < currentTime - windowSizeInMillis) {
timestamps.pollFirst();
}
// 檢查是否添加一個新請求會超過最大限制
if (timestamps.size() < maxRequests) {
timestamps.addLast(currentTime);
return true;
}
return false;
}
public static void main(String[] args) {
SlidingWindowRateLimiter limiter = new SlidingWindowRateLimiter(5, 1000); // 每秒5個請求
for (int i = 0; i < 10; i++) {
System.out.println(limiter.allowRequest()); // 前5個為true,后5個為false
try {
Thread.sleep(200); //睡眠200毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
在這個例子中,SlidingWindowRateLimiter限制了在一定時間窗口(windowSizeInMillis)內(nèi)的最大請求次數(shù)(maxRequests)。Deque用于存儲請求的時間戳。每次判斷是否可以接受新請求時,它會先刪除已經(jīng)超出當(dāng)前窗口的時間戳,然后再把Deque的長度和最大請求次數(shù)對比。
8. 如何在微服務(wù)架構(gòu)中處理速率限制?
在API網(wǎng)關(guān)層實現(xiàn)限流器或使用集中式存儲來實現(xiàn)分布式速率限制方法。
9. 在實時系統(tǒng)中進行速率限制有哪些挑戰(zhàn)?
要求盡可能降低延遲,應(yīng)對海量的請求,并在監(jiān)控和執(zhí)行限制的過程中不影響系統(tǒng)性能。
10. 如何向用戶或服務(wù)通知他們的速率限制狀態(tài)?
使用HTTP頭,如X-RateLimit-Limit,X-RateLimit-Remaining,和X-RateLimit-Reset來傳達速率限制的細節(jié)。
總結(jié)
速率限制是后端工程廣闊領(lǐng)域中的一項重要技術(shù),它能夠保證系統(tǒng)的穩(wěn)定性和資源的公平分配。我們已經(jīng)了解了Java提供的各種工具和技術(shù),可以用來實現(xiàn)有效的速率限制策略。無論你是準備面試,還是想要優(yōu)化你的后端系統(tǒng),掌握速率限制的細節(jié)都是非常必要的。建議你深入學(xué)習(xí)并進行實驗。