Когда следует использовать Async Controllers в ASP.NET MVC?

У меня есть некоторые проблемы с использованием async-действий в ASP.NET MVC. Когда это улучшает производительность моих приложений, а когда это не так?

  • Хорошо ли использовать async-действие везде в ASP.NET MVC?
  • Что касается ожидаемых методов: следует ли использовать ключевые слова async/wait при запросе базы данных (через EF/NHibernate/other ORM)?
  • Сколько раз я могу использовать ключевые слова ожидания для асинхронного запроса базы данных одним методом?

Ответ 1

Методы асинхронного действия полезны, когда действие должно выполнять несколько независимых длительных операций.

Типичное использование класса AsyncController - это длительный веб-интерфейс сервисные вызовы.

Должны ли мои вызовы базы данных быть асинхронными?

Пул потоков IIS часто может обрабатывать множество одновременных запросов блокировки, чем сервер базы данных. Если база данных является узким местом, асинхронные вызовы не ускоряют реакцию базы данных. Без механизма дросселирования эффективная отправка дополнительной работы на перегруженный сервер базы данных с использованием асинхронных вызовов просто переносит большую нагрузку на базу данных. Если ваша БД является узким местом, асинхронные вызовы не будут волшебной пулей.

Вы должны посмотреть 1 и 2

Получено из комментариев @PanagiotisKanavos:

Кроме того, async не означает параллель. Асинхронное выполнение освобождает полезная нить потока из блокировки для внешнего ресурса, для нет сложности или производительности. Это означает, что одна и та же машина IIS может обрабатывать более параллельные запросы, а не то, что он будет работать быстрее.

Вы также должны учитывать, что блокирующие вызовы начинаются с CPU-интенсивная спинвейт. Во время стресса блокирующие вызовы будут приводят к возрастанию задержек и рециркуляции пула приложений. Асинхронные вызовы просто избегайте этого

Ответ 2

Вы можете найти мою статью статьи MSDN по этому вопросу; Я занимал много места в этой статье, описывая, когда вы должны использовать async на ASP.NET, а не только как использовать async на ASP.NET.

У меня есть некоторые проблемы с использованием async-действий в ASP.NET MVC. Когда это улучшает производительность моих приложений, а когда - нет.

Во-первых, поймите, что async/await - это освобождение потоков. В приложениях с графическим интерфейсом это в основном касается освобождения потока графического интерфейса пользователя, поэтому лучше работать с пользователем. В серверных приложениях (включая ASP.NET MVC) это в основном касается освобождения потока запросов, поэтому сервер может масштабироваться.

В частности, это не будет:

  • Сделайте ваши индивидуальные запросы быстрее. Фактически, они будут завершаться (просто бит подростка) медленнее.
  • Вернитесь к вызывающему/браузеру, когда вы нажмете await. await только "дает" пулу потоков ASP.NET, а не браузеру.

Первый вопрос: полезно ли использовать асинхронное действие везде в ASP.NET MVC?

Я бы сказал, что хорошо использовать его везде, где вы делаете I/O. Это может быть необязательно полезно (см. Ниже).

Однако, он плохой, чтобы использовать его для связанных с ЦП методов. Иногда разработчики думают, что могут получить преимущества async, просто называя Task.Run в своих контроллерах, и это ужасная идея. Потому что этот код заканчивается тем, что освобождает поток запросов, занимая еще один поток, поэтому нет никакой пользы (и на самом деле они берут на себя штраф за дополнительные переключатели потоков)!

Должен ли я использовать ключевые слова async/wait при запросе базы данных (через EF/NHibernate/other ORM)?

Вы можете использовать любые доступные методы, доступные вам. Сейчас большинство основных игроков поддерживают async, но есть некоторые, которые этого не делают. Если ваш ORM не поддерживает async, не пытайтесь обернуть его в Task.Run или что-нибудь в этом роде (см. Выше).

Обратите внимание, что я сказал "вы могли бы использовать". Если вы говорите об ASP.NET MVC с одним бэкэндом базы данных, то вы (почти наверняка) не получите выгоды от масштабирования от async. Это связано с тем, что IIS может обрабатывать гораздо более параллельные запросы, чем один экземпляр SQL-сервера (или других классических RDBMS). Однако, если ваш бэкэнд более современен - ​​кластер SQL-сервера, Azure SQL, NoSQL и т.д. - и ваш бэкэнд может масштабироваться, а узкое место масштабируемости - IIS, тогда вы можете получить преимущества масштабируемости от async.

Третий вопрос. Сколько раз я могу использовать ключевые слова ожидания для асинхронного запроса базы данных в ОДНОМ одном действии?

Сколько вам нравится. Однако обратите внимание, что многие ORM имеют правило одной операции за соединение. В частности, EF допускает только одну операцию на DbContext; это верно, является ли операция синхронной или асинхронной.

Кроме того, помните о масштабируемости вашего backend снова. Если вы нажмете один экземпляр SQL Server, и ваш IIS уже способен хранить SQLServer на полную мощность, то удвоение или утроение давления на SQL Server не поможет вам вообще.

Ответ 3

Хорошо ли использовать асинхронное действие везде в ASP.NET MVC?

Как обычно в программировании, это зависит. Всегда есть компромисс при спуске по определенному пути.

