Как ускорить ответ контроллера Api с помощью асинхронного кода для запуска другой задачи при получении запроса? - PullRequest
0 голосов
/ 19 июня 2019

В моем контроллере API у меня есть метод под названием «SendMail», который получает сообщение с телом json, которое выглядит следующим образом:

{
    "MailTo": "abcdefg@hijklmn.opqrst",
    "Subject": "This is the subject",
    "Body": "This is the body"
}

При получении запроса метод «SendMail» проверяет данные и, если они верны, отправляется письмо.

[HttpPost]
public IHttpActionResult SendMail([FromBody] MailData mailData)
    {
        if(ValidateMailData(mailData) == true)
        {
             Email.send(mailData);
             return Ok("Your email was sent!");
        }

        return BadRequest("Some error");
    }

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

1 Ответ

2 голосов
/ 19 июня 2019

Вы должны отделить веб-слой вашего приложения от фактического сервисного слоя.
Обычно это делается с помощью очередей.

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

Если запрос пользователя является действительным, вы затем помещаете запрос в выделенную очередь, а затем возвращаете 202 принятого ответа с кодом состояния (обратите внимание, что вам не нужно фактически отправлять электронное письмо перед ответом на запрос). HTTP-запрос, вы просто должны быть уверены, что пользовательский запрос был успешно поставлен в очередь).

Если, в противном случае, пользовательский запрос недействителен на основе ваших правил проверки, вы вернете 422 код статуса необработанного объекта, чтобы пользователь понял, что его запрос недействителен.

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

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

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

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

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

Как вы думаете, более эффективно заказывать пиццу, а затем делать другие полезные вещи, пока пицца едет из ресторана в ваш дом или сидит перед дверью, ожидая пиццу и ничего не делая в это время? Что ж, если вы веб-сервер, вы очень заняты и наверняка у вас есть много важных дел (читай обслуживайте входящие HTTP-запросы ), пока пицца едет к вам домой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...