【问题标题】:Recommendations for designing a long-running, resource-intensive web service设计长期运行的资源密集型 Web 服务的建议
【发布时间】:2010-11-12 09:47:10
【问题描述】:

我有一个 .NET 函数可以进行一些复杂的计算。根据传入的参数,函数:

  • 运行时间从几分钟到几小时不等
  • 在计算过程中使用 100% 的单核
  • 需要 100 到几 GB 的内存
  • 将几 MB 到几 GB 的数据写入磁盘
  • 可能会引发异常,包括 OutOfMemoryException

可以通过函数参数化准确预测要写入磁盘的数据量。没有简单的方法可以从函数参数化中预测其他资源需求。

我需要通过网络服务公开这个功能。该服务需要:

  • 灵活且优雅地报告计算过程中的任何问题
  • 能够处理并发请求,只要有足够的资源来处理请求而不会显着降低性能,否则可以优雅地拒绝请求。

我打算通过让初始请求返回可以轮询进度的状态资源来处理长时间运行的性质。计算完成后,此资源将提供输出数据的位置,客户端可以下载(可能通过 FTP)。

我不太清楚如何最好地处理其他要求。我正在考虑某种“计算池”来维护计算器的实例并跟踪当前正在使用哪些实例,但我还没有弄清楚细节。

有遇到类似情况的人有什么建议吗?只要解决方案可以在 Windows 机器上运行,所有技术选项都可以考虑。

【问题讨论】:

  • VladV 和 Steven 都提供了非常有用的答案。我只能将一个答案标记为已接受,因此我根据撰写此评论时的投票数选择了 VladV。

标签: .net web-services long-running-processes


【解决方案1】:

我建议将您的应用程序分成两部分。

  1. Web 服务本身。它的功能:
    • 从客户端获取工作项;
    • 将此工作转移到执行实际工作的后端服务;
    • 报告进度和结果;
  2. 后端服务。它的功能:
    • 处理来自网络服务的请求;
    • 执行实际计算。

这种设计的原因是
1) 在托管应用程序 (ASP.NET) 中处理工作负载相对困难,因为服务器 (IIS) 将管理资源,而在单独的应用程序中您拥有更直接的控制权;
2) 两层设计更具可扩展性 - 例如,稍后您可以轻松地将后端移动到另一台物理机器(或多台机器)。

Web 服务应该是无状态的 - 例如,在接受请求后,用户会返回一些 ID 并使用此 ID 轮询服务以获取结果。

后端服务器可能必须维护一个要处理的请求队列和一组处理它们的工作线程。工作人员应监控可用资源并注意不要使机器过载(当然,要优雅地处理所有可能的错误情况)。

【讨论】:

  • 谢谢,后端服务的想法似乎是关键。现在我需要考虑如何隔离计算实例,以便一个失败不会杀死整个服务。
  • 只需在每个用于计算的线程中创建一个包罗万象的异常处理程序,这样后台线程就不会向外抛出异常。您也可以使用 AppDomains 将实例彼此隔离,但我认为这在这里没有多大意义。如果您担心虚拟内存不足,只需迁移到 x64 操作系统即可。
【解决方案2】:

虽然您可能希望提供 Web 服务接口,但 Web 服务通常不是为此类进程设计的。您可能想要做的是将请求转发到可以处理此问题的 Windows 服务(在专用机器上)。 Windows 服务不会被回收,您可以更好地控制该过程。

关于计算池:您可以尝试创建一个计算队列(例如数据库中的一个表)。这样,您可以在处理计算的专用机器上拥有多个 Windows 服务。这可以让您更轻松地扩展。

【讨论】:

  • 谢谢,后端服务的想法似乎是关键。现在我需要考虑如何隔离计算实例,以便一个失败不会杀死整个服务。
  • 您可以做的是让一个 Windows 服务始终一次运行一个计算,当计算(或服务)失败时,您可以将该计算标记为失败并记录失败。我们对失败所做的事情取决于手头的任务,但通常我们会重新安排任务,以便稍后再次执行。当然,您必须确保任务是原子的。当任务成功时,它将被标记为“完成”。管理员有一个用户界面,可以让他们查看哪些任务已安排、哪些正在运行、哪些失败以及失败的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-23
  • 1970-01-01
  • 2019-10-26
  • 2010-12-22
  • 1970-01-01
  • 1970-01-01
  • 2017-01-15
相关资源
最近更新 更多