一、故障基本信息

发生时间

消除时间

故障历时

故障类别

影响

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 [net.sf.json.AbstractJSON$CycleSet@73c791f]) and a value of type [java.lang.ref.SoftReference] (value [java.lang.ref.SoftReference@51484b24]) 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是连接池的高级功能,理论上这中配置不应该出现在实际的生产环境,因为有时应用程序执行长事务,可能这种情况下,会被连接池误回收,该种配置一般在程序测试阶段,为了定位连接泄漏的具体代码位置,被开启,生产环境中连接的关闭应该靠程序自己保证。

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

  1. f5会话保持导致站点访问故障

    1.环境: vs Service Port为443和80,vip为10.160.100.66,pool为10.160.45.42/43的8080.80的vs重新到443. 2.问题: 单独访问源站都没 ...

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

    eclipse下修改项目名导致tomcat内发布名不一致的解决方法 . ------------------------------------------------------- 解决方案: 直接 ...

  3. tomcat抬头有“选择”或“选定”,导致tomcat无法运行问题

    2. 遇到tomcat抬头有"选择"或"选定",导致tomcat无法运行问题 解决:在tomcat抬头右键--属性,去掉"快速编辑模式"勾选 ...

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

    package com.diancai.interceptor; import java.io.IOException; import javax.servlet.Filter; import jav ...

  5. MyEclipse异常关闭导致Tomcat不能启动的问题

    由于MyEclipse的异常关闭从而导致Tomcat并没有关闭,所以再次启动Tomcat当然是无法启动的啦,解决方法:在任务管理器中关闭一个叫javaw.exe的进程,如果你这时已经启动了MyEcli ...

  6. SampleDateFormat 高并发下导致 线程 Blocked 从而导致 Tomcat 吞吐一直上不去

    SampleDateFormat 高并发下导致 线程 Blocked 从而导致 Tomcat 吞吐一直上不去

  7. 启动eclipse导致Tomcat的配置文件重置

    转: 启动eclipse导致Tomcat的配置文件重置 导入一个项目,需要在Tomcat的配置文件中配置JNDI数据源,需要修改Tomcat下的server.xml文件.但是当我们修改完后重启Tomc ...

  8. [转帖]御界预警:3700余台SQL服务器被入侵挖矿 或导致严重信息泄露事件

    御界预警:3700余台SQL服务器被入侵挖矿 或导致严重信息泄露事件 https://zhuanlan.kanxue.com/article-8292.htm sqlserver的弱密码破解和提权攻击 ...

  9. 一次tomcat数据乱码事件

    一次环境变量出错导致的tomcat数据乱码事件 1.1 事件起因 由于业务的调整,我们需要将在A服务器上的后台系统迁移到B服务器上的后台,我们选择在下班后进行迁移,因为那个时间点,后台系统已经几乎没有 ...

随机推荐

  1. MongoDB学习笔记(三)

    第三章 索引操作及性能测试 索引在大数据下的重要性就不多说了 下面测试中用到了mongodb的一个客户端工具Robomongo,大家可以在网上选择下载.官网下载地址:http://www.robomo ...

  2. section元素与div、article元素的区别

    section元素是对网站或应用程序中页面上的内容进行分块,一个section元素通常有标题和内容组成.但section元素并非一个普通的容器元素,当一个容器需要直接定义样式或通过脚本定义行为时,推荐 ...

  3. spring boot + mybatis + druid配置实践

    最近开始搭建spring boot工程,将自身实践分享出来,本文将讲述spring boot + mybatis + druid的配置方案. pom.xml需要引入mybatis 启动依赖: < ...

  4. Spring Cloud入门教程-Hystrix断路器实现容错和降级

    简介 Spring cloud提供了Hystrix容错库用以在服务不可用时,对配置了断路器的方法实行降级策略,临时调用备用方法.这篇文章将创建一个产品微服务,注册到eureka服务注册中心,然后我们使 ...

  5. w3school上系统过了一遍Jquery的总结

    下面是今天学习JQUERY中发现的一些小钻石 1:$(document).ready(function(){}); 为了防止文档在完全加载(就绪)之前运行 jQuery 代码(终于搞清了这句代码的含义 ...

  6. werfault进程使用CPU率高

    werfault进程是Windows vista 错误报告进程,是用来向微软反馈报告.是安全的正常进程. 解决方法:1.打开控制面板”—“系统和维护”,点击“问题报告和解决方案”. 2.点击“更改设置 ...

  7. python笔记--2--字符串、正则表达式

    字符串 ASCII码采用1个字节来对字符进行编码,最多只能表示256个符号. UTF-8以3个字节表示中文 GB2312是我国制定的中文编码,使用1个字节表示英语,2个字节表示中文:GBK是GB231 ...

  8. 解决miner.start() 返回null

    下面我列举了三种解决方案,前面两张是某两位大佬试出来的,第三种是我蒙出来的. 第一种解决方案 转载自  http://mp.weixin.qq.com/s/AB9vj1EzOgWT7JyryfQhDg ...

  9. python---购物车---更新

    购物车程序更新: 更新商家入口,实现以下功能: 1. 商家能够修改商品价格: 2. 商家能够下线商品: 3. 商家能够增加商品: 4. 商品信息存在文件中 # -*- coding:utf-8 -*- ...

  10. php插入mysql中文数据出现乱码

    $con = mysqli_connect(DB_HOST, DB_USER, DB_PWD, $dbname) or die('数据库连接失败'); mysqli_set_charset($con, ...