Ответ
Прямые синхронные вызовы (REST API, gRPC) уместны, когда необходим немедленный, транзакционный ответ в рамках одного запроса от клиента.
Ключевые сценарии применения:
- Синхронные цепочки действий (SAGA Orchestration): Когда следующий шаг зависит от результата предыдущего.
- Пример:
Проверить запас товара → Заблокировать товар → Создать заказ.
- Пример:
- Запросы данных в реальном времени: Получение текущего баланса пользователя, проверка авторизации (API Gateway → Auth Service).
- Простая CRUD-логика: В небольших системах или внутри защищенного периметра, где сложность асинхронности не оправдана.
- Ситуации, где важен немедленный успех/ошибка: Операция оплаты, где клиент должен сразу узнать результат.
Пример синхронного REST-вызова (Spring Boot):
@Service
public class PaymentService {
@Autowired
private RestTemplate restTemplate;
public PaymentResult processPayment(PaymentRequest request) {
// 1. СИНХРОННЫЙ вызов для проверки баланса
ResponseEntity<Boolean> balanceCheck = restTemplate.postForEntity(
"http://account-service/api/v1/balance/check",
request,
Boolean.class
);
if (!balanceCheck.getBody()) {
throw new InsufficientFundsException(); // Немедленная ошибка клиенту
}
// 2. СИНХРОННЫЙ вызов для списания средств
restTemplate.postForEntity(
"http://account-service/api/v1/balance/debit",
request,
Void.class
);
// 3. Локальная операция - создание записи о платеже
return createPaymentRecord(request);
}
}
⚠️ Риски прямых вызовов:
- Жесткая связь (Tight Coupling): Сервис-потребитель должен знать эндпоинт и формат ответа сервиса-провайдера.
- Каскадные отказы: Падение одного сервиса может «повалить» всю цепочку вызовов. Для смягчения необходимы Circuit Breaker (Hystrix, Resilience4j) и повторные попытки (Retry).
- Снижение производительности: Общее время ответа равно сумме задержек всех вызванных сервисов.
Итог: Используйте синхронную коммуникацию для прямых, транзакционных запросов, но обязательно применяйте паттерны устойчивости к отказам.