在执行长时间运行的数据库任务时处理Web服务超时

Pau*_*ams 13 c# architecture sql-server web-services timeout

我们其中一个产品的架构是典型的3层解决方案:

  • C#客户端
  • WCF Web服务
  • SQL Server数据库

客户端从Web服务请求信息.Web服务命中数据库以获取信息并将其返回给客户端.

这是问题所在.其中一些查询可能需要很长时间,而且我们不知道哪些查询会很慢.我们知道一些通常比其他人慢,但即使最简单的请求也可能因为足够的数据而变慢.有时使用查询或运行大量数据的报告.只有在大量数据减慢之前,才能优化查询.

如果数据库中的查询在SQL Server中达到最大查询超时,则数据库查询将终止,并且Web服务会向客户端返回错误.这是理解的.我们可以处理这些错误.

客户端正在等待Web服务调用完成.如果数据库调用需要很长时间,则客户端可能会在调用Web服务时超时.客户端放弃,但数据库请求继续处理.此时,客户端与数据库不同步.数据库调用可能成功也可能不成功.可能有错误.客户永远不会知道.在某些情况下,我们不希望我们的用户发起另一个请求,如果完成上一个请求,可能会导致无效状态.

我很想知道其他人是如何处理这个问题的.您使用了哪些策略来防止Web服务超时影响数据库调用?

我能提出的最好的想法涉及在某个地方建立一个实际的数据库层 - 在Web服务内部,附加到消息队列 - 某些东西.将每个查询卸载到另一个进程似乎过多.(然后,我们并不总是知道给定的请求是快还是慢.)

如果我们能够将发出HTTP请求的行为与启动和运行数据库进程的行为分开,那就太好了.我已经在之前的公司看到过使用自定义服务器,但它使用的是直接套接字通信,我宁愿避免使用某些自定义应用程序替换Web服务.

请注意,考虑到我们处理的数据量,我们都在进行查询优化.查询优化,索引等只会在数据量很大时才将您带到目前为止.有时事情需要很长时间.

Bra*_*vax 6

我以前遇到过类似的问题,并使用以下3种方法之一来解决它:

  1. 将所有长时间运行的查询添加到队列中,并按顺序处理它们.
    在我的情况下,这些都是复杂的报告,然后通过电子邮件发送到客户端,或者存储在永久的"临时"表中,供客户在收到通知后查看.
  2. 我们使用JQuery调用调用了一个Web服务,然后在完成时调用了一个javascript回发方法.
    当我们不想让页面加载与Web服务正在执行的操作同步时,这很有效.
    但是,它确实意味着在长时间运行的过程完成之前,该功能不可用.
  3. 最复杂的一个.
    我们弹出另一个显示进度条的窗口,该窗口还定期轮询服务器.
    这使用会话变量来确定显示进度条的距离.
    启动进度条后,启动了一个新线程,它定期更新同一个会话变量.
    会话变量值设置为100后,弹出窗口将自行关闭.
    客户喜欢这种方法.

无论如何,我希望其中一个对你有所帮助.


Ser*_*uei 5

Web服务可以在线程池中运行查询,如果线程没有完成,比如5秒(参见Thread.Join()),Web服务调用会返回客户端JobID而不是客户端可以的结果集用于每隔几秒轮询服务器以查看其查询是否已完成.当线程完成时,结果可以存储在哈希表中,直到客户端再次轮询.


Pau*_*ams 2

我们最近使用的解决方案之一是将巨大的数据库进程分解为单独的并行操作。每个操作都小得多,并且设计得尽可能高效。客户端启动操作,生成一些线程,并并行执行它们可以执行的操作。

例如,我们将一些庞大的流程分解为一系列步骤,例如开始、处理第 1 个工作块、完成和收集报告数据。流程工作步骤可以并行运行,但在开始步骤完成之前它们无法启动。Finish 步骤需要等待所有 Process Work 步骤完成。

由于客户端控制流程,因此客户端可以准确报告其所处步骤的进度。