记录一波由会话堵塞导致tomcat应用故障事件

一、故障基本信息


发生时间


消除时间


故障历时


故障类别


影响


2018-5-17 18:14:30


2018-05-18 08:58:15


16小时


应用故障


业务瘫痪,用户投诉

二、故障现象

APP无法登陆,导致大面积投诉。

三、故障分析

1.查看系统2018-5-17 17:23:47时catalina日志显示 ORA-00060等待资源时检测到死锁,且2018-5-17 18:11后无日志生成。

2.查看数据库显示与2018-05-17 17:23:12分时产生死锁现象,生成数据报告,分析如下:

3.tomcat应用日志2018.5.17号存在疑似内存泄漏告警

五月 17, 2018 4:56:51 下午 org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc

严重: The web application [/manage] registered the JDBC driver [oracle.jdbc.OracleDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.   –内存泄漏告警

五月 17, 2018 4:56:51 下午 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads

严重: The web application [/manage] appears to have started a thread named [Dispatcher-Thread-3] but has failed to stop it. This is very likely to create a memory leak.

五月 17, 2018 4:56:51 下午 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads

严重: The web application [/manage] appears to have started a thread named [oracle.jdbc.driver.BlockSource.ThreadedCachingBlockSource.BlockReleaser] but has failed to stop it. This is very likely to create a memory leak.

五月 17, 2018 4:56:51 下午 org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks

严重: The web application [/manage] created a ThreadLocal with key of type [net.sf.json.AbstractJSON.CycleSet] (value [[email protected]]) and a value of type [java.lang.ref.SoftReference] (value [[email protected]]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.

五月 17, 2018 4:56:51 下午 org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks

注:Java不需要管理内存的分配和释放,一切由JVM自己来进行处理,当Java对象不再被应用时,等到堆内存不够用时JVM会进行GC处理,清除这些对象占用的堆内存空间,但是如果对象一直被应用,那么JVM是无法对其进行GC处理的,那么我们创建新的对象时,JVM就没有办法从堆中获取足够的内存分配给此对象,这时就会导致内存溢出(OOM)。出现OOM原因,一般都是因为不断的往容器里存放对象,然而容器没有相应的大小限制或清除机制,这样就容易导致OOM。

4.oracle awr性能报告(SQL部份截取)

1)      上面是sql语句执行时间排序,主要是更新商家信息账户信息表及账户系统账户信息表余额,分别excutions执行了300多次,Elapsed Time per Exec (s)平均一个update执行时间(单位:秒),即每次update 5分钟左右。

2)      第1个sql:update PAY_CST_ACC set PCA_TOTALBANLANCE =( PCA_TOTALBANLANCE-:1 ), PCA_AVABANLANCE =(PCA_AVABANLANCE-:2 ) where PCA_CSTNO =:3 and PCA_USERACC=:4,花了325秒,即5分钟左右,此时已经不正常。

因为oracle对数据增删改查的操作机制,都需要将数据从磁盘调到内存操作,操作完commit提交后再根据一定规则刷到磁盘(如果该记录原先已被其它会话操作调在内存,则直接从内存读取)。连接会话操作数据都要占内存,如果应用众多并发会话连接没释放,则到后面的连接内存不够用了,等待前面的语句操作完释放,如果出现多个并发操作同一记录并锁住其它连接要用的记录等资源,则出现死锁。具体处理建议请见第五章。

四、故障处理

临时处理:分别Kill掉服务器tomcat进程,会话连接断开,重启应用问题解决。

五、故障预防建议

系统tomcat应用连库配置路径:xx/conf/context.xml,代码如下:

<Resource name="jdbc/ebank_ds" type="javax.sql.DataSource"

        driverClassName="oracle.jdbc.OracleDriver"

        url="jdbc:oracle:thin:@xxxx:1521/实例名"

        username="数据库用户名"

        password="密码"

        maxActive="2000"

        maxIdle="30"

        maxWait="9000"/>

综合上述应用日志提示内存泄漏告警以及和oracle数据库日志提示检测到等待资源死锁,以及oracle awr性能报告。建议优化tomcat连接池参数,修改前建议先在测试和验证环境模拟生产环境高并发连接测试,验证有效后再修改生产配置。

增加和修改连接池参数如下:

