前言

项目中有一个逻辑是消费kafka消息,然后调用下游接口处理逻辑,作者在用kafka处理消息的时候,通过google的rateLimiter.acquire()方法来达到接口限流的目的,但是发现,之后无论如何增大RateLimiter.create方法中的permitsPerSecond参数,接口QPS都没有变化,于是就有了下面的一系列猜测+验证的解决方法。

猜测+验证

首先可以从自己应用到的组件开始排查,然后定位到大概的地方,优化并验证。

比如:
在项目中的kafka消费端,有以下线程池的应用

@Autowired
private ThreadPoolTaskExecutor taskExecutor;

 // 异步执行
 try {
      taskExecutor.execute(() -> dosomething());
 } catch (Exception e) {
      log.error("execute# 处理dosomething方法发送线程池打满了", e);
  }

于是查看线程池的配置:

@Bean
public ThreadPoolTaskExecutor taskExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(5);
    executor.setKeepAliveSeconds(60);
    executor.setMaxPoolSize(20);
    executor.setQueueCapacity(1000);
    executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
    return executor;
}

线程池的核心数为5,最大线程数为20,队列数量为1000,我猜想是不是有可能线程任务在排队导致处理不过来,从而导致接口的QPS上不去,于是又查看了下调用下游接口的QPS:
在这里插入图片描述
发现的接口的RPS高峰稳定在1700左右,而我机器的集群QPS配置的是3600,少了一半的量,然后看了下kafka的消费者容器的并发数,根据接口的耗时,也就是1s处理请求的个数 * 我们机器的数量 * kafka的并发数 * 线程池的maxPoolSize等于1700左右,所以猜测是跟线程池的maxPoolSize的大小和下游接口耗时有关系,下游接口耗时没办法优化,于是我将线程池的maxPoolSize改成动态配置(nacos或者apollo)便于动态调整该参数,
将参数调大后,发现调用接口的QPS上来了,
在这里插入图片描述
高峰QPS稳定在2500左右,问题得已解决😄😄😄

总结

以上问题首先可以根据自己项目的逻辑用到了哪些组件,然后根据这些组件去排查,大概定位到是哪些地方出了问题,然后根据自己的猜测,列举几种解决方案,逐一去尝试,可能问题的答案就在其中,希望以上经验可以帮助到你!!!

Logo

Kafka开源项目指南提供详尽教程,助开发者掌握其架构、配置和使用,实现高效数据流管理和实时处理。它高性能、可扩展,适合日志收集和实时数据处理,通过持久化保障数据安全,是企业大数据生态系统的核心。

更多推荐