async-await светит в тех местах, где вы знаете, что будете получать параллельные запросы к своей службе, и вы хотите иметь возможность масштабироваться хорошо. Как async-await помогает с масштабированием? В том, что когда вы вызываете синхронный вызов асинхронного ввода-вывода синхронно, например, сетевой вызов или попадание в вашу базу данных, текущий поток, который отвечает за выполнение, блокируется в ожидании завершения запроса. Когда вы используете async-await, вы включаете фреймворк для создания конечного автомата, который гарантирует, что после завершения ввода-вывода ваш метод продолжит выполнение с того места, где он остановился.

Следует отметить, что эта машина состояний имеет тонкие накладные расходы. Создание асинхронного метода не ускоряет выполнение, и это важный фактор для понимания и заблуждения многих людей.

Еще одна вещь, которую следует учитывать при использовании async-await, - это то, что она полностью асинхронна, что означает, что вы увидите, как async проникает во весь стек вызовов, сверху до buttom. Это означает, что если вы хотите разоблачить синхронные API, вы часто будете дублировать определенный код, а async и sync не смешиваются очень хорошо.

Должен ли я использовать ключевые слова async/wait, когда я хочу запросить базу данных (через EF/NHibernate/другие ORM)?

Если вы решите пойти по пути использования асинхронных вызовов ввода-вывода, тогда да, async-await будет хорошим выбором, так как все больше и больше современных поставщиков баз данных обнаруживают метод async, реализующий TAP (Task Asynchronous Pattern).

Сколько раз я могу использовать ключевые слова ожидания для запроса базы данных асинхронно в одном методе одного действия?

Сколько хотите, если вы следуете правилам, указанным поставщиком базы данных. Нет никаких ограничений на количество асинхронных вызовов, которые вы можете сделать. Если у вас есть запросы, которые независимы друг от друга и могут быть сделаны одновременно, вы можете создать новую задачу для каждого и использовать await Task.WhenAll, чтобы дождаться завершения обоих.

Ответ 4

Мои 5 центов:

  • Используйте async/await тогда и только тогда, когда вы выполняете операцию ввода-вывода, например, службу БД или внешнюю службу обслуживания.
  • Всегда предпочитайте асинхронные вызовы в DB.
  • Каждый раз, когда вы запрашиваете БД.

P.S. Для точки 1 есть исключительные случаи, но для этого вам нужно хорошо понять внутренние асинхронные функции.

В качестве дополнительного преимущества вы можете выполнять несколько вызовов IO параллельно при необходимости:

Task task1 = FooAsync(); // launch it, but don't wait for result
Task task2 = BarAsync(); // launch bar; now both foo and bar are running
await Task.WhenAll(task1, task2); // this is better in regard to exception handling
// use task1.Result, task2.Result

Ответ 5

async действия помогают лучше всего, когда действия выполняют некоторые операции I\O с БД или некоторые связанные с сетью вызовы, где поток, обрабатывающий запрос, будет остановлен, прежде чем он получит ответ от связанного с БД или связанного с сетью вызова, который вы только что вызвали, Лучше всего использовать их с ними, и это действительно улучшит отзывчивость вашего приложения (потому что меньше потоков ASP/выходных потоков будет остановлено в ожидании БД или любой другой операции вроде этого). Во всех моих приложениях, когда многие обращения к БД очень нужны, я всегда завербовал их в awaiatable method и называл это ключевым словом await.

Ответ 6

Как вы знаете, MVC поддерживает асинхронные контроллеры, и вы должны воспользоваться им. В случае, если ваш контроллер выполняет длительную операцию (это может быть ввод/вывод на основе диска или сетевой вызов другой удаленной службы), если запрос обрабатывается синхронно, поток IIS занят все время. В результате поток просто ждет завершения длительной операции. Его можно лучше использовать, обслуживая другие запросы, в то время как запрашиваемая операция сначала выполняется. Это поможет в обслуживании большего количества одновременных запросов. Ваш веб-сервис будет очень масштабируемым и не будет легко запущен в проблема C10k. Рекомендуется использовать async/await для запросов db. и да, вы можете использовать их столько раз, сколько считаете нужным.

Посмотрите здесь за отличные рекомендации.

Ответ 7

Хорошо ли использовать асинхронное действие везде в ASP.NET MVC?

Это полезно делать везде, где вы можете использовать асинхронный метод, особенно если у вас есть проблемы с производительностью на уровне рабочих процессов, что происходит для массивных данных и вычислительных операций. В противном случае, нет необходимости, потому что юнит-тестирование потребует кастинга

Относительно ожидаемых методов: я буду использовать ключевые слова async/await, когда я хочу сделать запрос к базе данных (через EF/NHibernate/другой ORM)?

Да, лучше использовать async для любой операции с БД, чтобы избежать проблем с производительностью на уровне рабочих процессов. Обратите внимание, что EF создал много асинхронных альтернатив для большинства операций, таких как:

.ToListAsync()
.FirstOrDefaultAsync()
.SaveChangesAsync()
.FindAsync()

Сколько раз я могу использовать ключевые слова await для асинхронного запроса к базе данных одним единственным действием?

Небо это предел

Ответ 8

По моему опыту, сегодня многие разработчики используют async/await по умолчанию для контроллеров.

Я предлагаю, использовать его только тогда, когда вы знаете, что это поможет вам.

Причина в том, что, как Стивен Клири и другие уже упоминали, он может создавать проблемы с производительностью, а не решать их, и поможет вам только в определенном сценарии:

  • Контроллеры с высоким трафиком
  • Масштабируемый бэкэнд