При работе с системами, основанными на событиях, и особенно при использовании нескольких производителей и / или потребителей, важно смириться с тем фактом, что обычно не существует такого понятия, как гарантированный порядок событий.И чтобы получить надежную систему, также целесообразно спроектировать систему так, чтобы обработчики сообщений были идемпотентными;они должны терпеть получение одного и того же сообщения дважды (или более).
Существует множество способов, которые могут (и фактически должны позволять) мешать порядку;
- Производители могут доставлять сообщения в несколько ином темпе
- Один производитель может пропустить квитанцию (из-за пропущенного пакета) и повторно отправит сообщение
- Один потребитель может получить и обработать сообщение,но подтверждение на обратном пути теряется, поэтому сообщение доставляется дважды (другому потребителю).
- Некоторые другие службы, от которых зависят ваши обработчики, могут быть недоступны, поэтому вам придется отклонить сообщение.
При этом существует одна схема, которую системы сервисных шин, такие как NServicebus , используют для принудительного использования сообщений заказа.Существуют некоторые требования:
- Вам потребуется централизованное хранилище (например, sql-сервер или хранилище документов), которое позволяет выполнять условные обновления;например, вы хотите иметь возможность хранить порядковый номер последнего обработанного сообщения (или как далеко вы продвинулись в процессе), но только , если уже сохраненная последовательность / ход выполнения является правильной / ожидаемой,Хранение идентификатора пользователя и прогресса даже для миллионов клиентов должно быть очень простой операцией для большинства баз данных.
- Вы должны убедиться, что очередь настроена на dead-letter-queue / exchange для повторных попыток, а затем снова установите исходную очередь в качестве очереди недоставленных писем.
- Вы устанавливаете TTL (например, 30 секунд) в очереди на повторную попытку / недоставленное письмо.Таким образом, сообщения, которые появляются в очереди недоставленных писем, будут автоматически возвращаться в исходную очередь через некоторое время.
- При обработке сообщений вы проверяете свое хранилище / базу данных, если вы находитесь в правильном состоянии дляобработать сообщение (т.е. необходимые предыдущие шаги уже выполнены).
- Если вы можете справиться с этим, вы делаете и обновляете хранилище (условно!).
- Если не - вы убираете сообщение, чтобы оно было брошеноочередь мертвых писем.По сути, вы говорите: «Нет, я не могу обработать это сообщение, возможно, в очереди есть еще какое-то сообщение, которое должно быть обработано первым».
Таким образом, счастливый-path - обрабатывать большое количество сообщений в правильном порядке.Но если что-то случится и вы получите сообщение вне группы, вы бросите его в очередь повторов (очередь недоставленных писем), и Кролик удостоверится, что оно вернется в очередь для повторной попытки на более позднем этапе.,Но только с задержкой.
Прелесть этого в том, что вы способны справиться с большинством ситуаций, которые могут помешать обработке сообщения (неупорядоченные сообщения, отключение зависимых служб, отключение вашего обработчика)в середине обработки сообщения) точно таким же образом;отклоняя сообщение и позволяя вашей инфраструктуре (Кролику) позаботиться о том, чтобы через некоторое время его повторили.