Один сценарий тянет за собой десять действий
После принятия заказа надо уведомить клиента, зарезервировать товар, выписать документ, обновить отчёт и сообщить в 1С. Сейчас это одна цепочка, и сбой в хвосте роняет начало.
Event-driven система — это система, в которой части общаются событиями: «заказ принят», «оплата получена», «остаток изменился». Отправитель не ждёт получателя, а получателей можно добавлять, не трогая отправителя. Такой подход нужен не всякой системе: он избавляет от одних проблем и приносит другие. Мы разбираем ваши потоки, оставляем события там, где они окупаются, и проектируем контракты, повторы без дублей и видимость сбоев так, чтобы систему могла сопровождать ваша команда.
Обследование потоков — от 200 000 ₽, 2–3 неделиНачинаем с одного потока, а не с перестройки всей системыИсходный код и описание событий в вашем репозитории с первого коммита
После принятия заказа надо уведомить клиента, зарезервировать товар, выписать документ, обновить отчёт и сообщить в 1С. Сейчас это одна цепочка, и сбой в хвосте роняет начало.
Приём заявок не должен зависеть от того, жива ли сегодня учётная система или платёжный провайдер. Заявку надо принять и довести позже.
Аналитике понадобились те же данные, и команда заказов снова вносит изменения в свой код.
Очередь поставили, а что в ней лежит и что делать с зависшим сообщением, не записано. Дубли находят по жалобам.
Путаница между этими тремя понятиями — самая частая причина неудачных событийных схем. Различие простое, но от него зависят имена, права и ответственность.
Событие — это публичный интерфейс системы, такой же, как API. Его меняют осторожнее, чем внутренний код, потому что читателей вы можете не знать.
Короткое событие несёт только идентификатор объекта: «заказ 42 изменился». Получатель идёт за подробностями к источнику. Это просто и всегда актуально, но источник должен выдерживать запросы всех читателей и быть доступным. Полное событие несёт нужные поля: сумму, состав, статус. Читателю не нужно ходить к источнику, зато схема становится общим договором, и поле, которое вы решили переименовать, ломает чужие обработчики.
Мы выбираем по тому, кто читает: для внутренних потребителей годится полное событие, для внешних систем часто безопаснее короткое. Выбор записывается в каталог вместе с причиной.
Результатом проектирования становится таблица: событие, кто выпускает, кто читает, что значит поле, как долго храним, что делать, если обработчик не справился. Без неё через год никто не скажет, можно ли удалить поле. Каталог лежит в репозитории рядом с кодом и проверяется в сборке: изменение схемы, ломающее читателя, не проходит.
Когда шагов несколько, надо решить, кто знает весь порядок. От этого зависит, как вы будете искать причину сбоя.
Как отправитель надёжно записывает событие вместе с изменением данных (исходящий ящик), описано на странице про микросервисы и высокую нагрузку. Здесь о другой половине: что должен делать читатель.
Практически все брокеры гарантируют, что сообщение дойдёт хотя бы один раз, но не ровно один. Сеть оборвалась после обработки, подтверждение не дошло, сообщение пришло снова. Поэтому обработчик обязан давать тот же результат при повторе. Способы такие: хранить идентификаторы обработанных событий; записывать результат так, чтобы повторная запись ничего не меняла (установить статус, а не прибавить единицу); поставить в базе ограничение на повтор пары «событие, обработчик».
Если события одного заказа обрабатываются разными обработчиками параллельно, «отменён» может обработаться раньше «создан». Решения два: направлять события одного ключа одному обработчику или хранить в данных версию объекта и отбрасывать устаревшие события. Глобальный порядок всех событий почти никогда не нужен и дорого стоит, поэтому мы сначала выясняем, где порядок действительно важен.
Событие, которое обработчик не может разобрать, нельзя бесконечно повторять: оно заблокирует очередь. После нескольких попыток с нарастающей паузой сообщение уходит в отдельный список недоставленных. Человек видит его в панели, понимает причину и повторяет обработку после исправления. Список недоставленных, в котором никто не смотрит, — тот же потерянный заказ.
После «Оплатить» экран не должен показывать старый статус, если обработчик отстал на минуту. В интерфейсе вводим состояние «обрабатывается» и понятное сообщение при сбое. Если от результата зависит следующий шаг пользователя, этот шаг лучше сделать синхронным вызовом.
Выбор делаем по нагрузке, составу команды и тому, кто будет этим управлять после сдачи. Нагрузку считаем на вашем профиле, а не по общим цифрам.
Проверка остатка перед оплатой, расчёт цены в корзине, вход пользователя. Здесь пользователь ждёт, и синхронный вызов с тайм-аутом честнее очереди.
Если два изменения должны произойти только вместе, события превращают это в цепочку компенсаций. Держите их в одной базе и одной транзакции, пока можете.
Асинхронная система требует панели, оповещений и дежурного порядка разбора. Без них сбои копятся молча. Круглосуточного дежурства мы не обеспечиваем, это надо закладывать у вас.
Цены совпадают со страницей тарифов. Цена после первой ступени называется по результатам, остановиться можно после любой.
Карта потоков, замер нагрузки и частоты сбоев, список мест, где события оправданы, и мест, где достаточно вызова. На выходе черновой каталог событий, выбор носителя с причинами, вилка бюджета. Вычитается из первого этапа, если продолжаете с нами.
Если события должны связать учёт, склад, сайт и внешние сервисы: матрица источников истины, схема обменов, перечень точек отказа.
Выбираем один поток, где сбой дороже всего, выносим его на события, запускаем рядом со старым путём и сравниваем результаты. Каталог, панель недоставленных, оповещения.
Процесс с откатами и сроками, интеграция с боевыми системами, нагрузочная проверка, регламент разбора сбоев.
Перевод остальных потоков по одному, отключение старых связей, обучение вашей команды, передача каталога и инструкций.
Мониторинг очередей, разбор недоставленного, плановые доработки с пакета на 60 000 ₽. Три пакета: до 4, 12 или 25 часов в месяц; сверх пакета 5 000 ₽ в час.
Берём журналы за пиковые дни, список инцидентов и схему вызовов. Отмечаем, где сбой одной части останавливает другую.
Названия, поля, версии, ключи порядка, срок хранения.
Поднимаем носитель на тестовом стенде, пишем сценарии: обработчик упал, сообщение пришло дважды, события перепутались, носитель недоступен.
Новый путь работает рядом со старым, результаты сравниваются. Откат на старый путь возможен до приёмки.
Глубина очередей, возраст старейшего сообщения, число недоставленных, время цепочки. Порог оповещения согласуем с вами.
Переводим следующий поток, только если первый показал пользу. Остановиться можно сразу после пилота: сделанное остаётся у вас.
Каждая система добавляет контракт, тесты и сценарии отказов. Закрытая учётная система без интерфейса стоит дороже открытой.
События, где порядок не важен, дешёвые. Деньги, остатки и статусы требуют ключей порядка, проверки версий и сверки с учётом.
Если запись в базу и отправка идут раздельно, это правится до событий. Нет границ модулей — наводим их сначала.
Очередь в вашей базе не требует нового сервиса. Брокер или журнал событий требуют мониторинга и человека, который их знает.
Простыми словами: чем событие отличается от вызова, на каких задачах окупается подход и по каким признакам можно обойтись без него.
Что платите за распределённость и как резать систему по понятиям. Пригодится, если события нужны между частями одной большой системы.
Повторы запросов, ключ идемпотентности, вебхуки с повторной доставкой. Те же принципы применимы к событиям.
Сорок минут созвона: какие части системы связаны между собой, где сбой одной роняет другую и что нужно пользователю сразу, а что может подождать. По итогам скажем, нужны ли события, с какой ступени начинать и в какую вилку это укладывается.
Цена зависит от числа потоков и систем, а не от самой технологии. Обследование потоков стоит 200 000 ₽ за один-два процесса и 350 000 ₽ за несколько систем; оно вычитается из первого этапа, если продолжаете с нами. Пилот одного потока 150 000–400 000 ₽, тяжёлый пилот с координатором и боевой интеграцией 400 000–1 200 000 ₽. Вывод в эксплуатацию от 1 500 000 ₽ этапами по 300 000–700 000 ₽.
Часто достаточно очереди фоновых задач внутри приложения и чётких границ модулей. Событийная схема между частями монолита оправдана, когда отдельные модули должны реагировать на изменения других, не зная о них, и когда вы готовитесь выделять сервисы. Обследование покажет, какой из случаев ваш.
Для небольшого потока и команды без опыта с брокерами начинаем с очереди в PostgreSQL: не нужен новый сервис, запись события и данных идёт в одной транзакции. Для задач с маршрутизацией и повторами берём RabbitMQ. Журнал вроде Kafka рассматриваем, когда нужны большой поток, несколько независимых читателей и повторный разбор истории.
Отправитель записывает событие в ту же транзакцию, что и изменение данных, а отдельный процесс передаёт его в очередь. Получатель выдерживает повтор: запоминает обработанные идентификаторы или записывает результат так, чтобы повтор ничего не менял. Необработанное попадает в список недоставленных, который кто-то смотрит. Проверяем это сценариями отказов на стенде, до запуска.
В каждое событие и запись журнала кладём идентификатор цепочки, по нему собирается путь заказа через все части. Для главных процессов добавляем сквозную трассировку и панель с возрастом старейшего необработанного сообщения. Без этой наблюдаемости распределённую систему мы не сдаём.
На ваших серверах или у выбранного вами хостера. Исходный код, каталог событий и инструкции в вашем репозитории с первого коммита. Результат работ передаётся вам по акту; порядок передачи прав записывается в договоре; открытые компоненты остаются под своими лицензиями, их список входит в документацию.
Ежемесячно: 20 000, 60 000 или 120 000 ₽ в месяц, до 4, 12 или 25 часов. Часы уходят на мониторинг очередей, разбор недоставленного и обращения; плановые доработки входят с пакета на 60 000 ₽. Сверх пакета 5 000 ₽ в час, по согласованию до начала.
Мы в Ростове-на-Дону, работаем с заказчиками по всей России: удалённо и в вашем контуре. Доступ к системам и обследование согласуем на старте с вашей службой безопасности.