【问题标题】:Should We use a Windows Service or Thread Pool?我们应该使用 Windows 服务还是线程池?
【发布时间】:2014-06-30 09:00:25
【问题描述】:

我们正在使用 Asp.Net MVC 4 为数百名用户开发一个 Web 应用程序。

我们需要有一个后台服务每个用户在几分钟的时间间隔内工作。

我们不确定是使用Windows Services(多个Windows 服务)还是使用进程的线程池。我们认为 Windows 服务是因为它们可以通过 Windows 服务器轻松维护,并且这种方法可以节省编程 UI 和管理线程的开销。它也可以很容易地在一段时间内运行。

Windows Service 是否可以为刚刚注册的新用户自动启动一个新实例(所以我们有多个后台 windows 服务实例,每个用户一个)?如果不是,Windows Services 选项就会失效。

如果上层可行,我们应该选择Windows Services的方式还是自己管理Thread Pool的进程?

【问题讨论】:

  • “进程的线程池”实际上没有任何意义。你能澄清一下吗?
  • 为什么每个新用户都需要自己的服务?这是无缘无故的主要开销。
  • 我们一般都在谈论架构。我故意含糊其辞。我在这里需要一个通用的方法答案。在 Windows 服务和线程之间。
  • @YuvalItzchakov 有趣的是,首先你问为什么每个用户都需要自己的服务(因为不清楚),然后声称这是一个主要开销 没有理由 但他没有甚至还告诉过你原因;)
  • @DGibbs 你让我笑了:)

标签: c# vb.net multithreading asp.net-mvc-4 windows-services


【解决方案1】:

当然,为每个用户启动一个进程可以保证当您达到 1000 个时,您的内存开销会很高且不可扩展。我看不出启动一个进程(而不是一个线程)可以节省什么,因为新进程将包含至少一个线程。此外,Windows 服务与“登录用户”无关。它们不是为多实例而设计的。

You seem to want to run background work in ASP.NET MVC. 请注意,这很难。在这里使用一个 Windows 服务是有意义的。

后台工作的难点在于工作进程可能出于多种原因退出。您必须容忍这一点。一个服务也有同样的问题:需要部署新版本,定期重启服务器。您还需要一个 HA 策略,因此您需要多个服务器。

即使对于长时间运行的后台工作,我也不认为 Windows 服务会是更好的选择。

如果有 100 多个并发后台工作线程,您可能应该使用异步 IO 来避免使用 100 个专用线程。

我假设您的后台工作大部分时间都在等待。您可以使等待异步(使用计时器)和所有其他同步。这为您提供了一个简单的实现,并大大节省了内存使用量。

【讨论】:

  • 当说“为每个用户启动一个进程可以保证你的高内存开销”时,说“进程”是指 Windows 服务,对吗?而且,您能否更详细地说明使用等待异步?你是什​​么意思,所有其余的都是同步的?非常感谢。
  • 这适用于任何流程。服务启动新进程(和 CLR!)不会有太多额外开销。
【解决方案2】:

我们编写了一个开源项目Revalee 来处理这种类型的工作负载。它使用 Windows 服务来管理任务调度,但利用现有的 ASP.NET MVC 应用程序来处理带外操作。任务可能有数十万个,并且会一直持续到成功调度为止。

这是一个简单的工作流程图:

user initiated action
        |
        |           ......................
        |           :  future callback   :
        V           V                    :
======================       ===========================
|   Your web app     |       | Revalee Windows Service |
|                    |       |                         |
======================       ===========================
        |                                ^
        |    registers a callback now    |
        |________________________________|

【讨论】:

    【解决方案3】:

    使用单独的服务来执行后台任务可能会带来额外的负担:

    1. 拥有两个独立的应用程序肯定会增加项目的复杂性:如果您需要在 Web 应用程序和服务之间进行任何通信,这将比在 Web 应用程序中拥有整个东西更复杂(并且更慢)。您还需要部署两个单独的项目,因此这样的管道开销会增加一倍。

    2. 在性能方面,您不会从这种方法中获得任何收益。相反,在 Web 应用程序中拥有自己的托管池将允许更好地调度这些线程,并且很可能允许您更有效地运行它们,而不是简单地让 Windows 处理这些。您真的不想在同一台机器上产生数百个进程(或线程)同时竞争资源。

    3. 如果不出意外,将整个功能保留在 Web 应用程序中可能会简化您的托管选项。安装和管理 Windows 服务可能需要比廉价托管服务提供商提供的更多权限。

    话虽如此,在 ASP.NET 中运行后台任务意味着您需要准备好让您的线程由于异常、回收或 IIS 可以想到的任何其他原因而突然中止。在单独的进程中运行这些后台任务肯定不会受到这些 ASP.NET 怪癖的影响,因此最终归结为一种妥协:确保这些任务永不中断对您来说是多么重要,并且它是否证明额外的编程是合理的和维护工作?

    [编辑]

    如果您关心如何在服务中安排这些任务,请查看一些 .NET 的调度库,例如 Quartz。与简单地使用计时器相比,它可以更好地控制调度,并且(如果您需要它们)提供了一些高级功能,例如持久化作业(如果您想确保您的作业在重新启动后完成时很有用)和大规模应用程序的集群。

    使用简单的计时器也可以,但请确保您了解每个 .NET 计时器如何调度其事件。

    【讨论】:

    • @ilanS:看来@usr 也有你想在 ASP.NET 中运行任务的想法。我不确定当时的问题是什么?如果您已经知道您将拥有一个单独的应用程序,那么请选择 Windows 服务,这很容易。但显然,一个单一的 Windows 服务将管理所有后台作业;您需要控制线程调度,同时运行数百个数据库连接和数百个独立进程是没有意义的。
    • Tnx @Groo。我想我会选择管理线程的 Windows 服务。我应该在 Windows 服务中使用线程池还是手动启动线程?关于“您提到的数百个数据库连接”-我有什么选择?考虑到每个客户都有自己的数据库...但是您知道吗,这将是一个问题,因为我需要我们的支持团队能够停止/启动特定客户的后台任务。
    • 如果您谈论的是 .NET ThreadPool 与创建新的 Thread,那么它通常取决于您的任务持续时间。 CLR ThreadPoolTask 默认也使用它)适用于短期作业,因为它被整个运行时使用。另一方面,您可能在谈论您自己的托管线程池,这也是有道理的。这完全取决于这些任务的性质。他们完成得很快吗?在此使用 ThreadPoolTasks,因为它们已经过优化以减少争用。
    • 没有。这些服务需要一直工作。这些是 XML 服务,一直在客户数据库上运行和工作。
    猜你喜欢
    • 2010-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-12
    • 2012-06-24
    • 2010-11-29
    • 2011-07-09
    • 2011-05-14
    相关资源
    最近更新 更多