简体   繁体   English

async / await如何在ASP.Net应用程序中提供帮助?

[英]How async / await can help in ASP.Net application?

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. 在MVC控制器的操作方法中使用async / await可以扩展Web应用程序,因为等待Asp.Net线程池的请求线程被释放,以便它可以处理IIS队列中的此工作进程的其他请求。 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. 这意味着如果我们将工作进程的队列长度限制为10,并向异步操作发送50-100个请求,则IIS不应返回HTTP 503错误,因为始终存在从Asp.Net线程池到服务器的空闲线程来电请求。

I have a WebApi that does the calculation as given below: 我有一个WebApi进行如下计算:

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

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. 非常基本的web api只是为了模仿长时间运行的代码。

Next is the MVC async action that awaits for the result: 接下来是等待结果的MVC异步操作:

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);
    }
}

The WebApi and MVC are hosted on IIS. WebApi和MVC托管在IIS上。 The MVC website is limited to only 10 requests in queue. MVC网站仅限于10个队列请求。

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. 当客户端在15或20个请求之后调用MVC异步方法时,IIS发送HTTP 503错误,这意味着IIS队列已满请求。

Here is the console application code that calls the MVC async method. 以下是调用MVC异步方法的控制台应用程序代码。 It schedules 30 tasks and executed them in parallel. 它安排了30个任务并并行执行。

          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);

When this runs, after 20 or so requests I get HTTP 503 error message. 当这个运行时,在20个左右的请求后,我收到HTTP 503错误消息。

If I use synchronous MVC action, the result is still the same. 如果我使用同步MVC操作,结果仍然相同。 I know that with async / await different threads are used before and after await. 我知道使用async / await会在await之前和之后使用不同的线程。

All I want to prove is that using async / await will scale up the web application. 我想要证明的是,使用async / await将扩展Web应用程序。

I think you are confusing pool queues. 我认为你混淆游泳池队列。 There are 5 places where ASP.NET requests can become queued on an IIS server. ASP.NET请求有5个位置可以在IIS服务器上排队。

  1. Application pool queue 应用程序池队列
  2. IIS worker process IIS工作进程
  3. CLR threadpool queue CLR线程池队列
  4. Integrated mode global queue 集成模式全局队列
  5. Classic mode application queue 经典模式应用队列

The Queue Length you are setting to 10 is HTTP.SYS: Application pool queue. 您设置为10的队列长度是HTTP.SYS:应用程序池队列。

When you use async/awat you are using ASP.NET: CLR threadpool queue. 当您使用async / awat时,您正在使用ASP.NET:CLR线程池队列。

That is the reason why you get 503 error even with async/await. 这就是为什么即使使用async / await也会出现503错误的原因。

On the other hand, here there is a wonderful article about scalling web app with async/await that can help you. 另一方面, 这里有一篇关于使用async / await来scalling web应用程序的精彩文章可以帮到你。

[EDIT] I had just found this article about request queuing that can help too. [编辑]我刚刚发现这篇关于请求排队的文章也可以提供帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM