SSRS批量生成PDF报表卡顿停滞的问题排查求助
SSRS批量生成PDF报表停滞问题排查与解决建议
场景说明
通过.NET控制台应用,基于WCF对接SQL Server报表服务器,批量生成数百份参数不同的同一份SSRS PDF报表(每份约1MB)。采用基础异步并发方式生成,核心代码如下:
并发任务代码
var listOfTasks = customers .Select(async customer => { var parameters = new Dictionary<string, string> { { "CustomerId", customer.Id }, { "BillDate", billDate } }; await GenerateInvoice(parameters); }) .ToList(); await Task.WhenAll(listOfTasks);
报表生成逻辑
private async Task GenerateInvoice(Dictionary<string, string> parameters) { var reportBytes = await _renderSsrs.ConvertToAsync( "\reportPath\InvoiceReport", parameters, FormatType.PDF); var filePath = $@"C:\temp\Invoices\Invoice-{parameters["CustomerId"]}.pdf"; await CreateFileFromBytesAsync(reportBytes, filePath); }
问题表现
- 初期约50份报表生成速度正常,后续逐渐变慢直至完全停滞,不再产出PDF
- SQL Server端存在大量处于睡眠状态、等待命令的开放连接
- 同一份报表的数据检索时间波动极大
- 最终进程因「报表执行已过期或无法找到」异常终止
- 已调整
rsreportserver.config中的MaxActiveReqForOneUser从20改为50,无改善;sp_who2未检测到阻塞进程,Profiler数据平稳、CPU活动下降
原因分析
- 无限制并发耗尽资源:直接用
Task.WhenAll发起所有请求,瞬间创建数百个并发任务,报表服务器的连接池、内存、处理线程被占满,后续请求排队等待直至超时。 - WCF客户端连接未释放:若
ConvertToAsync中WCF客户端实例未妥善关闭/释放,会导致连接池耗尽,新请求无法获取可用连接。 - 报表服务器资源瓶颈:虽无数据库阻塞,但报表服务器的渲染、内存资源已达上限,新请求无法被及时处理,最终触发超时。
- 数据库连接池不足:报表数据源的连接池配置过小,大量请求抢占数据库连接,导致数据检索延迟飙升。
解决建议
1. 限制并发数
用SemaphoreSlim控制同时执行的任务数量,避免瞬间压垮服务器(建议先从10-20的并发数测试):
var semaphore = new SemaphoreSlim(15); var listOfTasks = customers .Select(async customer => { await semaphore.WaitAsync(); try { var parameters = new Dictionary<string, string> { { "CustomerId", customer.Id }, { "BillDate", billDate } }; await GenerateInvoice(parameters); } finally { semaphore.Release(); } }) .ToList(); await Task.WhenAll(listOfTasks);
2. 优化WCF客户端管理
确保WCF客户端实例使用后及时释放,用using包裹实现自动释放:
using (var rsClient = new ReportExecutionServiceSoapClient()) { // 报表渲染逻辑 }
3. 调整报表服务器配置
- 修改
rsreportserver.config:提高MemoryLimit(报表服务器可用内存上限)、MaxQueueThreads和MaxWorkerThreads(报表处理线程数) - 启用报表缓存:针对固定参数(如
BillDate)设置缓存,减少重复数据检索
4. 优化数据库连接
- 调整报表数据源的连接池配置(如
Max Pool Size),适当提高连接池容量 - 优化报表查询语句,减少单报表的数据检索时间,降低数据库负载
5. 延长超时设置
在WCF客户端配置中延长超时时间,避免排队等待导致的超时:
<bindings> <basicHttpBinding> <binding name="ReportExecutionServiceSoap" receiveTimeout="00:10:00" sendTimeout="00:10:00"> </binding> </basicHttpBinding> </bindings>
6. 监控排查
- 查看SSRS日志(默认路径:
C:\Program Files\Microsoft SQL Server Reporting Services\SSRS\LogFiles)获取具体错误信息 - 监控报表服务器的内存、CPU、磁盘IO使用情况,定位资源瓶颈
- 用SQL Server Profiler跟踪报表查询,排查慢查询或资源争抢问题
内容的提问来源于stack exchange,提问作者Shandy Sawyer
相关产品推荐
相关产品推荐

