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