it-swarm.com.ru

Когда я должен использовать асинхронные контроллеры в ASP.NET MVC?

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

  1. Хорошо ли использовать асинхронное действие везде в ASP.NET MVC?
  2. Относительно ожидаемых методов: использовать ли ключевые слова async/await, когда я хочу сделать запрос к базе данных (через EF/NHibernate/другой ORM)?
  3. Сколько раз я могу использовать ключевые слова await для асинхронного запроса к базе данных в one методе с одним действием?
191
Vnuuk

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

Типичное использование класса AsyncController - длительные вызовы веб-службы.

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

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

Вы должны взглянуть на 1 и 2 ссылки

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

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

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

94
Tharif

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

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

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

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

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

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

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

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

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

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

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

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

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

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

208
Stephen Cleary

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

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

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

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

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

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

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

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

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

19
Yuval Itzchakov

Мои 5 центов:

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

Постскриптум Для пункта 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
7
bohdan_trotsenko

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

6
Dimitri

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

Посмотрите здесь для отличного совета.

4
anurag

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

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

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

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

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

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

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

2
Shadi Namrouti