Экспертиза · Сложные архитектуры
Несколько систем, которые должны работать вместе, в том числе когда одна из них падает.
Мы проектируем и эксплуатируем платформы из нескольких сервисов, с шиной сообщений, ограниченными повторными попытками, ключами идемпотентности, circuit breaker-ами и публикацией с автоматическим возвратом. Каждый шаблон ниже работает в собственной системе, а не на диаграмме.
Уже построеноМы эксплуатируем четыре собственные платформы с разными архитектурами и можем открыть их все. Цифры измерены сегодня командами, а не взяты из документации: aichat имеет 28 служебных директорий, 235 моделей данных на четырёх схемах и шину сообщений с 297 очередями и 17.525 связями; Kallina имеет 472 edge-функции, 559 миграций и 28 запланированных задач в базе; MEGA CRM имеет backend из 9.516 строк с 99 маршрутами и 179 политиками доступа в строку; Taskin запускает 21 запланированную задачу без единого Docker. Оговорка, которую мы говорим: в двух местах собственная документация отстала от кода — утверждение о числе строк было устаревшим на 16%, а схема инфраструктуры описывала сервер, на котором мы уже ничего не запускаем. Мы использовали измерение, а не документ.
«Сложная архитектура» не означает много коробок на рисунке. Это значит, что вы знаете, что происходит, когда одна из них не отвечает. Система с тремя сервисами, которые вызывают друг друга синхронно, без лимита повторных попыток и без идемпотентности, более хрупкая, чем монолит, — потому что каждая новая связь это новый способ отказа, а способы отказа множатся быстрее, чем функциональность.
Наша работа начинается с разделения обязанностей и заканчивается тем, что видно, когда что-то выходит из строя. В одной из собственных платформ сообщения не идут напрямую между сервисами, а проходят через шину с 297 очередями, 9 exchange и 17.525 связями, из которых 278 очередей генерируются на клиента, а не пишутся вручную. Восемь очередей имеют dead-letter exchange, и у восьми время жизни сообщения составляет пять минут — то есть сообщение, которое не может быть обработано, попадает туда, где его можно увидеть, а не исчезает.
Паттернов, которые мы применяем, немного, и они повторяются: повторы с лимитом, прописанным в коде, ключи идемпотентности, делающие вторую доставку того же события безвредной, выключатель, который останавливает вызовы к сервису, который регулярно падает, шлюз потребления перед действиями, которые стоят денег, и алерты с порогом повторения, чтобы периодическая неисправность не похоронила остальное.
Последняя часть, на которую смотрят, — публикация. Одна из платформ публикуется через синхронизацию файлов, без Docker, с проверкой, что обслуживаемая страница содержит ровно идентификатор только что опубликованного пакета — не просто что сервер отвечает 200 — и с автоматическим откатом к предыдущей версии, если проверка не проходит. Правило появилось после реального инцидента, когда поверхностная проверка отменила удачную публикацию.