Преимущества асинхронного программирования. Сравнение ASP.NET Core и MVC
09 апреля 2021

Преимущества асинхронного программирования. Сравнение ASP.NET Core и MVC

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

На основе сравнения на реальных примерах разберем, почему async - это круто и сделаем выводы, стоит ли придерживаться старых принципов.

Компилятор выполняет множество преобразований, чтобы сделать асинхронное программирование максимально похожим на синхронное. Для этого он создает экземпляр конечного автомата, передает его построителю асинхронного метода, который вызывает объект awaiter для задачи, и т.д.

Подобная логика работы имеет свою цену, но стоит ли нам вообще задумываться над этим?

Пока в .net не появилась библиотека TPL (Task Parallel Library), асинхронные операции не были так широко распространены. Хотя в текущих реалиях даже маленькое приложение выполняет сотни, а то и тысячи асинхронных операций в секунду.

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

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

Из такого ответа вытекает еще несколько вопросов:

  • Как обработать ошибку выполнения асинхронной операции?
  • Как получить и обработать результат выполнения?
  • Как поступить, если нужно выполнить сразу несколько таких операций?

Рассмотрим реальный метод аутентификации.

Это классический асинхронный метод контроллера asp.net core. Он принимает некую модель данных пользователя и асинхронно (не блокируя один из потоков из пула потоков приложения на все время выполнения метода) выполняет аутентификацию пользователя.

Первым делом пытается выполнить аутентификацию пользователя.

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

После того как модель пользователя получена, выполняется создание токена доступа к АПИ.

Как только токен сгенерирован и записан, он возвращается в основной вызывающий метод. И уже там формируется ответ на запрос клиента.

Что в итоге дает нам такой подход?

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

Так что произойдет при синхронном выполнении этого кода?

На обработку одного такого запроса из пула потоков выделится один поток, и он будет заблокирован на все время выполнения операции. Это не вызовет неудобств, если обращения к API редкие или приложение развернуто на мощном сервере с огромным количеством ресурсов.

А если в один момент времени придет 5, 10 или 100 запросов к API? На каждый запрос будет выделен поток из пула потоков. В конечном итоге свободных потоков не останется, и запросы будут попадать в очередь. Но и очередь не бесконечна, в итоге на клиенте возникнет ошибка 503, которая говорит нам, что веб сервер временно недоступен.

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

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

Чем отличаются ASP.NET Core и MVC?

Во-первых, основное отличие в том, что технология ASP.NET Core поддерживает кроссплатформенность. Если вы не хотите использовать сервер на Microsoft Windows, то нет никаких проблем, используйте Linux. Технология ASP.Net.Core.EntityFramework позволит реализовать подключение, например, к базе данных на PostgreSql.

Если вы начинаете разработку нового веб приложения с использованием MVC или Web API, вам определенно нужно обратить внимание на ASP.NET Core. Технология содержит в себе целую серию значительных улучшений, которые заметно отличают её от предшественницы. Помимо прочего, она также может похвастаться первоклассной системой внедрения зависимостей, тем самым можно избавиться от использования сторонних DI контейнеров таких как Unity, Ninject и им подобных.

Огромный плюс в том, что переход на новую платформу не займет много времени, если вы ранее использовали ASP.NET MVC или Web API. Основной прицнип ASP.NET Core – использовать все основные фишки предшественника, но делать это гораздо лучше. Конечно, отличия все же есть, но это не станет огромной проблемой. Несколько новых вещей, вроде того, как запускается приложение или как работает конвейер обработки запросов, выучить придется, но в целом опыт работы на предыдущей ASP.NET MVC тут будет решать очень многое.

Основная фишка ASP.NET Core - это, конечно же, конвейер обработки запросов (middleware). Весь цикл обработки запроса клиента построен на принципе конвейера. Сначала данные запроса получает первый компонент в конвейере. После обработки он передает данные HTTP-запроса второму компоненту и так далее.

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

Тут может возникнуть закономерный вопрос: погоди, ведь все тоже самое можно сделать в ASP.NET MVC с помощью фильтров? Конечно, можно, но система фильтров не настолько гибкая и удобная, как конвейер обработки запросов в ASP.NET Core.

Например, мы используем один этап конвейера обработки запросов для поддержки веб-сокетных соединений в наших сервисах.

Или же для корректного преобразования запроса с телом в xml со стороны 1С.

Вариаций использований может быть масса, и добиться этого с помощью фильтров ASP.NET MVC не всегда получится.

Если вернуться к вопросу об асинхронности, то в ASP.NET Core также была внедрена отличная система управления потоками и контроля за ними. Таким образом, каждый поток имеет возможность вернуться в пул и обработать уже другой входящий запрос, тем самым увеличивается количество запросов, которые можно обработать в один момент времени. В ASP.NET MVC это, конечно, тоже было, но net.core делает это гораздо лучше своего предшественника.

Так как же поступить в конечном итоге?

Если вы планируете разработать совершенно новое приложение, то лучше посмотреть в сторону ASP.NET Core.

А если у вас уже есть работающие приложения и вам не нужны все современные технологии, то конечно ваше право остаться на ASP.NET MVC.

Как в итоге поступили мы, команда 42Clouds? Мы выбрали современный путь. И постепенно избавляемся от старых технологий, внося в наш проект все новое и актуальное. То есть мы придерживаемся основного принципа ASP.NET Core. Сохраняем все старые фишки, привносим новые технологии и делаем это лучше, чем было раньше.

Комментарии для сайта Cackle

Сервисы 1С для работы с маркетплейсами