壹佰网|ERP100 - 企业信息化知识门户

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 1311|回复: 0

关于Smart Upload文件上载应用组件引起CPU资源100%占用问题

[复制链接]
发表于 2012/9/11 16:34:51 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。如果您注册时有任何问题请联系客服QQ: 83569622  。

您需要 登录 才可以下载或查看,没有帐号?注册

x
文件上载应用引起CPU资源100%占用问题

问题现象:
1.不定时出现内存异常增长、GC无法释放并导致JVM崩溃现象,JVM Heap堆被Upload类及其中间数据占满。
2.偶尔出现CPU占用率异常,达到100%,但没有发生JVM崩溃,其他应用也能较正常进行,JVM中有多个Upload进程在持续运行。

问题出现的区域:文档上传过程

问题出现的源头:
1.网络传输延迟/错误
2.操作人员连续多次点击,造成同一文件在数秒内多次上传引起的传输错误。

问题出现的原因:
应用服务器之前装有IHS HTTP服务器,用户在访问过程中,在没有得到后台服务器相应的情况下断开连接,而重新发起新的请求。但由于IHS HTTP中间起着缓冲的作用,客户强行断开连接的异常,后台并不能及时得到,而认为连接正常,导致SmartUpload类持续读InputStream(造成CPU占用异常), 或读取了不完整的文件内容在处理过程中无法结束(造成内存泄漏)。

问题发生机制:
SmartUpload类主体代码可分为两部分(具体代码可参见相关类文件):
Part 1:从ServletHttpStream中连续读取字节流,直至读完。如果其中发生传输或其他系统错误,由Try,Catch进行错误处理。
Part 2:将取出的内容按照Post Content的统一规范进行处理,根据文件的开始、结束标志逐个进行处理,放入File对象(支持多个文件同时上传)。

通过跟踪我们发现,如果在上传文件过程中出现了传输错误(网络延迟、或操作失误),后台应用服务器并没有截获错误,没有触发Try、Catch机制,由此产生了两种错误及其现象,所以我们不能仅仅通过Try/Catch方式来进行判断:
1.ServletHttpStream中一直读不到字节流,相关后台应用服务器没有截获错误,导致SmartUpload类Part1一直在执行,造成CPU一直占用。在这样的情况发生多次后,CPU占用100%。
2.ServletHttpStream没有读完或读取错误,相关后台应用服务器没有截获错误,认为正常读取完成。导致上传文件的开始、结束标志残缺或不匹配,在SmartUpload类Part2处理过程中一直找不到文件结束标志,而不断增加新的File。最终造成内存泄漏。


问题解决方法:
改写SmartUpload代码,增加更全面、合理的条件判别,具体代码如下。(smartupload.jar,SmartUpload Java源代码)
[php]
package com.jspsmart.upload;
……
public class SmartUpload
{
……
    public void upload()
        throws SmartUploadException, IOException, ServletException
    {
        int totalRead = 0;
        int readBytes = 0;
        long totalFileSize = 0L;
        boolean found = false;
                ……
//////// ----- Begin ----- //// Add for protecting Endless Do While Clause      
        int protectEndlessDoWhile = 0;
//////// -----  End  ----- //// Add for protecting Endless Do While Clause

//////// Add condition to determinate the InputStream status, to protect endless reading closed InputStream         
////////  Original code shows as this:
////////                 for(; totalRead < m_totalBytes; totalRead += readBytes)
////////  Revised code shows as:
////////           for(; totalRead < m_totalBytes && readBytes >=0; totalRead += readBytes)

        for(; totalRead < m_totalBytes && readBytes >=0; totalRead += readBytes)
            try
            {
                m_request.getInputStream();
                readBytes = m_request.getInputStream().read(m_binArray, totalRead, m_totalBytes - totalRead);
               
            }
            catch(Exception e)
            {
                throw new SmartUploadException("Unable to upload.";
            }

                ……
        do
        {
//////// ----- Begin ----- //// Add for protecting Endless Do While Clause  
                protectEndlessDoWhile ++;
//////// ----- End   ----- //// Add for protecting Endless Do While Clause


////////  Add condition to protect endless multiple files processing         
////////  Original code shows as this:
////////                 if(m_currentIndex >= m_totalBytes)
////////  Revised code shows as:
////////           if(m_currentIndex >= m_totalBytes || protectEndlessDoWhile >20)        
            if(m_currentIndex >= m_totalBytes || protectEndlessDoWhile >20)
                break;
            dataHeader = getDataHeader();
            m_currentIndex = m_currentIndex + 2;
            isFile = dataHeader.indexOf("filename" > 0;
            fieldName = getDataFieldValue(dataHeader, "name";
                        ……
        } while(true);
    }
……
    private Request m_formRequest;
}
[/php]
您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|Archiver|小黑屋|手机版|壹佰网 ERP100 ( 京ICP备19053597号-2 )

Copyright © 2005-2012 北京海之大网络技术有限责任公司 服务器托管由互联互通
手机:13911575376
网站技术点击发送消息给对方83569622   广告&合作 点击发送消息给对方27675401   点击发送消息给对方634043306   咨询及人才点击发送消息给对方138011526

GMT+8, 2025/11/29 03:26 , Processed in 0.011638 second(s), 14 queries , File On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表