加入收藏 | 设为首页 | 会员中心 | 我要投稿 泉州站长网 (https://www.0595zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长资讯 > 动态 > 正文

敖丙Dubbo线程池事故排查

发布时间:2021-04-18 16:45:15 所属栏目:动态 来源:互联网
导读:个线程因为执行异常而结束,那么线程池会添加一个新的线程。 所以由于dubbo默认采用了直接提交的SynchronousQueue工作队列,所以,所有的task会直接提交给线程池中的某一worker线程,如果没有可用线程,那么会拒绝任务的处理然后抛出我们当前现在遇到的问题

个线程因为执行异常而结束,那么线程池会添加一个新的线程。

所以由于dubbo默认采用了直接提交的SynchronousQueue工作队列,所以,所有的task会直接提交给线程池中的某一worker线程,如果没有可用线程,那么会拒绝任务的处理然后抛出我们当前现在遇到的问题

以下说明下我们创建一个线程池的必要参数 :

  • corePoolSize - 池中所保存的线程数,包括空闲线程。
  • maximumPoolSize-池中允许的最大线程数。
  • keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
  • unit - keepAliveTime 参数的时间单位。
  • workQueue - 执行前用于保持任务的队列。此队列仅保持由 execute方法提交的 Runnable任务。
  • threadFactory - 执行程序创建新线程时使用的工厂。
  • handler 由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序。ThreadPoolExecutor是Executors类的底层实现。

好,看了这么多源码,从上面我们已经了解这个异常来的来源了,那是什么原因导致我遇到的这次的线程池耗尽呢?

排查思路

第一阶段:

由于10.33.xx.xxx这台机器出现线程池耗尽的时候,伴随出现了一次时间比较久的ygc;所以怀疑是因为ygc时间较长,导致了机器资源紧张,从而拖垮了线程池;思考什么原因导致YGC时间这么长:

这里给大家简单说明下为什么IO高会导致GC时间长

1.JVM GC需要通过发起系统调用write(),来记录GC行为。

2.write()调用可以被后台磁盘IO所阻塞。

3.记录GC日志属于JVM停顿的一部分,因此write()调用的时间也会被计算在JVM STW的停顿时间内。

通过GC日志可以看到新生代在进行垃圾回收的时候停顿时间是在3.92s;对于新生代空间在1.8G左右的显然是不正常的;ParNew收集器的工作过程中会出现以下步骤:

(1)标记-标记出来活着的对象 ----> (2) 将对象从eden区复制到survior区 -----> (3)清理eden区

理论上来说第三步的时间是一定的,那可能时间会比较久的要么在第一步,要么在第二步

如果是第一步标记时间过长,就意味着本次GC之前,eden区存在大量的小对象(因为eden区大小是一定的),量级应该是正常的对象数量的数十倍

如果是第二步时间过长的话,那么存在以下可能:

1.标记完之后,eden区还有大量的对象(表现是回收之后新生代的对象占用内存仍然很大),这个从gclog可以排除(回收之后新生代的大小还有39M)

2.标记完之后仍然有大量碎片化的小对象存在

3.YGC出发了fullGC,但是我们没有查看到有关日志

此时以上的情况都指向一种可能,那就是新生代存在大量的碎片化的小对象;

为了验证这个论据,那就只有一种办法就是去分析一下堆快照,但是我们那个时候刚好机器被重起,无法查明原因

在我们无法验证的时候,第二台机器出现了同样的问题,准备再次jump日志的时候,回过头来看了一下GC日志,发现GC正常。所以推翻阶段一结论

这里给大家介绍一些我们常用的服务器命令:

top : 这是最常用的,也是展示信息最全的,可以看到负载,内存,cpu等很多东西

比如使用top常见分析步奏:

1.top -Hp命令,查看具体是哪个线程占用率较高 2.使用pr

(编辑:泉州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!