gpt4 book ai didi

c# - IHttpHandler 与 HttpTaskAsyncHandler 性能对比

转载 作者:太空狗 更新时间:2023-10-29 21:26:15 30 4
gpt4 key购买 nike

出于 CORS 和安全目的,我们有一个网络应用程序通过 .NET IHttpHandler(称为 proxy.ashx)路由许多请求。一些资源加载速度快,而另一些资源加载速度慢,这取决于这些资源所需的大量计算。这是预期的。

在重负载期间,proxy.ashx 会慢得像爬行一样,所有资源都需要很长时间才能加载。在这些高峰加载时间,如果绕过代理并直接加载资源,它会立即加载,这意味着代理是瓶颈。
(即 http://server/proxy.ashx?url=http://some_resource 加载缓慢,但 http://some_resource 自行加载快速)。

我假设响应速度降低是因为 IHttpHandler 是同步编码的,当有太多长时间运行的请求处于事件状态时,IIS 请求线程都处于繁忙状态。我创建了一个快速 A/B 测试应用程序来验证我的假设,我的测试结果表明情况并非如此。

This article是我了解请求线程池的基础。

On the Web server, the .NET Framework maintains a pool of threads that are used to service ASP.NET requests. When a request arrives, a thread from the pool is dispatched to process that request. If the request is processed synchronously, the thread that processes the request is blocked while the request is being processed, and that thread cannot service another request. ...
However, during an asynchronous call, the server is not blocked from responding to other requests while it waits for the first request to complete. Therefore, asynchronous requests prevent request queuing when there are many requests that invoke long-running operations.

在我下面的示例中,理论上,同步处理程序应该在某个阈值后占用请求线程,以防止启动更多新请求。异步处理程序应该允许更多的请求排队,因为每个请求在等待 Task.Delay 时几乎立即将其请求线程返回给线程池,从而允许该请求线程在处理新请求的同时之前的请求仍在等待中。

同步HttpHandler

<%@ WebHandler Language="C#" Class="SyncHandler" %>
using System.Web;
using System.Threading;
public class SyncHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
//BLOCKING artifical pause to simulate network activity
Thread.Sleep(300);
var Response = context.Response;
Response.Write("sync response");
}
public bool IsReusable { get { return true; } }
}

异步处理程序

<%@ WebHandler Language="C#" Class="AsyncHandler" %>
using System.Web;
using System.Threading.Tasks;

public class AsyncHandler : HttpTaskAsyncHandler
{
public override async Task ProcessRequestAsync(HttpContext context)
{
//NON-BLOCKING artificial pause to simulate network activity
await Task.Delay(300);
var Response = context.Response;
Response.Write("async response");
}
public override bool IsReusable { get { return true; } }
}

基准测试

我使用 apache 基准测试实用程序运行了一些基准测试。这是我正在使用的命令(显然更改下面结果的数字)。

ab -n 1000 -c 10 http://localhost/AsyncProxyTest/Sync.ashx
ab -n 1000 -c 10 http://localhost/AsyncProxyTest/Async.ashx

结果

1,000 个请求,一次 10 个

  • 同步:30.10 请求/秒
  • 异步:32.05 请求/秒

10,000 个请求,一次 100 个

  • 同步:33.02 请求/秒
  • 异步:32.05 个请求/秒

10,000 个请求,一次 1,000 个

  • 同步:32.55 个请求/秒
  • 异步:32.05 个请求/秒

如您所见,同步与异步似乎几乎没有任何影响(至少不足以值得切换)。

我的问题是:我是不是在测试中搞砸了一些没有准确模拟这个概念的东西?

最佳答案

IIS 的桌面版本存在一个限制,即一次将并发请求限制为 10 个(参见 this post)。此限制不存在于 IIS Express 中,也不存在于 Windows 服务器上的 IIS 中。

测试没有任何问题,它们只需要在不受限制的网络服务器上运行即可。我在 Windows Server 上使用 IIS 重新运行了这些测试,我的发现与我最初假设的预期完全一致。

这里再次显示结果。 (注意:这些结果来自一个非常活跃的开发服务器,因此可能会有一些波动)

1,000 个请求,一次 10 个
(这些结果是相同的,因为我们没有超出请求限制)

  • 同步:31.88 请求/秒
  • 异步:29.13 请求/秒

10,000 个请求,一次 100 个

  • 同步:68.53 请求/秒
  • 异步:310.66 请求/秒

10,000 个请求,一次 1,000 个

  • 同步:55.09 请求/秒
  • 异步:669.41 请求/秒

我捕获的另一个指标是运行的最大并发请求数。这就是我发现本地机器 10 的限制的方式。在 Windows 服务器上再次运行测试后,同步的最大值为 ~48 个并发请求。对于异步,它是 301,这意味着 async/await 在处理非阻塞调用时肯定会产生更高的吞吐量。

关于c# - IHttpHandler 与 HttpTaskAsyncHandler 性能对比,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48528773/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com