问题背景

​ 早上才上班,测试就提了一个问题:"昨天所有批量任务都没有跑"。我看了一下任务监控页面,任务是有生成的,但却一直在等待调度状态。初步怀疑是我们的调度服务问题,于是上去查看调度服务日志。

​ 从日志上观察,发现没有调度日志。正常情况下即使没有任务,也会有日志输出,说明没有任务需要调度。于是怀疑调度线程没启动。

​ 说明一下背景:我们的调度服务主要由调度线程和任务线程组成,调度线程定时扫描任务表,发现有任务需要调度就启动任务线程处理。

初步定位问题

​ 查看代码,发现调度线程在spring bean初始化时启动的。 没有任何分支,理论上应该不可能没启动。

​ 回去查看日志,发现调度服务启动时,调度线程是有正常启动的。而且之后调度很正常,一直到昨天下午五点多之后突然就没有调度线程的日志了。

​ 这里突然想起来,昨天下午五点多的时候,测试做了压测,结果导致服务器都登录不上。(登录时提示:“fork: retry:资源不可用”)

​ 后来使用root登录后杀掉一些进程,才恢复正常。(linux会给root用户保留一些资源,方便管理员处理系统故障)

​ 当时检查,发现原来是最大进程数设置成1024,但我们服务器上部署了几个java服务,每个服务又开了很多线程。压测时线程数上升,导致系统资源耗尽。

​ 于是初步怀疑是当时资源耗尽引起调度线程的问题,但具体是怎么引起的,还需要再进一步确认。

确认问题

​ 先尝试使用jstack查看调度服务线程,想看一下是不是调度线程因为什么锁卡住了。输出结果发现一个奇怪的情况:调度线程不见了。

于是猜测:难道是昨天下午压测时资源不足,引起了调度线程出异常?(因为调度线程需要开启任务线程,任务线程因为当时系统资源不足,肯定开启失败)

​ 上网搜索了一下,发现其他人也碰上过类似情况。解决方法是增加Catch Throwable,这样可以防止线程退出。

​ 考虑到Catch Throwable可能导致虚拟机一些异常无法恢复,影响后续功能。我直接打印了日志退出。

问题复现与复测以及防止

​ 由于比较忙,没做复现。修改了代码让测试重新压测一下,发现问题没再发生。到此告一段落。

这次学习到了几个知识点:

1 java服务里面线程崩溃不会引起进程退出,这跟我以前写c++的经验是不一样的。

2 java的Error不是Exception的子类,只是捕获Exception不能防止线程因为出现OOM而退出

3 OOM包括了好多种情况,无法创建线程是其中一种。全部情况如下:

java.lang.OutOfMemoryError:Javaheap space

堆内存(Heap Space)没有足够空间存放新创建的对象

Java 进程花费 98% 以上的时间执行 GC,但只恢复了不到 2% 的内存,且该动作连续重复了 5 次

永久代(Permanent Generation)已用满,通常是因为加载的 class 数目太多或体积太大

Metaspace 已被用满

JVM 向底层操作系统请求创建一个新的 native 线程时,如果没有足够的资源分配

所有可用的虚拟内存已被耗尽

操作系统OOM Killer关闭进程

程序请求创建的数组超过最大长度限制

Direct ByteBuffer超出限制,就会抛出

