问题
系统做压测时发现响应很慢。
通过 mpstat
命令发现CPU使用率很高,并且消耗资源的程序并不是应用本身。
分析
通过 dtrace
查看当前哪些系统调用最花费CPU,结果发现是 fork 系统调用。
fork 是Linux用来产生新进程的,在JAVA中理应没有进程,只有线程。
通过代码分析找到了答案:每个用户请求时都执行了一个外部Shell 脚本来获取一些系统信息,执行脚本是通过 Runtime.getRuntime().exec()
调用的,这种方法是非常消耗资源的,即使脚本本身执行很快,但频繁创建进程的开销非常可观。
JVM执行这个命令的过程:
- 克隆一个和当前虚机拥有一样环境变量的线程。
- 用这个新的进程去执行外部脚本命令。
- 退出这个进程。
所以,不仅是CPU,内存的压力也极大。
解决
去掉Shell脚本的调用,直接使用Java的API获取系统信息,之后应用恢复正常。
网友评论