处理长期运行的报告
我正在用Cwith Sql Server 2000数据库编写ASP.net应用程序。我们有一些PDF报告,客户可以根据他们的业务需求使用。问题在于这些报告需要一段时间才能生成(> 3分钟)。通常最终会发生的情况是,当用户请求报告时,请求超时会在Web服务器有时间完成报告生成之前终止请求,因此用户将永远没有机会下载文件。然后,用户将刷新页面并重试,这将重新启动整个报告生成过程,但仍然超时。 (不,我们现在不缓存报告;这是我努力争取的...)。
我们如何处理这些情况?我脑子里有个想法,其中涉及一个不同步的请求,以开始生成报告,然后使用一些JavaScript定期检查状态。状态指示报告完成后,请单独请求实际文件。
有没有我看不到的更简单的方法?
解决方案
将报告通过电子邮件发送给用户呢? asp页面应该做的就是发送请求以生成报告,并返回一条消息,报告说在完成运行后将通过电子邮件发送该报告。
从处理的角度来看,我会考虑使此报告脱机一些。
就像创建一个队列以放置报告请求一样,从那里处理报告,完成后,它可以向用户发送消息。
也许我什至可以为队列处理创建一个单独的Windows服务。
更新:可以通过电子邮件发送给用户,也可以有一个"报告"页面,在该页面中,用户可以检查其报告的状态,并准备好下载。
用户可能不接受这种方法,但是:
当他们请求报告时(通过单击按钮或者链接等),我们可以在单独的线程上启动报告生成过程,然后将用户重定向到一个页面,上面写着"谢谢,报告将通过电子邮件发送给几分钟后我们"。
当线程完成生成报告后,我们可以直接通过电子邮件发送PDF(可能由于大小而无法使用),或者将报告保存在服务器上并通过电子邮件将链接发送给用户。
或者,我们可以进入IIS并将超时增加到> 3分钟。
在这里使用文件系统可能是一个不错的选择。有一个请求,要求立即将网址返回到报告pdf位置。然后,服务器可以启动外部进程,也可以向其自身发送请求以执行报告。客户端可以在提供的URL上轮询服务器(使用http HEAD)以获取PDF。如果使PDF的文件名从报表参数派生,则可以使用哈希或者直接将参数放入名称中,我们也将获得即时服务器端缓存。
如果出现这个问题,我将做一些事情:
1停止那些超时!它们完全浪费资源。 (调出ASP页面的超时值)
2将所有数据库访问集中在一个点中,然后收集有关报告的统计信息,这些报告何时由谁运行以及花费了多少时间。调查为什么要花这么长时间,是因为报表复杂吗?数据范围?服务器负载? (实际上,我们都可以将其写在服务器上的.csv文件中,然后定期将此文件导入sql服务器中以供以后分析)。
最终,如果我们通过此单个访问点,将可以更轻松地"缓存"报告(例如,相同的查询相同的日期将返回先前生成的相同的PDF)
3我知道这确实不是问题,但我们是否尝试过深入研究这些查询以了解为什么它们要运行这么长时间?查询调整可能吗?
报告准备就绪时的4Email / SMS /屏幕消息似乎很棒...如果用户通常发送一批要生成的报告,则可能有一个小的仪表板指示可以在应用程序中构建"其"队列的进度。一个小的ajax控件将定期刷新状态。
提示:如果我们使用了中央数据库访问权限,并且我们有足够的信息了解什么运行的原因,运行时间和运行时间,那么我们最终将能够粗略估计报表运行所花费的时间。
如果响应时间对任务至关重要,那么是否应该在一天的某些小时内将某些用户限制在数据范围内(例如,日期范围)?
祝我们好运,如果我们想获得更准确的提示,请发布有关情况的更多详细信息...
查询优化可能是我们最好的起点。尽管我不知道我们正在生成报告,但是这一步并不需要花那么长时间。另一方面,效果不佳的查询可能会完全破坏性能。
根据查看查询的内容,我们可能需要添加一些索引,或者甚至可能建立一个表以非规范化的方式存储报告信息,以使其能够更快地获得。然后可以每小时(通过SQL Server作业)或者以要求规定的频率(在合理的范围内)刷新此非规范化表。
如果它是一个相对静态的报告,并且没有更改用户输入参数,那么将报告缓存在一天中较早的时间运行也是一个好主意,但是在不了解情况的情况下很难再对此进行详细说明。
对于这样的问题,除非我们没有理由怀疑报告生成的代码是罪魁祸首,否则我们确实需要从数据库开始。我们可以使用各种创可贴,这可能会在一段时间内有所帮助,但是如果数据库是根本原因,那么这些解决方案将无法很好地扩展,并且将来可能会遇到类似的问题(或者更糟糕的是) 。