速率限制是指对用户在一定时间段内向系统发出的请求次数进行控制,以保证系统的稳定性和资源的公平分配。
成都创新互联公司主要从事成都做网站、成都网站建设、网页设计、企业做网站、公司建网站等业务。立足成都服务华容,十余年网站建设经验,价格优惠、服务专业,欢迎来电咨询建站服务:18980820575
可以使用令牌桶或滑动日志方法。
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;
}
}
系统以一定的频率向桶里放入令牌。每个请求都要消耗一个令牌。如果桶里没有令牌,请求就会被拒绝。
Redis,凭借其原子操作和过期键,可以在分布式系统中高效地跟踪记录请求次数或令牌数量。
Redis 可用于限制速率
使用一个集中式存储,如Redis,或一个分布式配置系统,如ZooKeeper,来协调多个实例之间的速率限制。
Redis 可处理分布式速率限制
ZooKeeper 可处理分布式速率限制
有状态的限流器会保存状态(比如请求次数),而无状态的限流器只根据当前的数据做出决策,不存储过去的信息。
无状态的限流器不会在请求之间保留任何状态,也就是说它不会记住之前的请求。它只是根据当前请求的信息做出决策。无状态限流器的一种常用方法是使用JWT(JSON Web Token)或类似的令牌,令牌里面包含了必要的信息。
下面是使用JWT的简单示例:
下面是基本的实现:
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
。
用一个列表或双端队列来存储请求的时间戳。保证在每个时间窗口内的请求次数不超过限制。
import java.util.Deque;
import java.util.LinkedList;
public class SlidingWindowRateLimiter {
private final Deque 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();
// 移除当前窗口外的时间戳
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)内的最大请求次数(maxRequests)。Deque用于存储请求的时间戳。每次判断是否可以接受新请求时,它会先删除已经超出当前窗口的时间戳,然后再把Deque的长度和最大请求次数对比。
在API网关层实现限流器或使用集中式存储来实现分布式速率限制方法。
要求尽可能降低延迟,应对海量的请求,并在监控和执行限制的过程中不影响系统性能。
使用HTTP头,如X-RateLimit-Limit,X-RateLimit-Remaining,和X-RateLimit-Reset来传达速率限制的细节。
速率限制是后端工程广阔领域中的一项重要技术,它能够保证系统的稳定性和资源的公平分配。我们已经了解了Java提供的各种工具和技术,可以用来实现有效的速率限制策略。无论你是准备面试,还是想要优化你的后端系统,掌握速率限制的细节都是非常必要的。建议你深入学习并进行实验。
分享名称:十道Java限流器面试题和答案
URL标题:http://www.shufengxianlan.com/qtweb/news11/549061.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联