该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2007-04-29
nihongye 写道 fins 写道 programmer 写道 解决你的 excel问题,可以考虑生成csv。先在服务器生成一个临时文件来存放csv问题,然后查询数据,取数据放入stringBuffer 当此stringBuffer的数据大到一定程度时候就往文件里输出,然后清空StringBuffer 这样重复处理,直到查询出来的数据都写人文件。这样因该可以避免java的outofmemory。
类似的方法我们用过 我们是直接将 response.getOutputStream传入dao 在dao里生成 printwriter 然后直接 out.print 这个方法应该更好 避免了生成和修改文件 如果是直接使用response,这是不好的办法.可能因为io阻塞,导致对象不能及时释放。 Wrapper一个Response,写到自己实现的ByteArrayOuputStream 这样生成的ByteArrayOuputStream会不会也是大对象呢?? |
|
返回顶楼 | |
发表时间:2007-04-30
可以算...,并发数量是500,每个大小是1m的话,那是500 * 1m = 500m。而如果io阻塞,每个请求都得不到释放。每个请求的临时对象是5m,那就,垃圾回收又不停在浪费cpu,继续导致。。我说的好象很象真的一样。试试才知道咯...
|
|
返回顶楼 | |
发表时间:2007-05-01
Lucas Lee 写道 1. 对于生成xls文件,我有一些经验。我用的POI。我发现,对于同样是将2万行的数据写入一个文件,放在一个sheet里和两个sheet里,内存占用能相差一倍,后者少。经过我的试验,一般一个sheet里1万行(一行有10几列)比较合适,多的就分sheet保存,可以有效的降低内存占用,约1--n倍。虽然不是终极的解决方案,也是一个可行的方案,不妨试试。 Lucas Lee说的有道理。我以前做HR产品,也有过类似经历。当从花名册导出XLS时,有时表格CELL超过100万,极易内存溢出。 改进途径: 1.修改Java Plugin 内存参数,效果不大; 2.当要导出的数据单元格超过10万时,输出不是一个而是多个XLS文件,也就是一拆多(以10万单元格为一单位),可有效避免大对象。 对极占用资源(如内存)的任务,应考虑“生产者-消费者模型+内存池”模型。数据由生产者(查询过程)从服务器端查询到内存池,消费者处理完数据从内存池移除旧数据...循环往复直到处理完毕。 |
|
返回顶楼 | |
发表时间:2007-05-01
什么啊?这样的问题,呵呵,你们居然一定要在内存中解决所有的数据吗?无论如何,这个思路,都会遇到out of memory问题的。
1. 修改查询方式,不要生成collection,因为无论你的内存多大,随着业务的增长,数据量只会变大,内存是永远不够的。 2. 如果可以使用简单的流式文件格式生成输出,尽可能使用流式文件,什么是“流”式文件?就是不可逆向移动文件指针的字节流,这样的流可以很少使用内存,stdout, response就是典型的流式文件。对你现在的问题,csv, XLS的html格式都很合适。 3. 我曾经输出过一些大量数据行的报表,查询时,直接使用jdbc,循环fetch一行rowset,然后把数据填到格式化的htmlString中,response.write(htmlString); 再fetch下一行,这是最基本的jdbc fetch循环,好像这里每一个人都忘记了最基本的技能,这样的查询加输出根本不需要应用服务器的内存(当然还是要一点点的,基本上只有那一行rowset的内存就够了)。你甚至可以把response的buffer关掉,这样你的客户端,就可以看到类似行打印机一样的输出效果,呵呵,我的客户还比较喜欢这个效果,她说看着数据一行一行的输出比坐等5分钟白屏幕,然后瞬间看到结果更有安全感和成就感 现在,问题的关键就是,你能不能使用流式的输出字节流了,不使用字节流,这样的大量数据,逻辑上是没有一个简单的解决办法的。前面有人提了n个复杂的方法,疯掉了,还是KISS原则,仔细考虑一下。 想一下啊,你们谁见过哪一个数据库提供的查询工具,在做 select * from table_with_huge_lines; 的时候是在内存中把数据格式化好了再输出的??开玩笑 |
|
返回顶楼 | |
发表时间:2007-05-05
嘿,本人在些论坛已潜水多年,今天也来凑个热闹.
我个人认为,楼上的兄弟些提出了如此多的思路,虽然很开阔,但不真正实用.正如楼主所说,导致OutOfMemory的问题其实并非技术因素,而是需求和设计上的缺陷.事实上,楼上已经有一位兄弟给出了一个较实用且常用的方案:用时间换空间. 诸如电信及银行这样的海量数据应用中,几乎没有任何一个系统是真正做到了实时下载的.且不说OutOfMemory,当下载该文件的工作就是一个大问题,每个Server上所能接受的并发线程是有限的,如果太多用户在下载资源,就必然会导致系统的吞吐率极巨下降,这导致其它用户连一个简单的请求也都做不了,甚至如果这其中出现了锁表或线程挂起的情况将会使整个系统停止服务,这是致命的. 而事实上,或许用户并非真的就非常迫切地要求实时下载,往往一种更常见的作法就是在查询出结果后,通过将结果进行保存后,再稍后下载即可.换句话说就是用户在界面上点击"导出到文件"时,并非真正执行下载,而是将任务加入一个队列,由后台异步地并限制并发量地执行,将结果文件产生后存于文件系统,当文件生成完毕后,用户便可在界面上点击下载文件了.且该文件下载功能最好单独开启一个Server,该Server就只负责文件下载任务,这样就不会影响到系统的正常服务了.对于资源紧缺的用户来说,可以在一台机器上启动两个Server,也可以是垂直集群的方式.不用担心CPU的瓶颈,大多数的应用其实如果只跑一个Server,那么该台机器的CPU事实上是非常闲的. |
|
返回顶楼 | |
发表时间:2007-05-07
langds 写道 嘿,本人在些论坛已潜水多年,今天也来凑个热闹.
我个人认为,楼上的兄弟些提出了如此多的思路,虽然很开阔,但不真正实用.正如楼主所说,导致OutOfMemory的问题其实并非技术因素,而是需求和设计上的缺陷.事实上,楼上已经有一位兄弟给出了一个较实用且常用的方案:用时间换空间. 诸如电信及银行这样的海量数据应用中,几乎没有任何一个系统是真正做到了实时下载的.且不说OutOfMemory,当下载该文件的工作就是一个大问题,每个Server上所能接受的并发线程是有限的,如果太多用户在下载资源,就必然会导致系统的吞吐率极巨下降,这导致其它用户连一个简单的请求也都做不了,甚至如果这其中出现了锁表或线程挂起的情况将会使整个系统停止服务,这是致命的. 而事实上,或许用户并非真的就非常迫切地要求实时下载,往往一种更常见的作法就是在查询出结果后,通过将结果进行保存后,再稍后下载即可.换句话说就是用户在界面上点击"导出到文件"时,并非真正执行下载,而是将任务加入一个队列,由后台异步地并限制并发量地执行,将结果文件产生后存于文件系统,当文件生成完毕后,用户便可在界面上点击下载文件了.且该文件下载功能最好单独开启一个Server,该Server就只负责文件下载任务,这样就不会影响到系统的正常服务了.对于资源紧缺的用户来说,可以在一台机器上启动两个Server,也可以是垂直集群的方式.不用担心CPU的瓶颈,大多数的应用其实如果只跑一个Server,那么该台机器的CPU事实上是非常闲的. 单独开启一台服务器的方式 可以避免生成文件下载文件是对其他服务的影响 可以参考, 不过会增加企业的成本 ps:这种横向服务转纵向服务的方式可以解决很多webserver的问题 |
|
返回顶楼 | |
发表时间:2007-05-10
对于excel文件导出生成的问题,我建议不要用poi或jxl之类的工具包去生成文件,我们可以用xml+xsl->xml->把生成的xml另存为excel文件的形式。大家知道office2000之后的版本都支持xml格式.
|
|
返回顶楼 | |
发表时间:2007-05-10
对于打印,建议使用jasper report,在collection中放入大量数据是会让垃圾回收器回收不到。应当强制手动的进行垃圾收集。
|
|
返回顶楼 | |
发表时间:2007-05-11
ahuaxuan 写道 fins 写道 打印就是用的浏览器的,但是也是打印全部(在隐藏帧里显示一个简单的表格,然后调用window.print 我也知道这方案不好,但是还有别的方法吗?)
这种打印挺好的,其他方法比如jasperreport生成pdf打印,或者applet打印,但是我觉得js打印是最好的 好象不能控制范围吧,java控制的打印方式是什么呢? |
|
返回顶楼 | |
发表时间:2007-05-12
使用Cache服务器吧;将一些实时性不强的数据采取缓存策略。
比较常用的Cache服务器有负载均衡服务器F5带的RAMCache。 或者使用squid 来做缓存服务器。效果很好的。 |
|
返回顶楼 | |