System.outOfMemoryException 流程未考虑机器性能而报错
突然遭遇 System.outOfMemoryException 错误,我的妈呀,这也太吓人了.
问题起因
一个单元测试的流程,由Oracle到Oracle的流程挂起了,使用事件查看器,错误为:System.outOfMemoryException
如图:
感到问题很奇怪,于是再次设置启动条件,启动该流程,发现消息先是冻结,报同样的错误,再运行再报错,几次后流程挂起.
查找经过
找到出错点,是发送消息到DB,消息返回时报错.
将消息以sql的形式在数据库中执行测试,发现一点问题也没有,很正常.
莫非是人品问题,不会啊,我人品一直很好的.
单元测试能通过,为什么正式部署就有问题呢.
仔细分析异常消息,貌似是说内存不够,为什么呢,突然眼前一亮,想到可能是数据量太大的问题.
再次执行sql文,发现数据有10k多条,并且每个记录都有100多个字段,数据量确实挺大的.
解决方法
从硬件方面着手
现在的硬件配置情况:cpu 2.0 Ghz 内存 8.0 G,客户给的机器已经够好的了,想要客户再增加配置,估计会直接叫我们闪人了.
从流程方面入手
原来的流程设计考虑到的是,只有几k条数据,并且字段不多,为简单起见,直接一次性将数据取出发送.
汗颜先,看来这个设计真是太没远见了!人家客户数据增长的很快,发展很很快,我们的思想跟不上了.
修改设计,在发送的消息中,限制返回的数据数目,将数据分批取出(每次取出3k条),取出一批后设计标记,标明下次数据从最后取走的那个数据后一条开始.
如图:
架构消息中有个maxrows可以控制消息得到的数据记录最大条数,但是不知道设置3k,然后满足条件的有4k,去了max的3k之后,其他的1k条怎么处理了(丢弃?无视?),所以还是自己在程序中控制好了.以后有机会再去研究吧,现在事情本来就忙.
教训总结
一,流程的性能问题,一次性取全部数据,没有想到数据量巨大时,内存爆掉!!!这点确实很重要,有时莫名其妙的错误都是由于没有控制好程序的性能.
二,自己没有好好再考虑,等出了问题才知道错误.自从200707开始接触BTS,在一些前个开发者已经有的流程上,自己的流程思路完全按照搬前一个人,别人没有考虑周全的思路我也直接拿过来用了,导致错误的出现.在软件开发设计中,这点确实很重要,除非可以确定前一个人是个牛人,基本不会犯错.所以我需要去面壁20分钟.
三,总之,自己做设计时,别人考虑好的可以拿来使用,同时自己也要好好想想,还是那句话:开始未解决的问题,在后期需要3倍的时间精力来解决.