Tomcat 假死原因分析报告
最近监控服务发现有台tomcat 的应用出现了无法访问的情况
,由于已做了集群,基本没有影响线上服务的正常使用。下面来简单描述该台tomcat当时具体的表现:客户端请求没有响应,查看服务器端tomcat 的java 进程存活,查看tomcat 的catalina.log ,没有发现异常,也没有error 日志.查看localhost_access.log 也没有最新的访问日志,该台tomcat 已不能提供服务。
根据前面的假死表象,最先想到的是网络是否出现了问题,于是开始从请求的数据流程开始分析。由于业务的架构采用的是nginx + tomcat 的集群配置,一个请求上来的流向可以用下图来简单的描述。
从上图可以看出,如果是网络的原因,可以从两个点进行分析。
1、从前端到nginx的网络情况;
分析nginx上的access.log ,在其中一台上可以查出当时该条请求的访问日志,也就是说可以排除这段网络的问题。
2、从nginx 到tomcat 的网络情况。
分析tomcat 的访问日志localhost_acess.log 上无法查出该条请求的访问日志。可以怀疑是否网络有问题。就该情况,从该台nginx ping 了一下tomcat server ,均为正常,没有发现问题。既然网络貌似没有问题,开始怀疑是tomcat本身的问题,在tomcat本机直接curl 调用该条请求,发现仍然没有响应。到此基本可以断定网络没有问题,tomcat 本身出现了假死的情况。
基于tomcat 假死的情况,开始分析有可能的原因。造成tomcat假死有可能的情况大概有以下几种:
一、tomcat jvm 内存溢出
分析当时的gc.log ,
7581861.927: [GC 7581861.927: [ParNew
Desired survivor size 76677120 bytes, new threshold 15 (max 15)
- age 1: 5239168 bytes, 5239168 total
: 749056K->10477K(898816K), 0.0088550 secs] 1418818K->680239K(8238848K), 0.0090350 secs]
没有发现有内存溢出的情况
直接grep catalina.sh 也没有结果,证明没有发生内存溢出的情况 ,,这种假死可能可以排除。
grep OutOfMemoryException catalina.sh
二、jvm GC 时间过长,导致应用暂停
7581088.402: [Full GC (System) 7581088.402: [CMS: 661091K->669762K(7340032K), 1.7206330 secs] 848607K->669762K(8238848K), [CMS Perm : 34999K->34976K(58372K)], 1.7209480 secs] [Times: user=1.72 sys=0.00, real=1.72 secs]
最近的一次full gc 显示,也不应该会暂停几分钟的情况,这种假死可能可以排除。
三、load 太高,已经超出服务的极限
当时top一下linux
top
load average: 0.02, 0.02, 0.00
Tasks: 272 total, 1 running, 271 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.2%us, 0.2%sy, 0.0%ni, 99.6%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 32950500k total, 23173908k used, 9776592k free, 1381456k buffers
Swap: 33551744k total, 236k used, 33551508k free, 12320412k cached
load 并不是高,,这种假死可能可以排除。
四、应用本身程序的问题,造成死锁。
针对这种情况,做了一下jstack,有少量线程处于TIMED_WAITING。
"Ice.ThreadPool.Client-75" daemon prio=10 tid=0x000000005c5ed800 nid=0x4cde in Object.wait() [0x0000000047738000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00002aab14336a10> (a IceInternal.ThreadPool)
at IceInternal.ThreadPool.followerWait(ThreadPool.java:554)
- locked <0x00002aab14336a10> (a IceInternal.ThreadPool)
at IceInternal.ThreadPool.run(ThreadPool.java:344)
- locked <0x00002aab14336a10> (a IceInternal.ThreadPool)
at IceInternal.ThreadPool.access$300(ThreadPool.java:12)
at IceInternal.ThreadPool$EventHandlerThread.run(ThreadPool.java:643)
at java.lang.Thread.run(Thread.java:619)
"ContainerBackgroundProcessor[StandardEngine[Catalina]]" daemon prio=10 tid=0x00002aacc4347800 nid=0x651 waiting on condition [0x00000000435f7000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1378)
at java.lang.Thread.run(Thread.java:619)
"version sniffer" daemon prio=10 tid=0x00002aacc4377000 nid=0x645 in Object.wait() [0x0000000040f3c000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00002aaaee20b7b8> (a java.lang.Boolean)
at com.panguso.map.web.service.LocateServiceFactory$IpDataVersionSniffer.run(LocateServiceFactory.java:351)
- locked <0x00002aaaee20b7b8> (a java.lang.Boolean)
at java.lang.Thread.run(Thread.java:619)
"ReplicaSetStatus:Updater" daemon prio=10 tid=0x000000005d070800 nid=0x636 waiting on condition [0x0000000044001000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at com.mongodb.ReplicaSetStatus$Updater.run(ReplicaSetStatus.java:428)
从jvm 堆栈信息可以看出,其中有可能出现线程锁死的情况为:IceInternal 和访问mongdb 的客户端 com.mongodb.ReplicaSetStatus$Updater类。针对这两种情况,看了一下源码,基本排除。
五、大量tcp 连接
CLOSE_WAIT
netstat
-n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
TIME_WAIT 48
CLOSE_WAIT 2228
ESTABLISHED 86
常用的三个状态是:ESTABLISHED
表示正在通信,TIME_WAIT
表示主动关闭,CLOSE_WAIT
表示被动关闭。
CLOSE_WAIT
从上面的图可以看出来,如果一直保持在CLOSE_WAIT
状态,那么只有一种情况,就是在对方关闭连接之后,服务器程序自己没有进一步发出ack
信号。换句话说,就是在对方连接关闭之后,程序里没有检测到,或者程序压根就忘记了这个时候需要关闭连接,于是这个资源就一直被程序占着。个人觉得这种情况,通过服务器内核参数也没办法解决,服务器对于程序抢占的资源没有主动回收的权利,除非终止程序运行。
由于咱们自己使用的是HttpClient
,并且遇到了大量CLOSE_WAIT
的情况。所以怀疑这个点可能出了问题。
查看了咱们的httpClient
的写法需要改正:
HttpGet get =
new
HttpGet(url.toString());
InputStream
ins =
null
;
try
{
HttpResponse
response = excuteHttp(httpClient, get);
//
HttpResponse response = httpClient.execute(get);
if
(response.getStatusLine().getStatusCode() != 200) {
throw
new
MapabcPoiRequestException(
"Http
response status is not OK"
);
}
这种写法意味着一旦出现非200
的连接,InputStream ins
根本就不会被赋值,这个连接将永远僵死在连接池里头.
解决方法:
if
(response.getStatusLine().getStatusCode() !=
200) {
get.abort();
throw
new
MapabcPoiRequestException(
"Http
response status is not OK"
);
}
应该改为显示调用HttpGet
的abort
,这样就会直接中止这次连接,我们在遇到异常的时候应该显示调用,因为无法保证异常是在InputStream in
赋值之后才抛出。但是这种情况也是发生在httpClient
后端的服务出现了没有响应的情况,
- 大小: 15.1 KB
- 大小: 13.8 KB
分享到:
相关推荐
Linux定时脚本监控tomcat是否假死或出现运行异常,若出现异常则自动重启。
检测Tomcat等网站假死,自动重启脚本,方便大家下载,可以参考修改。
本文将深入探讨导致Tomcat自动关闭的原因,以便采取有效措施预防和解决此类问题。 ### 1. Tomcat配置不当 Tomcat自动关闭的第一个常见原因是配置不当。这包括但不限于以下几点: - **内存配置**:如果Tomcat的JVM...
对tomcat的gclog日志进行分析,进行可视化展示,可以查看一些配置参数,检查是否软件是否运行正常
Tomcat启动闪退是一个常见的问题,其原因多种多样,针对不同的情况有不同的解决方法。具体问题应该具体分析解决,一般而言我们解决Tomcat启动闪退问题的关键就是在于收集详细的错误信息,结合日志文件、环境配置和...
### Tomcat架构的源码分析 #### 一、Tomcat的架构概述 Tomcat作为一款广泛使用的开源Java Servlet容器,其内部架构设计简洁而高效。本文档将对Tomcat的架构进行详细介绍,并从源码层面深入分析其核心组成部分。...
《Tomcat学习与分析总结资料》是一份涵盖了Tomcat服务器核心知识的综合资源,适合对Java Web应用服务器感兴趣的开发者深入学习。Tomcat是Apache软件基金会的项目,是世界上最流行的开源Servlet容器,它实现了Java ...
tomcat的基础脚本分析 tomcat的源码启动分析 tomcat的web应用启动分析 tomcat的socket分析 tomcat的cocket与容器对接时序分析
在深入分析Tomcat的架构之前,需要了解Tomcat是Apache Jakarta项目中的一个核心项目,是一个免费的开源Servlet容器。它主要用于作为独立服务器或集成到Web服务器中,如Apache和IIS等。作为Web服务器,Tomcat负责解析...
《Tomcat6源码分析——深入理解Web服务器的运行机制》 Tomcat6作为Apache软件基金会的Jakarta项目的一部分,是一款广泛使用的Java Servlet容器,它实现了Java Servlet和JavaServer Pages(JSP)规范,为开发和部署...
Tomcat作为Apache软件基金会旗下的一个开源...通过深入分析Tomcat系统架构,可以更好地理解其工作原理,从而在实际应用中根据需要进行定制和优化。无论是进行开发工作还是系统配置,对Tomcat架构的掌握都显得至关重要。
4. "Tomcat源码分析(4)容器处理链接之责任链模式.doc":分析了Tomcat如何利用责任链模式来处理请求,使得请求可以被多个处理器(如过滤器)有序处理。 5. "tomcat加载类的顺序.doc":详细说明了Tomcat加载类的具体...
在分析Tomcat常见问题时,我们经常会遇到各种各样的错误,这些错误可能涉及到服务器配置、依赖库、系统环境以及应用程序本身。以下是一些常见的问题及其解决方案: 首先,Jdk版本不匹配是导致Tomcat无法正常运行的...
对 NIO 模式,请求的流程描述的很详细。值得去仔细的研究。
tomcat源码分析,tomcat原理分析,底层机制,一些源代码等等
Tomcat是Apache软件基金会下的一个开源项目,是一个广泛使用的Java Servlet容器,特别因为其轻量级、高效能和稳定性而闻名。它实现了Java Servlet和JavaServer Pages(JSP)规范,使得开发者能够用Java语言来编写...
1. **日志分析**:定期分析Tomcat的日志,找出导致服务假死或异常的常见原因,优化系统配置或代码以减少这类问题的发生。 2. **故障转移**:如果可能,可以设置Tomcat集群,当一个节点出现问题时,流量可以自动切换...
tomcat最新客户端tomcat最新客户端tomcat最新客户端tomcat最新客户端tomcat最新客户端tomcat最新客户端tomcat最新客户端tomcat最新客户端tomcat最新客户端tomcat最新客户端tomcat最新客户端tomcat最新客户端tomcat...
Tomcat7、Tomcat8和Tomcat9是不同版本的Tomcat,每个版本都有其特性和改进。 **Tomcat7**: Tomcat7是2011年发布的,它主要支持Java Servlet 3.0和JSP 2.2规范。这个版本引入了一些重要改进,包括增强的安全性、更...