【问题标题】:ASP.NET and multithreading best practicesASP.NET 和多线程最佳实践
【发布时间】:2012-11-01 18:46:49
【问题描述】:

我正在处理 ASP.NET 项目,昨天我看到一段代码使用 System.Threading.Thread 将一些任务卸载到新线程。该线程运行一些 SQL 语句并记录结果。

使用其他方法不是更好吗?例如,拥有一个执行 SQL 批处理的 Windows 服务。然后网页只会将批处理排入队列(通过 WCF)。

一般来说,ASP.NET 中多线程的最佳实践是什么?线程/TPL 任务/等的使用是否合理?在网页中?

【问题讨论】:

  • 请解释为什么您认为在另一个进程中执行 SQL 查询会更好。
  • 我主要关心的是为每个 Web 请求多处理一个线程。这有效地使线程加倍,我认为这不是一个好主意,尤其是当有很多并发用户时。可能最好将批处理参数写入表中,然后使用 SQL Server 作业执行实际查询。

标签: asp.net multithreading architecture


【解决方案1】:

我在 ASP.NET 中使用多线程时的想法:

  1. ASP.NET 会出于某些原因(例如您更改 web.config 或在一段时间内避免内存泄漏)回收 AppDomain。问题是你不知道回收的确切时间。长时间运行的线程不适合,因为当 ASP.NET 回收时,它会相应地降低您的线程。这种情况的正确方法是长时间运行的任务应该通过队列在后台进程上运行,就像你提到的那样。

  2. 对于 短期运行和触发后忘记任务TPLasync/await 是最合适的,因为它不会阻塞线程池中的线程用于 HTTP 请求。

【讨论】:

    【解决方案2】:

    在我看来,这应该通过在数据库中提高某种标志以及定期检查标志并启动作业的 Windows 服务来解决。如果作业过于频繁,则应使用专用队列解决方案(MSMQ、RabbitMQ 等)以避免数据库过载或表增长过快。我不认为通过 WCF 或其他任何方式直接与 Windows 服务通信是一个好主意,因为这可能会导致消息丢失。

    话虽如此,有时项目需要在共享主机中运行,并且无法设置专用的 Windows 服务。在这种情况下,可以接受一个线程作为解决方法,一旦项目增长到足以拥有自己的服务器,就应该将其删除。

    我相信 ASP.NET 中的所有其他线程都是一个问题的征兆,除了使用任务来表示异步操作,或者在极少数情况下,当您想在 Web 项目中并行执行计算但您的项目具有非常并发用户少(并发用户少于内核数)

    为什么任务在 ASP.NET 中很有用?

    使用 Tasks 进行异步操作的第一个原因是,从 .NET 4.5 开始,异步 API 返回 Tasks :) 异步操作(不要与并行计算混淆)可能是 Web 服务调用、数据库调用等。它们可能对两件事有用:

    1. 同时解雇几个,您的工作将花费相当于最长操作的时间。如果您以顺序(非异步)方式触发它们,它们将花费等于每个操作时间总和的时间,这显然更多。
    2. 他们可以通过释放执行页面的线程来提高可伸缩性 - Node.js 样式。 ASP.NET 一直支持这一点,但在 4.5 版中它真的很容易使用。我会声称它比 Node.js 更容易,因为 async/await。释放线程很重要,因为您可能会通过让它们等待来耗尽池中的线程。结果是,当有一定数量的用户时,您的网站会变得很慢,尽管 CPU 使用率大约是 30%,这仅仅是因为新请求在队列中等待。如果您增加线程池中的线程数,那么您付出的代价就是持续的上下文切换,而不是操作系统。在某些时候,您将获得 100% 的 CPU 使用率,但其中 40% 将用于上下文切换。您将增加吞吐量,但收益递减。大量线程也会增加内存占用。

    【讨论】:

    • 我大体上同意。起初我考虑使用 Windows 服务,但现在我认为使用 SQL Server 工作就足够了。不需要 MSMQ、RabbitMQ 或其他任何东西。我仍然不明白为什么应该将 TPL 任务用​​于异步操作。此外,我没有看到适用于 Web 服务器上的异步操作的合理场景。你能详细说明一下吗?
    • 我想可能存在适合 TPL 任务的场景,尽管我现在想不出任何。一般来说,我认为网络服务器上不应该有任何多线程。应使用所有可用资源(线程)来服务请求。如果你有很多并发用户,你最终会得到很多线程。是否有 Web 请求或 I/O 完成端口都没有关系。在某些时候,服务器将变得超载。您始终可以构建应用逻辑,这样您就可以支持短序列化请求而不是(长)并行任务。
    • 并行只是异步执行的一种。任务代表并行执行和等待。此外,线程是工作线程还是 I/O 完成端口也很重要。 I/O 线程的全部意义在于它们与普通线程不同:) BTW 检查这个相关问题:stackoverflow.com/questions/4842325/…
    猜你喜欢
    • 2014-06-04
    • 1970-01-01
    • 1970-01-01
    • 2010-09-05
    • 2010-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-14
    相关资源
    最近更新 更多