优化排查线程阻塞:CompletableFuture 和 DiscardPolicy

开发 前端
既然不是死循环、CPU空转。那是不是代码阻塞的问题呢。导出 66182 进程jvm的 stack 文件 jstack -l 66182 > block66182.jstack。因为知道是http 线程的问题。

[[426087]]

本文转载自微信公众号「潜行前行」,作者cscw 。转载本文请联系潜行前行公众号。

 问题发现

1 前天大佬通过prometheus发现 tomcat http busy状态的线程这几天呈线性递增。每一天增加3个

排查问题

1:找到busy线程在哪。通过jvm自带的 jps 命令可以找到服务对应的进程ID:66182$>$top -Hp 66182

$pidstat -u -p 66182 1 5

大部分的线程都正常,cpu利用率不高,而且线程ID变动快,基本排除 死循环、CPU 空转的问题

2:既然不是死循环、CPU空转。那是不是代码阻塞的问题呢。导出 66182 进程jvm的 stack 文件 jstack -l 66182 > block66182.jstack。因为知道是http 线程的问题。http 的开头一般都是 http-nio 。可以使用 grep -A 15 'http-nio' block66182.jstack 输出一些关键信息。找了很久,多数http 都是正常状态。然后还找到了项目代码 updateXYDVerifiedCodeByDate 之类的。定位到具体,发现是一个定时任务

3 查了下 xxl-task 调度日志。凌晨左右调度了十次,失败了三次,和在prometheus发现的 busy http线程增加的规律是一致的

4 查找代码发现是 CompletableFuture 调用get阻塞住了。后来改成 future.get(15, TimeUnit.SECONDS);。则每隔 15 秒报错一次。但是在promethues 监控到 verifiedCodeQueryExecutor 的线程队列是空的。

4.1 promethues 监控到的线程队列数为空

5 没有任务 CompletableFuture 的get方法还在执行,查看下 verifiedCodeQueryExecutor 的定义。发现,阻塞队列的拒绝策略 是 DiscardPolicy 丢弃。也就是任务丢弃了不被执行,而封装成的CompletableFuture 自然就不会有结果返回,因此一直会被阻塞,而改了代码则是超时返回。真相大白。。。。。

解决问题

1:队列无限,好像不太好,不接受

2:自定义拒绝策略

  1. new RejectedExecutionHandler(){ 
  2.             @Override 
  3.             public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { 
  4.                 throw new RuntimeException(" over size error "); 
  5.             } 
  6.         } 

3:但考虑到任务必须被处理掉,任务不能被丢弃啊。so 暂时用 CallerRunsPolicy 策略,executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

4:后面再优化

 

 

责任编辑:武晓燕 来源: 潜行前行
相关推荐

2021-06-04 18:14:15

阻塞非阻塞tcp

2018-01-11 08:24:45

服务器模型详解

2022-09-06 08:25:13

线程异步任务

2014-10-09 09:48:14

JavaScript

2010-03-16 19:08:03

Java线程同步

2023-06-02 18:37:14

Dubbo异步化接口

2017-12-21 15:48:11

JavaCompletable

2024-01-11 12:14:31

Async线程池任务

2021-02-22 17:18:35

MySQLSQL行锁

2010-03-15 18:34:08

Java多线程

2012-10-10 10:00:27

同步异步开发Java

2020-07-13 09:05:47

2021-11-14 05:00:56

排查Sdk方式

2010-01-28 09:55:05

性能优化

2018-05-17 09:46:40

apachenginx阻塞

2021-06-06 16:56:49

异步编程Completable

2021-08-30 19:00:46

静态CompletableCountDownLa

2022-06-23 06:34:56

Node.js子线程

2023-10-31 08:22:31

线程类型.NET

2021-01-10 11:21:33

JavaScript语言开发
点赞
收藏

51CTO技术栈公众号