V
V
Victor P.2018-08-29 11:21:23
ASP.NET
Victor P., 2018-08-29 11:21:23

Who can chew asynchronous controllers?

Good time!

The difference between synchronous and asynchronous controllers from the book
Чтобы понять различие между синхронными и асинхронными методами, рассмотрим, как IIS обрабатывает входящие запросы. Веб-сервер поддерживает пул потоков, которые обслуживают запросы. При обращении пользователя к веб-ресурсу IIS выделяет поток из пула для обслуживания данного запроса. И пока данный поток не обработает предназначенный для него запрос, другие запросы он обрабатывать не может.
Однако предположим, что метод контроллера в процессе обработки запроса должен выполнить запрос к другому ресурсу или к базе данных. Запрос к сетевому ресурсу или БД сам по себе может занять некоторое время. При синхронной обработке поток, обрабатывающий запрос, временно блокируется, пока сетевой ресурс или БД не возвратят нужные нам данные.
И если обработка запроса блокируется очень долго, то IIS начинает задействовать для обслуживания других входящих запросов новые потоки. Однако есть ограничения на общее количество потоков. Когда количество потоков достигает предела, то вновь входящие запросы помещаются в очередь ожидания. Однако и тут есть ограничение на количество запросов в очереди. И когда это количество превышает предел, то IIS просто отклоняет все остальные запросы с помощью статусного кода 503 (Service Unavailable).
При асинхронной обработке поток не ждет, пока БД вернет ему данные, а начинает обрабатывать запрос от другого пользователя. Но когда, наконец, с сетевого ресурса или БД придут нужные данные, поток возвращается к обработке ранее обрабатываемого запроса в обычном режиме.
Some code
public class HomeController : Controller
    {
        BookContext db = new BookContext();
 
        public ActionResult Index()
        {
            IEnumerable<Book> books = db.Books;
            ViewBag.Books = books;
            return View();
        }
 
        // асинхронный метод
        public async Task<ActionResult> BookList()
        {
            IEnumerable<Book> books = await db.Books.ToListAsync();
            ViewBag.Books = books;
            return View("Index");
        }
    }

Actually, the alignment is this, I understand that historically asynchrony has become extremely in demand in Windows applications, take, for example, winforms. The entire program is processed by one thread. When we press a button on the visual part that starts some long calculations or the same long operations of external calls, the visual part of the program is blocked (hangs). As far as I understand, this is the execution flow from the operating system. In this situation, asynchrony comes to the rescue, and the visual part continues to work, since while the first thread is hanging, the OS allocates an additional thread that continues to process our program.
I understand correctly that in this case it is the OS with its dispatcher that allocates an additional thread?
Another situation is when we have a web server. As the spoiler says, we have a thread pool that is dedicated specifically to our website. And the process of suspending execution during such asynchronous operations is not really signed anywhere.
Let's get a little more detailed. A request comes from the user - a thread is allocated from the thread pool - processing reaches the await sugar line, then our thread returns to the thread pool. But! You can't just pause the execution of the program and release resources. They must be stored somewhere (in RAM), there must be links to these resources for the possibility of resuming work. To do this, the operating system creates its own new thread (handler? thread? what is it called correctly?) and the thread from the pool is returned back to the pool.
Actually, there are situations when asynchrony can degrade performance (for example, performing await operations in a large loop)
Another very important point, the number of pool threads can be set independently. In fact, this is just a restriction on our site so as not to give it all the server resources. But, purely theoretically, we can set this value to the maximum. Then there will be no use from asynchronous operations at all, only one harm due to overhead costs.
One colleague assures me that asynchrony was not invented for the web and should not be used on the web.
But on the other hand, I read articles, follow, so to speak, the development of asp.net core. All operations are covered with asynchrony (in middleware, for example), where there was no asynchrony in the first versions. Developers recommend using asynchronous operations where possible.
And I take the approach that using asynchrony on the web is the right thing to do. But the arguments of this comrade sound convincing. "And you prove that you are not a Number God"?
I'm confused. I don’t know how to do load testing, and I thought that the internet was full of results. But I dug around and found some Hindu crap that proves absolutely nothing. Some words, copied from article to article, that asynchrony is good.
I need numbers. specific numbers. It is desirable as in my code spoiler: there are two half-empty controllers, synchronous and asynchronous. In which there is a request to the database. Stress Testing. Numbers. Tablet. With a standard thread pool and set to the maximum possible.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
F
Fat Lorrie, 2018-08-29
@Jeer

awaitdoes not yet mean the creation of an additional thread (thread). Especially when it comes to asynchronous I/O.
In desktop applications, the main thread has the Main Loop (event loop), which, in its free time from handlers, grinds the window's message queue (pulls these same handlers in response to appropriate events, such as button presses). If the handler is too bold, then the messages are not processed - the window stops responding to messages.
On the web (ASP.NET), each new request is allocated a new thread. If requests are too slow, and clients come and go, then there is a risk of exhausting the thread pool. As a rule, the slowest actions are I/O, in which the thread of our program is not busy with anything other than waiting. But operating systems can do asynchronous I/O (signal when data has been read/written), so why don't we return an idle thread to the thread pool? And when the data is considered, we will select the stream and return to the task.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question