一次诡异的日志死锁
2015-12-05 11:56
429 查看
先说下项目背景,为了统一公司的schedule job,做了一个job的框架,定时任务统一接入到这个框架里面。
job框架用java开发,原理很简单,解析用户输入的crontab表达式,到了schedule的时间,用ProcessBuilder把用户的程序给带起来。
今天有同事反应,程序在本地可以正常运行,接入job框架后出现大量的SOA远程调用timeout。
第一反应是资源文件加载路径的问题,怀疑是不是读错了配置文件,再三检查发现一切无误。
打印线程堆栈后发现,所有的线程都卡死在了logback记日志的地方,大家都在等待一把锁,堆栈里面没能发现谁持有了这个锁对象。
从以下几点着手排查:
1. 怀疑是jar包冲突,job框架本身使用的logback版本和用户程序使用的logback版本冲突。于是一番折腾,无果。
2. 怀疑是SOA框架里面记日志的地方有冲突,再三check,还是无果。
然后发现用户的log配置,除了写磁盘以外,还会输出到console,于是改了下配置文件,不再输出到console,发现不再死锁。
于是赶紧的查了下jdk里面关于process的描述,摘录如下:
By default, the created subprocess does not have its own terminal or console. All its standard I/O (i.e. stdin, stdout, stderr) operations will be redirected to the parent process, where they can be accessed
via the streams obtained using the methods
and
The parent process uses these streams to feed input to and get output from the subprocess. Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream
of the subprocess may cause the subprocess to block, or even deadlock.
子进程是没有自己的console的,标准输出会redirect给自己的父进程。子进程输出到操作系统的buffer里面,等待着父进程从inputstream里面读出数据,如果父进程没有读,那么一旦buffer满了,子进程就会处于waiting状态,等待buffer清空,造成死锁。
看了这段描述后,真相大白了,job框架不会去读用户输出到ocnsole的信息,从而导致了死锁。
解决方法后很简单,禁止用户输出到console,日志直接写磁盘。
job框架用java开发,原理很简单,解析用户输入的crontab表达式,到了schedule的时间,用ProcessBuilder把用户的程序给带起来。
今天有同事反应,程序在本地可以正常运行,接入job框架后出现大量的SOA远程调用timeout。
第一反应是资源文件加载路径的问题,怀疑是不是读错了配置文件,再三检查发现一切无误。
打印线程堆栈后发现,所有的线程都卡死在了logback记日志的地方,大家都在等待一把锁,堆栈里面没能发现谁持有了这个锁对象。
从以下几点着手排查:
1. 怀疑是jar包冲突,job框架本身使用的logback版本和用户程序使用的logback版本冲突。于是一番折腾,无果。
2. 怀疑是SOA框架里面记日志的地方有冲突,再三check,还是无果。
然后发现用户的log配置,除了写磁盘以外,还会输出到console,于是改了下配置文件,不再输出到console,发现不再死锁。
于是赶紧的查了下jdk里面关于process的描述,摘录如下:
By default, the created subprocess does not have its own terminal or console. All its standard I/O (i.e. stdin, stdout, stderr) operations will be redirected to the parent process, where they can be accessed
via the streams obtained using the methods
getOutputStream(),
getInputStream(),
and
getErrorStream().
The parent process uses these streams to feed input to and get output from the subprocess. Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream
of the subprocess may cause the subprocess to block, or even deadlock.
子进程是没有自己的console的,标准输出会redirect给自己的父进程。子进程输出到操作系统的buffer里面,等待着父进程从inputstream里面读出数据,如果父进程没有读,那么一旦buffer满了,子进程就会处于waiting状态,等待buffer清空,造成死锁。
看了这段描述后,真相大白了,job框架不会去读用户输出到ocnsole的信息,从而导致了死锁。
解决方法后很简单,禁止用户输出到console,日志直接写磁盘。
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树
- [原创]java局域网聊天系统