【问题标题】:IIS and single-threaded applicationIIS 和单线程应用程序
【发布时间】:2019-07-23 20:30:48
【问题描述】:

我想知道托管在 IIS 中的单线程 .NET 应用程序中的请求/响应模型。例如,如果它是一个 WebAPI 应用程序,它是单线程读取一个大文件,处理它(对内容进行一些字符串操作)并在 API 响应中返回处理后的内容,为了论证,我们假设它需要处理文件需要 10 分钟。

现在,我在这里读到 ASP.NET IIS 映射是多线程的:

How is ASP.NET multithreaded?

如果我在一分钟内向同一个 API 发出 20 个请求会怎样?

  1. 调用者#2 等会发生什么?等待 10 分钟,然后 IIS 才会启动?
  2. IIS 在哪里跟踪传入的请求?

【问题讨论】:

  • 默认情况下,在 IIS 中运行的任何东西都是多线程的。
  • 如果您的请求需要几秒钟以上的时间来处理,那么直接在 Web 应用程序中完成这项工作是没有意义的。相反,将其移至后台进程。客户可以通过点击您的 API 来启动工作,然后他们可以轮询结果(或使用 webhook 或其他技术来通知他们)。

标签: c# .net multithreading iis


【解决方案1】:

如果不进行一些调整,IIS 将像任何其他服务器一样同时处理请求。

  1. 如果将请求队列大小、请求超时和线程池大小设置为适当的值 - 请求 #2 将在 IIS 请求队列中花费 10 分钟后处理。

  2. 没有持久性。只有内存。

这是一种不寻常的情况 - 等待如此长的请求完成,然后在一段时间内返回响应。从系统设计的角度来看,在后台作业管理器中对该计算进行排队或尽可能缓存结果,立即返回数据而不是等待几分钟是有意义的。

我想到的另一种选择如下:

  1. 设置后台作业以逐个处理文件。
  2. 将文件 POST 到服务器后,返回一个表示其身份的令牌。
  3. 创建一个单独的端点来使用文件身份。服务器应返回处理结果或指示文件在队列中等待处理的消息。

【讨论】:

  • 10 分钟来处理一个作业是一个夸大时间的假设场景,并将其作为一个平台来讨论如何为不同的线程提供服务。在更大的方案中,我绝对同意您的观点,即它应该在消息队列中提供,否则它的后台进程将需要很长时间来处理它。
  • 我将Hangfire 用于类似目的,here 是与其他替代方案的讨论
【解决方案2】:

默认情况下,IIS 会同时处理请求。如果您不主动采取任何措施来阻止它,那么如果 2 个请求同时到达,您将开始在 2 个线程上同时处理同一个文件。

如果不需要并发处理,您可以使用同步原语之一,例如 lock(...) 或互斥锁。然而;如果处理需要 10 分钟,您确定要将其作为 Web 请求的一部分吗?可能会有更好的选择。

【讨论】:

    【解决方案3】:

    Here 是一篇很好的文章,它描述了 HTTP 请求在到达您的代码之前通过的所有层 :) 每个层都有自己的配置和限制。

    请注意,.net 线程池增长相当缓慢,它每秒增加 2 个线程。如果您的控制器中有同步阻塞代码(使用锁或互斥锁)并向服务器推送 100 个请求,您的代码将仅在 45 秒内处理最后一个请求:将立即处理 10 个请求(考虑到它是默认线程池大小) ,然后线程池将增长(缓慢),并将在 45 秒内处理所有剩余的 90 个请求(将 2 个线程添加到池中)。

    【讨论】:

    • IIS 可以旋转的#of 线程的总体限制是多少?或者有没有?
    • 定义 IIS?您的应用程序受到内存和描述符数量的限制,以启动线程。对于线程池,您可以使用ThreadPool.GetMaxThreads() 来确定您网站的容量。 W3WP有自己的configuration,HTTP.sys的配置是here
    猜你喜欢
    • 2020-08-28
    • 1970-01-01
    • 2010-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多