解决了一个java服务线程退出的问题的更多相关文章

  1. 停止一个java的线程执行

    找了一个停止线程运行的方法,代码如下: public class stopThread extends Thread { private volatile boolean stop = false; ...

  2. 记一次生产事故的排查与优化——Java服务假死

    一.现象 在服务器上通过curl命令调用一个Java服务的查询接口,半天没有任何响应.关于该服务的基本功能如下: 1.该服务是一个后台刷新指示器的服务,即该服务会将用户需要的指示器数据提前计算好,放入 ...

  3. Java服务,内存OOM问题如何快速定位? (转)

    转自:公众号  架构师之路 问题:有一个Java服务出现了OOM(Out Of Memory)问题,定位了好久不得其法,请问有什么好的思路么? OOM的问题,印象中之前写过,这里再总结一些相对通用的方 ...

  4. Docker学习6:使用docker构建Jekyll服务和java服务

    写在前面 ## 文章Dockerfile中涉及apt-get 等操作需更换镜像 在Dockerfile中添加下列 Dockerfile源码,见下面作者githubhttps://github.com/ ...

  5. java中如何使正在运行中的线程退出

    终止线程的三种方法      有三种方法可以使终止线程.      1.  使用退出标志,使线程正常退出,也就是当run方法完成后线程终止.      2.  使用stop方法强行终止线程(这个方法不 ...

  6. 用Java开发一个本地服务管理软件

    一.最终界面先贴上最终效果图,图1为初始化界面,图二为点击启动/停止之后的中间过渡状态,图三为启动成功后弹出的提示框 把动态gif图片嵌入到jpg背景图中?用Adobe ImageReady即可办到 ...

  7. Java多线程-----线程安全及解决机制

    1.什么是线程安全问题? 从某个线程开始访问到访问结束的整个过程,如果有一个访问对象被其他线程修改,那么对于当前线程而言就发生了线程安全问题: 如果在整个访问过程中,无一对象被其他线程修改,就是线程安 ...

  8. JAVA的StringBuffer类(转载整理)____非常重要的一个类,线程安全,不用每次创建一个对象,以及和String的区别

    核心部分转载自:http://www.cnblogs.com/springcsc/archive/2009/12/03/1616330.html StringBuffer类和String一样,也用来代 ...

  9. java 使用线程做一个简单的ATM存取款实例.(转)

    线程 Thread 类,和 Runable 接口 比较两者的特点和应用领域. 可以,直接继承线程Thread类.该方法编写简单,可以直接操作线程,适用于单重继承情况,因而不能在继承其他类 实现Runn ...

随机推荐

  1. WPF之小米Logo超圆角的实现

    某些新闻:小米logo换新,程序员一行代码(border-radius:19px)实现,目前此行代码价值200万 某程序员内心:所以还是因为我代码写太少了,所以这200万才没有我的份吗? 这事儿也成功 ...

  2. 日志功能 - 使用 conf 配置文件

    配置文件:Logger.conf 工具类:LogUtil.py 测试类:testDemo.py 执行效果 配置文件:Logger.conf 定义日志的类型.级别.格式等信息. [loggers] # ...

  3. php中var关键字用法

    见很多朋友说在php中定义变量用不用var都没关系,其实不然. 看看例子,如果我这样使用var: 1 var $a=123; 2 echo $a; 3 //那么程序会提示语法错误,要去掉var这个变量 ...

  4. Linux启动流程和服务管理(init和systemd)

    目录 一:Linux启动流程 init和Systemd的区别 二:Linux服务管理(service,systemctl) 一:Linux启动流程 Rhel6启动过程: Rhel7启动过程: GRUB ...

  5. POJ2391 Floyd+离散化+二分+DINIC

    题意:       有n个猪圈,每个猪圈里面都有一定数量的猪(可能大于当前猪圈的数量),每个猪圈都有自己的容量,猪圈与猪圈之间给出了距离,然后突然下雨了,问多久之后所有的猪都能进圈. 思路:     ...

  6. 利用DNS进行命令控制和搭建隧道

    目录 利用DNS进行命令控制(DNS-Shell) 利用DNS搭建隧道 利用DNS进行命令控制(DNS-Shell) DNS-Shell是一款通过DNS信道实现交互式Shell的强大工具,该工具的服务 ...

  7. 安装google cloud sdk报错解决方法总结(超全)

    前提:python环境最好是2.7,如果是python3可能会出很多小毛病:能用64位系统就尽量用64位,32位系统安装也很多毛病 一.Error1:Unzip Failed: Error openi ...

  8. FlinkSQL使用自定义UDTF函数行转列-IK分词器

    一.背景说明 本文基于IK分词器,自定义一个UDTF(Table Functions),实现类似Hive的explode行转列的效果,以此来简明开发过程. 如下图Flink三层API接口中,Table ...

  9. SpringBoot整合JWT

    JWT (整合SpringBoot) 1. 引入依赖 <!-- 引入JWT --> <dependency> <groupId>com.auth0</grou ...

  10. Servlet三大域对象

    Servlet三大域对象的应用 request.session.application(ServletContext) ServletContext是一个全局的储存信息的空间,服务器开始就存在,服务器 ...