当前位置: 代码迷 >> Web前端 >> Web施用中开线程池做报表处理的一些思路
  详细解决方案

Web施用中开线程池做报表处理的一些思路

热度:100   发布时间:2012-08-15 16:57:17.0
Web应用中开线程池做报表处理的一些思路

以前在iteye上的一个帖子,讨论Web应用中开线程池做报表处理的一些思路


[ 需求]
甲方是个跨国500强企业,它要建立一套全球整合的CRM管理系统。
其中有一个功能是在Web上面打印报表。但是因为报表业务逻辑复杂,数据量大,在web上点击同步生成用户体验太差。所以决定采取异步的做法生成报表。
[ 甲方的架构师提出的设计]
甲方的架构师提出的思路是,
1. 定制servlet,在servlet的init方法里,初期化一个线程池。将线程池包装到一个ThreadController 单例里面去
2. 客户点击打印报表按钮,发送出一个http请求到服务器端
3. 服务器端将生成报表所需要的参数包装到一个Listener中,然后将Listener 的instance抛给ThreadController单例,在ThreadController中以Queue的模式保存。
4. ThreadController依次唤醒线程池中的线程,从Queue中取出Listener交给该线程执行打印报表。如遇线程池爆满,则在Queue中排队。
5. http响应返回成功给画面
6. 线程执行完毕以后,在DB中写入打印结果
7. 客户端用Ajax轮训WebService,察看打印结果,达到推送功能。

甲方的架构我觉得问题有。在Web应用的容器中开线程池,性能和安全性得不到保证。以后系统的横扩展也会困难。
[ 我提出的设计]
1. 专门搭建一个报表打印服务器
2. Web服务器接受到打印请求以后,发送一个JMS到打印服务器去
3. 打印服务器那边,接受JMS,排队,然后启动线程执行打印功能。
4. 打印服务器完毕以后,写DB
遗留的问题,
a. 用JMS通信好不好?据说很重。但是用http的话,又怕丢包
b. 这样设计,貌似横扩展比较困难。但是因为打印报表本身这个动作是有状态的,以后估计也只能上机器

一些经典的讨论和回帖

no1dog 写道
在Web应用的容器中开线程池,性能和安全性得不到保证。

能说下不安全的理由是什么吗?性能问题又是什么?

我回答
比如,Web应用本身负载很高的情况下,你还要开线程,占用资源
比如,如果线程死锁了,Web应用会被你拖死
比如,JVM能开得线程数是一定的,tomcat本身就有一堆守护线程,JVM也是。http请求也会有线程。你再开,开爆了怎么办

 

某位大牛说
主要还是根据具体的实际情况而定,

比如:实时性要求不高;要求能承受多大报表量,报表生成时间等等

建议不在web应用中做,分离出来一个单独的报表程序,单独运行,两系统间通过jms通信

如果放在web里的话,如果web程序挂掉了,那报表的模块不也就挂掉了。

也可用第三方成熟的报表程序还做。

缓存之类的也可以考虑。

 

 


 

rainmanyang 写道
这种对实时性要求不高的场景,用消息中间件来做稳定又省力

对于这种前台Web压力比较大, 而又要实现这种实时性要求不高的处理负荷又重的任务, 不要在Web中开线程做.

用消息中间件通知其他程序来处理是一个比较好的架构, 各自完成各自的任务, 而且将来也便于扩展.


 

某位大牛说到
报表一般是和web应用分开部署,这个毋庸置疑。具体实现也应该以此为基础展开,否则首先方向上就有问题。

甲方架构师的思路可能偏重于实现的策略,没有关注系统的整体规划和部署,实现有点复杂,可用性不强。

如果报表的可靠性要求很高,注意保证系统间通信消息的持久化就可以了,选择消息中间件也是个不错的办法,简单快捷。

 

vlinux 写道

从维护成本来看,用JMS通讯会存在消息延时甚至丢失的可能,JMS也是一台服务器啊~,然后再加上你的打印服务器。要知道这个瓶颈是在DB的CPU/MEM/IO上,有机器多拖几个读库或将DB的钱换成Hadoop之类的还差不多。可以想象这个打印服务器除了来了一个请求之后就开个线程在等待DB返回了,压力非常低。

 

JMS一台服务器、打印服务一台服务器,主备各一台,一共4台。

JMS的维护成本、联调成本,后期问题排查成本都得考虑进去。

 

作为后台系统,WEB层从来就不是瓶颈,如果不要求非常可靠,用甲方架构师的方案会更优。不过要集中精力解决下用户等得不耐烦,重复提交/F5、任务执行超时等问题。这些问题就算你做到打印服务器上,也是要考虑和解决的。

  相关解决方案