“遭遇黄牛党”一次系统优化实录

原创 2011年06月11日 16:00:00

不知道从哪天开始,在开启 SchedulerJob(定时任务) 的情况下,产品环境的数据库连接在一天之内全被系统占满了(MySQL开了200个连接),只能重启数据库,重启服务。因为之前在系统中使用了C3p0数据库连接池,猜想可能是c3p0的配置问题或本省的问题?于是去掉数据库连接池,恢复到以前的设置,运行了一天,没有出现问题。没想到跑了两三天之后,后台直接死掉了,查看日志,是EntityManager nullpoint,似乎又是数据库连接拿不到?于是想到了以下的原因:

数据库连接不释放?

可能是运行后数据库连接不释放?长期累积导致数据库连接数耗尽?于是自己写了小测试来调用dao方法,做数据库操作。做了20000次顺序操作,没问题,数据库连接没有超过设定的连接池最大上限。做了3000次(3000个线程)并发操作,总体连接数没有超过数据库连接池的上限(maxPoolSize)上限。这就奇怪了,既然我压力测试dao接口,连接数没出现异常,那问题在哪里?那可能只是跑SchedulerJob的时候出现问题了?

内存占用过多?

将BatchJob的频率提高(每秒一次),使用YourKit对application进行监控,发现内存上升的非常快,没跑到一个小时就把设定的512M最大内存跑完了,请看下面两张图

image

Figure 1 在系统运行的短短一分钟之内,app就使用了近140M内存

image

Figure 2 在不到一个小时的时间之内占用了460M内存,接近设定的head最大值

查看系统Log ,发现系统在不断地产生新的Service类(假设为 SchedulerJobService ),怪不得系统内存消耗得特别快,那在Spring 配置文件中(applicationContext.xml)中将这个service的scope改为singleton不就好了吗?

产生了太多的Spring ApplicationContext(IoC Container)实例!

Spring reference 3. The IoC container

改之,以为万事大吉,再跑,发现还是不断地产生SchedulerJobService,难道scope改错了,查看文档,没错啊。彷徨之际只能再回过头看一下写的代码,我们用的是Quartz来做SchedulerJob的,在执行每一个Job的时候需要拿到 SchedulerJobService 的实例,这个实例当然就配置在Spring ApplicationContext里面啦。问题终于找到了!在拿SchedulerJobService这个Bean的时候我们是这么写的。

private
 ApplicationContext appContext = new
 ClassPathXmlApplicationContext("applicationContext.xml
");

每次都创建了一个ApplicationContext ,当然包括每一个Bean的实例化,Bean之间的依赖关系,以及创建一些数据库连接,这是在ApplicationContext中配置好的。

这就难怪了,不管我在ApplicationContext设置数据库最大连接数还是设置Scope都不管用了。因为现在面临的问题已经超出了单个ApplicationContext的管辖范围了。

假设SechdularJob是15分钟跑一次,那一个小时就会产生4个ApplicationContext, 一天就会产生96个ApplicationContext,即使我限制了在一个ApplicationContext中的最大连接数是10,可是一天下来产生的连接数可能有960之巨。在Mysql中默认的等待时间(wait_timeout)是8个小时,也就是说,一旦创建了一个连接,即使什么都没做,MYSQL也会在8个小时之后关闭这个连接。同时也解释了为什么内存消耗如此快的原因了。

wait_timeout, 详见MySQL system variable:wait_timeout

相关有意思的文章:MySQL wait_timeout default is set too high!

这就好像遇到了黄牛党,虽然每人限购两台,但是派了100 个黄牛过来,一下子就被抢购了200 台。

简单改之,变成静态变量

private
 static
 ApplicationContext appContext = new
 ClassPathXmlApplicationContext("applicationContext.xml
");

保证一个Job只有一个ApplicationContext。改完后测试,问题大大改善,见下面两图

image

Figure 3启动一分钟之后,内存使用相当平稳

image

Figure 4跑了40分钟不到,最大内存也只有120M

内存消耗比较稳定,没有明显的上升趋势。

进一步改进

刚才的那个方案只是保证了每一个Job只产生一个ApplicationContext,如果有两个SchedularJob的话还会产生两个ApplicationContext. 加上原有的一个ApplicationContext(随Web容器启动的),有好几个独立的ApplicationContext,其实他们之间完全可以共享一个ApplicationContext。所以接下来的改进步骤

1. 使用同一个ApplicationContext

2. Quartz使用Spring来管理

延伸阅读

· YourKit – Java Profiler (可选:jconsole, 特方便,JDK自带,但是比较迟钝,仅限不时之需)

· Quartz

· Spring 2.5 docs

相关文章推荐

漫谈千亿级数据优化实践:一次数据优化实录

0x00 前言 即使没有数据倾斜,千亿级的数据查询对于系统也是一种巨大负担,对于数据开发来说,如何来优化它,既是挑战,也是机遇! 在上一篇文章 《漫谈千亿级数据优化实践:数据倾斜(纯干货)》中,我...

一次Java调用OS命令的优化过程实录

1前言 1.1优化目标 人脸识别(FaceRecognition)服务运行在Windows系统的bat文件中,其计算量非常大,运行耗时也比较长(10-20小时),并且在Java程序中使用R...

django练习——博客系统优化

一直准备使用Django搭建一个个人网站,最近终于开始动手,上周已经完成了基本博客功能的搭建(http://blog.csdn.net/hcx25909/article/details/2460133...
  • hcx25909
  • hcx25909
  • 2014年05月03日 20:10
  • 11446

如何进行java系统优化

上面这个核心字多点说也就是:更多用户访问、更短响应时间、数据正确性。    优化的过程,我的想法就是先顺藤摸瓜,沿着一个请求发生的路径一路看过去,测量一下每个点上消耗的时间,会发现很多消耗时间多的点...
  • kubaoer
  • kubaoer
  • 2011年11月18日 22:54
  • 2218

学生信息管理系统优化(一)

任何的系统在完成之前必须得优化,首先你的保证你做出来的软甲得没有正常的逻辑问题,还得提高用户体验,让别人用着比较舒服对吧!     下边我为大家分享一下我的优化心得! 1.登录界面     首先你的保...

Windows系统优化(个人整理)

Windows系统优化,提升电脑运行速度(个人整理)

学生信息管理系统优化(一)

第一个问题就是登陆的时候如果在姓名哪输入 “‘ ’” 单引号会报错的解决方法是         解决方法  1 给姓名的文本框建立个键盘输入事件 2然后就是用ASCI码的方式来禁止输入单引号 Priv...

特效系统优化

http://blog.csdn.net/leo1981816/article/details/5874974     这几天在做特效系统的优化,稍有些心得,分享一下。   首先要讨论的...

Altium Designer系统优化配置

System Data Management Schematic PCB Editor

为SSD编程(5):访问模式和系统优化

原文地址:http://codecapsule.com/2014/02/12/coding-for-ssds-part-5-access-patterns-and-system-optimizatio...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:“遭遇黄牛党”一次系统优化实录
举报原因:
原因补充:

(最多只允许输入30个字)