SpringBoot 实现QPS监控:别等系统宕机了才知道加监控

引言:为什么我们需要QPS监控?

系统运行得好好的,突然收到告警,CPU 100%,接口大量超时,用户疯狂投诉。你赶紧打开监控面板一看,QPS已经飙升到平时的10倍,而你之前根本没关注过这个指标。等你手忙脚乱地排查问题、扩容服务时,系统已经宕机了,老板在群里催着问情况...

这种场景在我们开发过程中并不少见。很多团队在系统上线初期,往往只关注功能实现,忽略了监控体系建设,直到系统真正出问题时才后悔莫及。

今天,我们就来聊聊如何用SpringBoot实现QPS监控,让系统运行状态尽在掌握,别等系统宕机了才知道加监控的重要性。

QPS监控架构与组件

QPS(Queries Per Second)即每秒查询率,是衡量系统性能的重要指标之一。在SpringBoot中实现QPS监控,主要涉及以下几个核心组件:

  1. 指标收集器:负责收集请求数据
  2. 计数器:统计单位时间内的请求数
  3. 存储器:临时存储统计数据
  4. 展示层:可视化展示监控数据
  5. 告警器:超过阈值时发送告警

实现方案与技术选型

方案一:使用Micrometer + Prometheus

Micrometer是SpringBoot官方推荐的指标收集库,与Prometheus结合可以实现强大的监控能力。

首先添加依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

配置application.yml:

management:
  endpoints:
    web:
      exposure:
        include: prometheus,health,info
  metrics:
    export:
      prometheus:
        enabled: true

方案二:自定义拦截器实现

如果需要更细粒度的控制,可以使用自定义拦截器:

@Component
public class QpsInterceptor implements HandlerInterceptor {
    
    private final MeterRegistry meterRegistry;
    private final Counter requestCounter;
    private final Timer requestTimer;
    
    public QpsInterceptor(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
        this.requestCounter = Counter.builder("http_requests_total")
            .description("Total number of HTTP requests")
            .register(meterRegistry);
        this.requestTimer = Timer.builder("http_request_duration_seconds")
            .description("HTTP request duration")
            .register(meterRegistry);
    }
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler) throws Exception {
        requestCounter.increment();
        return true;
    }
    
    @Override
    public void afterCompletion(HttpServletRequest request, 
                              HttpServletResponse response, 
                              Object handler, Exception ex) throws Exception {
        Timer.Sample sample = (Timer.Sample) request.getAttribute("timer_sample");
        if (sample != null) {
            sample.stop(requestTimer);
        }
    }
}

方案三:使用AOP切面统计

对于特定方法的QPS统计,可以使用AOP切面:

@Aspect
@Component
public class QpsAspect {
    
    private final MeterRegistry meterRegistry;
    private final Map<String, Counter> methodCounters = new ConcurrentHashMap<>();
    
    public QpsAspect(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }
    
    @Around("@annotation(trackQps)")
    public Object trackQps(ProceedingJoinPoint joinPoint, TrackQps trackQps) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        Counter counter = methodCounters.computeIfAbsent(
            methodName,
            k -> Counter.builder("method_calls_total")
                .tag("method", k)
                .description("Number of method calls")
                .register(meterRegistry)
        );
        
        counter.increment();
        return joinPoint.proceed();
    }
}

实际应用案例

案例一:API网关QPS监控

在API网关中,我们可以统计所有经过网关的请求:

@RestController
public class GatewayController {
    
    private final MeterRegistry meterRegistry;
    
    public GatewayController(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }
    
    @GetMapping("/gateway/monitor")
    public ResponseEntity<Map<String, Object>> getQpsMetrics() {
        Map<String, Object> result = new HashMap<>();
        
        // 获取QPS指标
        Gauge qpsGauge = meterRegistry.find("http_requests_total").gauge();
        if (qpsGauge != null) {
            result.put("qps", qpsGauge.value());
        }
        
        // 获取请求延迟指标
        Timer.Sample sample = meterRegistry.find("http_request_duration_seconds").timer();
        if (sample != null) {
            result.put("avg_response_time", sample.mean());
        }
        
        return ResponseEntity.ok(result);
    }
}

案例二:业务方法QPS监控

对核心业务方法进行QPS监控:

@Service
public class OrderService {
    
    private final MeterRegistry meterRegistry;
    private final Timer orderProcessingTimer;
    
    public OrderService(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
        this.orderProcessingTimer = Timer.builder("order_processing_duration_seconds")
            .description("Order processing duration")
            .register(meterRegistry);
    }
    
    public Order createOrder(OrderRequest request) {
        return orderProcessingTimer.record(() -> {
            // 订单处理逻辑
            return processOrder(request);
        });
    }
    
    private Order processOrder(OrderRequest request) {
        // 实际的订单处理逻辑
        return new Order();
    }
}

告警与通知机制

有了监控数据后,我们还需要设置合理的告警阈值:

@Component
public class QpsAlertService {
    
    private final MeterRegistry meterRegistry;
    private final int qpsThreshold = 1000; // 每秒1000次请求为阈值
    
    public QpsAlertService(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }
    
    @Scheduled(fixedRate = 5000) // 每5秒检查一次
    public void checkQpsAlert() {
        Double qps = getCurrentQps();
        if (qps != null && qps > qpsThreshold) {
            sendAlert("QPS过高", "当前QPS: " + qps + ", 阈值: " + qpsThreshold);
        }
    }
    
    private Double getCurrentQps() {
        // 获取当前QPS
        return meterRegistry.find("http_requests_total").counter().count();
    }
    
    private void sendAlert(String title, String message) {
        // 发送告警通知
        // 可以集成钉钉、企业微信等
        System.out.println("告警: " + title + " - " + message);
    }
}

最佳实践与注意事项

  1. 选择合适的监控粒度:不要过度监控,只关注核心指标
  2. 设置合理的采样率:避免监控本身影响系统性能
  3. 建立多层次告警:设置不同的告警级别和阈值
  4. 定期清理历史数据:避免监控数据占用过多存储空间
  5. 监控监控系统本身:确保监控系统正常运行

总结

通过SpringBoot实现QPS监控,我们能够实时了解系统运行状态,及时发现性能瓶颈和异常情况。在实际应用中,建议结合Micrometer、Prometheus等成熟方案,同时根据业务特点定制化监控指标。

记住,监控不是可有可无的装饰品,而是保障系统稳定运行的重要基础设施。别等系统宕机了才知道加监控的重要性,从现在开始,为你的系统建立完善的监控体系吧!


标题:SpringBoot 实现QPS监控:别等系统宕机了才知道加监控
作者:jiangyi
地址:http://jiangyi.space/articles/2025/12/26/1766729054083.html

    0 评论
avatar