<!--maxActive: 最大连接数量-->   

        <property name="maxActive" value="2000"/> 

        <!--minIdle: 最小空闲连接-->   

        <property name="minIdle" value="5"/> 

        <!--maxIdle: 最大空闲连接-->   

        <property name="maxIdle" value="30"/> 

        <!--initialSize: 初始化连接-->   

        <property name="initialSize" value="20"/> 

        <!-- 连接被泄露时是否打印 --> 

        <property name="logAbandoned" value="true"/> 

        <!--removeAbandoned: 是否自动回收超时连接-->   

        <property name="removeAbandoned"  value="true"/> 

        <!--removeAbandonedTimeout: 超时时间(以秒数为单位)-->   

        <property name="removeAbandonedTimeout" value="10"/>

        <!--maxWait: 超时等待时间以毫秒为单位--> 

        <property name="maxWait" value="10000"/> 

        <!-- 在空闲连接回收器线程运行期间休眠的时间值,以毫秒为单位. --> 

        <property name="timeBetweenEvictionRunsMillis" value="10000"/> 

        <!--  在每次空闲连接回收器线程(如果有)运行时检查的连接数量 --> 

        <property name="numTestsPerEvictionRun" value="10"/> 

        <!-- 1000 * 60 * 30  连接在池中保持空闲而不被空闲连接回收器线程--> 

        <property name="minEvictableIdleTimeMillis" value="10000"/>  

        <property name="validationQuery" value=" select 1 from dual "/>

站点修改应用tomcat连接池配置路径:xx/ applicationContext.xml

<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>

       <property name="url" value="jdbc:oracle:thin:@xx:1521:实例名"/>

                <property name="username" value="数据库用户名" />

                <property name="password" value="密码" />

                <property name="initialSize" value="5" />

                <property name="maxActive" value="2000" />

                <property name="defaultAutoCommit" value="true" /> 

修改成与账户系统一致的连接参数。

具体连接参数说明请参考tomcat 7官网链接说明:https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html

附:连接参数的几点说明

maxActive="100"

表示并发情况下最大可从连接池中获取的连接数。如果数据库不是单独,供一个应用使用,通过设置maxActive参数可以避免某个应用无限制的获取连接对其他应用造成影响,如果一个数据库只是用来支持一个应用那么maxActive理论上可以设置成该数据库可以支撑的最大连接数。maxActive只是表示通过连接池可以并发的获取的最大连接数。连接的获取与释放是双向,当应用程序并发请求连接池时,连接池就需要从数据库获取连接,那么但应用程序使用完连接并将连接归还给连接池时,连接池是否也同时将连接归还给数据库呢?很显然答案是否定的,如果那样的话连接池就变得多此一举,不但不能提高性能,反而会降低性能,那么但应用成归还连接后,连接池如何处理呢?

maxIdle="30"

如果在并发时达到了maxActive=100,那么连接池就必须从数据库中获取100个连接来供应用程序使用,当应用程序关闭连接后,由于maxIdle=30,因此并不是所有的连接都会归还给数据库,将会有30个连接保持在连接池种中,状态为空闲。

minIdle=”2”

最小默认情况下并不生效,它的含义是当连接池中的连接少有minIdle,系统监控线程将启动补充功能,一般情况下我们并不启动补充线程。

问题:如何设置maxActivemaxIdle

理论上讲maxActive应该设置成应用的最大并发数,这样一来即便是在最大并发的情况下,应用依然能够从连接池中获取连接,但是困难时的是我们很难准确估计到最大并发数,设置成最大并发数是一种最优的服务质量保证,事实上,如果某个用户登录提示系统繁忙,那么在他再次登录时,可能系统资源已经充足,对于xx系统我们建议将maxActive设置为系统注册人数的十分之一到二十分之一之间。例如系统的注册人数为1000,那么设置成50-100靠近100的数字,例如85或90。

maxIdle对应的连接,实际上是连接池保持的长连接,这也是连接池发挥优势的部分,理论上讲保持较多的长连接,在应用请求时可以更快的响应,但是过多的连接保持,反而会消耗数据库大量的资源,因此maxIdle也并不是越大越好,同上例我们建议将 maxIdle设置成50-100中靠近50的数字,例如55。这样就能在兼顾最大并发同时,保持较少的数据库连接,而且在绝大多情况,能够为应用程序提供最快的相应速度。

removeAbandoned="true"

removeAbandonedTimeout="60"

logAbandoned="true"

有时粗心的程序编写者在从连接池中获取连接使用后忘记了连接的关闭,这样连池的连接就会逐渐达到maxActive直至连接池无法提供服务。现代连接池一般提供一种“智能”的检查,但设置了removeAbandoned="true"时,当连接池连接数到达(getNumIdle() < 2) and (getNumActive() > getMaxActive() - 3)时便会启动连接回收,那种活动时间超过removeAbandonedTimeout="60"的连接将会被回收,同时如果logAbandoned="true"设置为true,程序在回收连接的同时会打印日志。removeAbandoned是连接池的高级功能,理论上这中配置不应该出现在实际的生产环境,因为有时应用程序执行长事务,可能这种情况下,会被连接池误回收,该种配置一般在程序测试阶段,为了定位连接泄漏的具体代码位置,被开启,生产环境中连接的关闭应该靠程序自己保证。

