async/await 如何帮助 ASP.Net 应用程序? [英] How async / await can help in ASP.Net application?

查看:37
本文介绍了async/await 如何帮助 ASP.Net 应用程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 MVC 控制器的 action 方法中使用 async/await 可以扩展 Web 应用程序,因为在 await 时释放了 Asp.Net 线程池的请求线程,以便它可以处理 IIS 队列中此工作进程的其他请求.这意味着,如果我们将工作进程的队列长度限制为 10,并向异步操作发送 50 - 100 个请求,则 IIS 不应返回 HTTP 503 错误,因为总会有来自 Asp.Net 线程池的空闲线程来服务器传入的请求.

Using async / await in action method of MVC controller can scale up the web application because at await the request thread of Asp.Net thread pool is freed up so that it can process other requests in the IIS queue for this worker process. This means that if we limit the Queue Length of worker process to 10, and send 50 - 100 requests to async action, the IIS should not return HTTP 503 error as there will always be a free thread from Asp.Net Thread Pool to server the incoming requests.

我有一个 WebApi 进行如下计算:

I have a WebApi that does the calculation as given below:

public class ValuesController : ApiController
{
    public int GetSum(int x, int y, int timeDelay = 1)
    {
        Thread.Sleep(timeDelay*1000);
        int result = x + y;
        return result;
    }
}

此操作方法只是延迟给定秒数,然后将总和结果返回给调用代码.非常基本的 web api 只是为了模仿长时间运行的代码.

This action method just delays for given number of seconds before returning the sum result to the calling code. Very basic web api just to mimic the long running code.

接下来是等待结果的 MVC 异步操作:

Next is the MVC async action that awaits for the result:

public class ThreadStarvationController : Controller
{
    public async Task<ActionResult> CallGetSumWithDelayAsync(int num1 = 5, int num2 = 8, int timeDelay = 60)
    {
        int callingThreadId = Thread.CurrentThread.ManagedThreadId;
        ThreadStarvationModel model = new ThreadStarvationModel();

        string url = "http://localhost:8111/api/values/GetSum?x=" + num1 + "&y=" + num2 + "&timeDelay=" + timeDelay;

        using (HttpClient client = new HttpClient())
        {

            // here still using the same request thread...
            // following line will force await to free up the request thread and wait asynchronouly               //for the response.
            model.ResponseFromWebService = await client.GetStringAsync(url);

            // here we can be on the same request thread or anyother thread... more likely on //another other thread than 
            // request thread.
        }

        int returningThreadId = Thread.CurrentThread.ManagedThreadId;

        model.CallingThreadId = callingThreadId;
        model.ReturningThreadId = returningThreadId;

        return this.View(model);
    }
}

WebApi 和 MVC 托管在 IIS 上.MVC 网站仅限于队列中的 10 个请求.

The WebApi and MVC are hosted on IIS. The MVC website is limited to only 10 requests in queue.

当客户端在 15 或 20 个请求后调用 MVC 异步方法时,IIS 发送 HTTP 503 错误,这意味着 IIS 队列已满请求.

When the client calls MVC async method after 15 or 20 requests the IIS sends HTTP 503 error which means that the IIS Queue is full with requests.

这是调用 MVC 异步方法的控制台应用程序代码.它调度了 30 个任务并并行执行.

Here is the console application code that calls the MVC async method. It schedules 30 tasks and executed them in parallel.

          List<Task> taskList = new List<Task>();
        for (int x = 0; x < 30; x++)
        {
            string url = "http://localhost:8333/ThreadStarvation/CallGetSumWithDelayAsync?num1=" + x + "&num2=" + x + "&timeDelay=1";

            Task stringDataTask = new Task(() =>
            {
                using (HttpClient webClient = new HttpClient())
                {
                    string data = webClient.GetStringAsync(url).Result;
                    Console.WriteLine("{0}", data);
                }
            });


            taskList.Add(stringDataTask);
        }

        DateTime startTime = DateTime.Now;

        Parallel.ForEach(taskList, item => item.Start());

        Console.WriteLine("================== START {0} ===========================", startTime);

        Task.WaitAll(taskList.ToArray());
        DateTime endTime = DateTime.Now;
        Console.WriteLine("================= THE END {0} ============================", endTime);

运行时,在 20 个左右的请求后,我收到 HTTP 503 错误消息.

When this runs, after 20 or so requests I get HTTP 503 error message.

如果我使用同步MVC动作,结果还是一样.我知道在 async/await 之前和之后使用不同的线程.

If I use synchronous MVC action, the result is still the same. I know that with async / await different threads are used before and after await.

我想证明的是,使用 async/await 将扩展 Web 应用程序.

All I want to prove is that using async / await will scale up the web application.

推荐答案

我认为您混淆了池队列.有 5 个地方可以让 ASP.NET 请求在 IIS 服务器上排队.

I think you are confusing pool queues. There are 5 places where ASP.NET requests can become queued on an IIS server.

  1. 应用程序池队列
  2. IIS 工作进程
  3. CLR 线程池队列
  4. 集成模式全局队列
  5. 经典模式应用队列

您设置为 10 的队列长度是 HTTP.SYS:应用程序池队列.

The Queue Length you are setting to 10 is HTTP.SYS: Application pool queue.

当您使用 async/awat 时,您使用的是 ASP.NET:CLR 线程池队列.

When you use async/awat you are using ASP.NET: CLR threadpool queue.

这就是即使使用 async/await 也会出现 503 错误的原因.

That is the reason why you get 503 error even with async/await.

另一方面,这里有一篇精彩的文章使用可以帮助您的 async/await 调用 Web 应用程序.

On the other hand, here there is a wonderful article about scalling web app with async/await that can help you.

我刚刚找到了 这篇关于请求队列的文章也有帮助.

I had just found this article about request queuing that can help too.

这篇关于async/await 如何帮助 ASP.Net 应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