Основы взаимодействия сервисов

Базовый System Design
≈ 2 мин чтения

Сетевой вызов — не вызов метода

Внутри одного процесса вызов метода обычно либо быстро завершается, либо сразу сообщает об ошибке. Между сервисами всё иначе: запрос проходит через сеть, удалённый процесс может быть перегружен, перезапущен или вообще недоступен, а ответ может задержаться.

Service A -> network -> Service B
             |
             +-> latency
             +-> timeout
             +-> connection error

Поэтому границу сервиса полезно воспринимать как отдельный контракт с собственными правилами отказа. Клиент не должен исходить из предположения, что удалённый сервис всегда ответит вовремя.

Контракт важнее внутренней реализации

Сервисы взаимодействуют через внешний интерфейс: HTTP API, RPC-контракт или формат сообщения. Пока контракт остаётся совместимым, реализацию за ним можно менять независимо от клиента.

Хороший контракт однозначно описывает, какие данные нужны на входе, что возвращается в ответ, какие ошибки ожидаемы и какие гарантии имеет операция. Чем меньше клиент знает о внутреннем устройстве сервиса, тем проще развивать обе стороны независимо.

Есть два базовых способа передать работу

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

Удалённый вызов всегда дороже локального. Даже если API выглядит как обычный метод, за ним остаются сеть, сериализация, таймауты и независимый жизненный цикл другого процесса.