原文地址:https://www.cnblogs.com/Dev0ps/p/9077956.html

时间: 2024-08-04 15:13:47

记录一波由会话堵塞导致tomcat应用故障事件的相关文章

eclipse下修改项目名导致tomcat内发布名不一致的解决方法

这几天做了一个项目,后来因为一点原因需要修改Javaweb项目的名称,点击项目的名称->右键Refactor->Rename...  输入要修改的项目名称,保存后,部署到tomcat,突然发现eclipse下修改项目名导致tomcat内发布名不一致了 ,郁闷了,开始在网上找到解决办法,我是看 http://blog.chinaunix.net/uid-25820084-id-3531608.html 这个网站的kimutaku001的ChinaUnix博客位朋友的博客,解决了这个问题,我吧他说

导致Tomcat启动过程缓慢的原因及解决方法

1.现象 在CentOS启动Tomcat时,启动过程很慢,需要几分钟,经过查看日志,发现耗时在这里:是session引起的随机数问题导致的.Tocmat的Session ID是通过SHA1算法计算得到的, 计算Session ID的时候必须有一个密钥.为了提高安全性Tomcat在启动的时候会通过随机生成一个密钥. 22-Apr-2017 19:33:07.623 INFO [localhost-startStop-1] org.apache.catalina.util.SessionIdGene

产品线上问题记录一:启动页仅记录时间未检查升级,导致不能弹出自动更新弹窗

记软件测试线上问题一: 启动页仅记录时间未检查升级,导致不能弹出自动更新弹窗 上线日期: V1.2.0 2016年12月20日 V1.3.1 2017年2月23日 问题经过描述: 最新版本集成了一个文件,所以领导要运营数据,然后发现不弹自动升级弹窗,只能手动更新,查看版本使用用户的时候发现近50%用户在使用老版本V1.2.0,并未升级,数据如下: 1.0版本数量168,1.1.0版本数量6562,1.1.1版本数量9286,1.2.0版本数量19679,1.3.0版本数量2829,1.3.1版本

freecms编程中几种可能导致tomcat崩溃的bug

这里说的bug,不是指的freecms本身的bug,是使用freecms时,由于自己的大意可能挂掉tomcat,甚至内存爆掉以后,连mysql, nginx等也会挂掉的bug.Tomcat挂了后,会出现502错误 1. mybatis的mapper.xml没有部署好 2. 数据库中free_operbutton错误,其实这个bug导致tomcat被爆,也暴露了freecms的鲁棒性不高.

解决Myeclipse中端口占用,导致tomcat无法启动的问题。(Linux)

本文出自:http://blog.csdn.net/svitter 引文:http://www.2cto.com/os/201305/209285.html { ubuntu查看占用某端口的程序 查看端口使用情况,使用netstat命令. 查看已经连接的服务端口(ESTABLISHED netstat -a 查看所有的服务端口(LISTEN,ESTABLISHED) netstat -ap 查看8080端口,则可以结合grep命令:netstat -ap | grep 8080 如查看8888端

因redis线程池挂起导致tomcat无响应

上周线上服务器突然出错,tomcat服务莫名其妙的无响应,查看内存和cpu,一切正常,查看nginx日志,发现一直返回499的错误码,看来是程序里面某一处出错,导致tomcat挂起.没啥好办法,线程,堆dump出来之后,重启tomcat服务,应用恢复正常. 分析了dump出来的堆之后,发现有5百多的redis的连接挂起在那里,查看了redis连接池的配置,发现一个pool最多500个,再仔细查看代码,发现代码逻辑有问题,当应用传入一个key,从redis里面获取一个值,如果该key不存在,代码里

filter 死循环(tomcat 启动完成 ,自动执行filter.dofilter,导致tomcat 启动超时) , tomcat 启动和 servers 启动 不同

package com.diancai.interceptor; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.se

[小问题笔记(二)] 可能导致DropDownList的SelectedIndexChanged事件不触发的几种情况

遇到SelectedIndexChanged事件没有触发,可以依次检查以下几种情况是否在程序中出现. 一.DropDownList的不同option设置了相同的value . 二.没有写 AutoPostBack="True" <asp:DropDownList id="BuDropDownList" runat="server" AutoPostBack="True"></asp:DropDownList&

解决linux系统下因分区目录划分过小,导致tomcat使用系统临时文件夹(/tmp)没有足够空间而报错的问题

1. 故障现象. B/S应用进行文件上传后,系统反馈:没有足够的磁盘空间(No enough space available). 2. 故障分析 检查文件占用情况如下: [root@Qa2 /]# df -h Filesystem Size Used Avail Use% Mounted on /dev/mapper/centos-root 6.7G 6.7G 20k 100% / devtmpfs 7.8G 0 7.8G 0% /dev tmpfs 7.8G 0 7.8G 0% /dev/sh