Опытный разработчик не так давно зашёл в .Net и поставил цель получить сертификат Microsoft. Свой ежедневный прогресс он описывает на канале .Net Разработчик. Заметки об изученном материале, советы по повышению производительности и поддержке мотивации, ин
День 1038.
Асинхронный Обмен Сообщениями. Продолжение
1. Основы распределённой архитектуры
2. Перманентные очереди
Примеры устойчивых очередей
3. Бэкенд-сервисы
4. Получение результатов
Важно отметить, что существует множество сценариев, которые не требуют явной отправки результатов. Например, отправка e-mail. Исходному клиенту не нужно получать уведомление о том, что письмо действительно было отправлено. Другой случай - когда конечный пользователь обновляет страницу. Он рано или поздно увидит результаты. Поэтому первый вопрос, который следует задать: действительно ли получение результатов необходимо?
Рассмотрим варианты получения результатов для REST API.
Опрос
Клиент может опрашивать конечную точку «статуса», пока не будут доступны результаты, а затем получить окончательный результат (или ошибку). К сожалению, вариантов реализации этого шаблона очень много. Единственное принятое соглашение: для вызова, который инициирует асинхронный обмен сообщениями, HTTP-приложение должно поместить сообщение в перманентную очередь, а затем вернуть 202 Accepted.
Приложение также должно возвращать информацию, которая позволит клиенту опрашивать статус завершения. Обычно это какой-то URI «статуса». Стандарт требует либо ссылку на монитор статуса, либо примерное время, когда запрос будет выполнен. Это очень нечёткое требование, и именно здесь реализации начинают расходиться. Один из вариантов - вернуть URI статуса в теле 202 Accepted (например, в JSON). Другой вариант - вернуть URI статуса в заголовке ответа Location.
Как только клиент получит URI статуса, он может начать периодически вызывать этот URI для получения статуса асинхронной операции. Опять же, реализации расходятся в деталях. Пока операция не завершена, некоторые реализации возвращают 200 OK с каким-то индикатором «незавершённого статуса» в теле. Другие снова возвращают 202 Accepted. Сервер также может дополнительно включать «процент завершения» в тело ответа и/или заголовок Retry-After, если он имеет предполагаемое время завершения (для предотвращения чрезмерно частых вызовов).
Если операция завершается с ошибкой, то URI статуса может либо вернуть 200 OK с «ошибкой» в теле ответа, либо вернуть соответствующий код ошибки (4xx/5xx) с дополнительными сведениями об ошибке в теле ответа. В случае успеха URI статуса может возвращать 303 See Other с заголовком Location для ресурса, который был обновлён/изменён через асинхронное сообщение. Либо вернуть 200 OK, 201 Created или 204 No Content, чтобы указать на успешное завершение.
Как видите, реализуется асинхронный обмен сообщениями с точки зрения REST API по-разному. Нет никаких стандартов или общепринятого образца. Не тратьте время на поиск «правильного» варианта, просто чётко задокументируйте, какой подход вы используете.
И последнее замечание: промежуточные результаты, вроде статуса операции, прогресса или URI обновлённого ресурса не обязательно должны быть долговечными. Их можно хранить в памяти, например в общем кэше.
Уведомление
В некоторых случаях клиентам необходимо немедленно знать, когда сообщение было обработано. В этом случае можно использовать систему уведомлений, инициированную сервером. В наши дни это почти всегда WebSockets (или SignalR), хотя старые решения, такие как длинный опрос или даже серверные события (SSE), тоже всё ещё существуют. Все эти решения позволяют приложению отправлять сообщение уже подключённому клиенту. Смысл в том, что бэкенд-сервис подключается к HTTP-приложению через какую-то шину (например, через хаб SignalR), а затем отправляет сообщение по этой шине непосредственно в HTTP-приложение, которое уведомляет клиентов. Есть только одно предостережение: шина должна быть готова к масштабированию. Некоторые системы (например, SignalR) по умолчанию не настроены на масштабирование.
Окончание следует…
Источник: blog.stephencleary.com/2021/01…lts.html