Я пытаюсь использовать async/await
функцию ASP.NET в своем проекте веб-API. Я не очень уверен, повлияет ли это на производительность моей службы веб-API. Ниже представлен рабочий процесс и пример кода из моего приложения.
Рабочий процесс:
Приложение пользовательского интерфейса → Конечная точка веб-API (контроллер) → Метод вызова на уровне службы веб-API → Вызов другой внешней веб-службы. (Здесь у нас есть взаимодействия с БД и т. Д.)
контроллер:
public async Task<IHttpActionResult> GetCountries()
{
var allCountrys = await CountryDataService.ReturnAllCountries();
if (allCountrys.Success)
{
return Ok(allCountrys.Domain);
}
return InternalServerError();
}
Уровень обслуживания:
public Task<BackOfficeResponse<List<Country>>> ReturnAllCountries()
{
var response = _service.Process<List<Country>>(BackOfficeEndpoint.CountryEndpoint, "returnCountries");
return Task.FromResult(response);
}
Я проверил приведенный выше код и работает. Но я не уверен, что это правильное использование async/await
. Пожалуйста, поделитесь своими мыслями.
Ответы:
Помните, что основное преимущество асинхронного кода на стороне сервера - это масштабируемость . Это не заставит ваши запросы работать быстрее. В статье об ASP.NET я рассмотрю несколько
async
вопросов, которые следует учитывать.async
.Я думаю, что ваш вариант использования (вызов других API) хорошо подходит для асинхронного кода, просто имейте в виду, что «асинхронный» не означает «быстрее». Лучший подход - сначала сделать ваш пользовательский интерфейс адаптивным и асинхронным; это заставит ваше приложение почувствовать быстрее , даже если это немного медленнее.
Что касается кода, это не асинхронно:
Вам потребуется действительно асинхронная реализация, чтобы получить преимущества масштабируемости
async
:Или (если ваша логика в этом методе действительно сквозная):
Учтите, что так легче работать «изнутри наружу», чем «снаружи внутрь». Другими словами, не начинайте с действия асинхронного контроллера, а затем заставляйте нижестоящие методы быть асинхронными. Вместо этого определите естественно асинхронные операции (вызов внешних API-интерфейсов, запросы к базе данных и т. Д.) И сделайте их асинхронными на самом низком уровне вначале (
Service.ProcessAsync
). Тогда пустьasync
потоку просочиться, сделав действия вашего контроллера асинхронными в качестве последнего шага.И ни при каких обстоятельствах нельзя использовать
Task.Run
в этом сценарии.источник
Это правильно, но, возможно, бесполезно.
Поскольку ждать нечего - нет вызовов API-интерфейсов блокировки, которые могут работать асинхронно - тогда вы настраиваете структуры для отслеживания асинхронной операции (которая имеет накладные расходы), но затем не используете эту возможность.
Например, если уровень сервиса выполнял операции БД с Entity Framework, который поддерживает асинхронные вызовы:
Вы позволите рабочему потоку делать что-то еще, пока запрашивается база данных (и, следовательно, может обрабатывать другой запрос).
Await, как правило, требует полного упразднения: очень сложно приспособиться к существующей системе.
источник
Вы не используете async / await эффективно, потому что поток запроса будет заблокирован при выполнении синхронного метода
ReturnAllCountries()
Поток, назначенный для обработки запроса, будет бездействовать, пока
ReturnAllCountries()
выполняет свою работу.Если вы можете реализовать
ReturnAllCountries()
асинхронность, вы увидите преимущества масштабируемости. Это связано с тем, что поток может быть возвращен в пул потоков .NET для обработки другого запроса во времяReturnAllCountries()
выполнения. Это позволит вашей службе иметь более высокую пропускную способность за счет более эффективного использования потоков.источник
Я бы изменил ваш уровень обслуживания на:
так как он у вас есть, вы все еще используете свой
_service.Process
вызов синхронно и получаете очень мало или совсем не получаете пользы от его ожидания.При таком подходе вы заключаете потенциально медленный вызов в объект
Task
, запускаете его и возвращаете для ожидания. Теперь вы можете ожидатьTask
.источник
Service
не является асинхронным методом и не ожидается в самомService
вызове. Я могу понять его точку зрения, но не думаю, что она применима здесь.Task.Run
следует избегать в ASP.NET. Такой подход устранит все преимущества отasync
/await
и фактически будет работать хуже под нагрузкой, чем просто синхронный вызов.