java如何实现qps
Java 实现 QPS(每秒查询数)的方法
在 Java 中实现 QPS(Queries Per Second)通常涉及对系统或接口的请求速率进行统计和监控。以下是几种常见的实现方式:
使用计数器统计 QPS
通过维护一个计数器,记录单位时间内的请求数量,可以计算出 QPS。
import java.util.concurrent.atomic.AtomicLong;
public class QPSCounter {
private final AtomicLong counter = new AtomicLong(0);
private long lastResetTime = System.currentTimeMillis();
public void increment() {
counter.incrementAndGet();
}
public double getQPS() {
long currentCount = counter.getAndSet(0);
long currentTime = System.currentTimeMillis();
double elapsedSeconds = (currentTime - lastResetTime) / 1000.0;
lastResetTime = currentTime;
return currentCount / elapsedSeconds;
}
}
使用滑动窗口算法
滑动窗口算法可以更精确地统计单位时间内的请求数,避免计数器方法的瞬时波动问题。
import java.util.LinkedList;
import java.util.Queue;
public class SlidingWindowQPS {
private final Queue<Long> timestamps = new LinkedList<>();
private final long windowSizeInMillis;
public SlidingWindowQPS(long windowSizeInMillis) {
this.windowSizeInMillis = windowSizeInMillis;
}
public synchronized void recordRequest() {
long now = System.currentTimeMillis();
timestamps.add(now);
removeOldRequests(now);
}
public synchronized int getCurrentQPS() {
long now = System.currentTimeMillis();
removeOldRequests(now);
return timestamps.size();
}
private void removeOldRequests(long now) {
while (!timestamps.isEmpty() && now - timestamps.peek() > windowSizeInMillis) {
timestamps.poll();
}
}
}
使用第三方库
许多成熟的第三方库提供了 QPS 统计功能,例如 Google Guava 的 RateLimiter 或 Netflix 的 Hystrix。
import com.google.common.util.concurrent.RateLimiter;
public class GuavaRateLimiterExample {
public static void main(String[] args) {
RateLimiter rateLimiter = RateLimiter.create(10.0); // 每秒 10 个请求
if (rateLimiter.tryAcquire()) {
// 处理请求
} else {
// 请求被限流
}
}
}
使用 Spring Boot 和 Micrometer
在 Spring Boot 应用中,可以使用 Micrometer 和 Prometheus 来监控 QPS。

import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
private final MeterRegistry meterRegistry;
public MyController(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
@GetMapping("/endpoint")
public String handleRequest() {
meterRegistry.counter("my.endpoint.requests").increment();
return "OK";
}
}
注意事项
- 多线程环境下需要确保计数器的线程安全性。
- 滑动窗口算法的精度和性能取决于窗口大小和请求频率。
- 第三方库通常提供了更丰富的功能和更好的性能优化。
以上方法可以根据具体需求选择适合的方案。






