美文网首页
从优化http接口的QPS说起--Java线程池的任务堆积

从优化http接口的QPS说起--Java线程池的任务堆积

作者: 天草二十六_简村人 | 来源:发表于2023-02-13 15:48 被阅读0次

一、背景

测试对http接口进行压测,压测请求并发数为300,每隔1秒进行持续加压直至1200。压测端发现,有20%~30%的请求被超时丢弃,大多数的接口耗时也都远大于3秒,换句话说,服务端的这个接口只有80左右。

服务端有两个节点,内存3.8g,cpu核数为2。接口的QPS和响应时间见下:


image.png

二、接口耗时分析

在压测时间段,接口的耗时最大有3.9秒之多,借助apm工具,进一步分析慢在哪里。

image.png image.png

和接口紧密相关的业务处理耗时只有388毫秒,但是三个异步任务原本应该是并行的,这里都变成了串行执行。

  • 源码分析:


    image.png

    在接口上增加注解@Async,然后定义线程池"async-event-executor"

    @Bean("async-event-executor")
    public AsyncTaskExecutor eventExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(4);
        executor.setMaxPoolSize(8);
        executor.setQueueCapacity(2000);
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("async-event-executor-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }

串行执行的原因总结

  • 当线程池的拒绝策略是CallerRunsPolicy() ,线程池的队列和最大线程数已满后,谁把任务给线程池的,就谁去执行。 也即undertow工作线程扔给线程池,因此不会交由线程池的线程去执行,不抛异常,而是调用者自己的线程串行执行。

三、线程池监控

image.png image.png

可以看到,线程的耗时非常大,线程池的压力非常大。

  • 这里还可以接入Metrics,由Prometheus拉取线程池的指标,让grafana展示。

四、JVM监控

这里看到的是gc,包括young gc和full gc的次数剧增,申请的堆内存过大。

堆内存.png gc次数.png gc耗时.png

总结:这里能够解释,为什么redis和Mongodb都没有慢查询,而apm接口中的慢接口分析中,和它们的交互却很慢。

五、改进意见

  • 1、线程池隔离,把不同的业务适用到多个线程池。

  • 2、流量消峰,使用mq替代java线程池。

  • 3、监控手段,实时分析线程池的队列积压。除了文中说的prometheus+grafana外, 还可以使用dynamic-tp等开源组件。

相关文章

  • 从优化http接口的QPS说起--Java线程池的任务堆积

    一、背景 测试对http接口进行压测,压测请求并发数为300,每隔1秒进行持续加压直至1200。压测端发现,有20...

  • java 实现自定义线程池

    java 实现自定义线程池 定义线程池接口 线程池接口的默认实现 示例摘抄于《Java并发变成的艺术》4.4.3线...

  • Java 线程池详解

    Java 线程池 Java 线程池模型的关键几个类和接口包括:Executor,Executors,Executo...

  • 线程池

    线程池管理器:用于创建并管理线程池工作线程:线程池中的线程任务接口:每个任务必须实现的接口,用于工作线程调度其运行...

  • 线程池

    参考:深入理解 Java 线程池:ThreadPoolExecutor 一 Executor接口 提供一种将”任务...

  • java - 如何监控线程池堆积任务

    1. 获得堆积任务大小 获取到堆积大小了,就可以通过打印日志的形式进行输出,也可以通过micrometer + p...

  • 2020-02-01-Java线程池

    Java线程池基本用法 Java提供了一些通用接口来创建线程池: 但是通常不推荐使用这些简易接口,因为这些接口可能...

  • 线程池学习

    Java线程池相关类 Executor定义了最常见的线程池接口,execute(Runnable command)...

  • Android中线程池的使用分析

    引言:说起线程池,学习过Java基础的同学估计都不陌生,Android中的线程池其实就是java的线程池。那么为什...

  • java中创建线程池的方式

    创建线程池的方式: 使用Java提供的用于管理线程池的接口ExecutorService 创建线程池,共有四种方式...

网友评论

      本文标题:从优化http接口的QPS说起--Java线程池的任务堆积

      本文链接:https://www.haomeiwen.com/subject/tknjkdtx.html