← Назад к вопросам
В чем разница между синхронной и асинхронной коммуникации?
2.0 Middle🔥 251 комментариев
#REST API и микросервисы#Брокеры сообщений
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Разница между синхронной и асинхронной коммуникацией
Это фундаментальное различие в архитектуре распределённых систем. Выбор между ними определяет надёжность, производительность и сложность.
1. Синхронная коммуникация
Принцип
Отправитель блокируется ДО получения ответа
Отправитель: Отправляю запрос
↓
Жду ответ (БЛОКИРОВАН)
↓
Получил ответ
↓
Продолжаю работу
Пример: HTTP запрос (REST API)
@RestController
public class OrderController {
@PostMapping("/orders")
public ResponseEntity<Order> createOrder(@RequestBody CreateOrderRequest req) {
// 1. Блокировка
Order order = orderService.create(req);
// 2. Отправку на сервис платежей
PaymentResult result = paymentService.charge(order.getAmount());
// 3. Если платёж не прошёл → ошибка
if (!result.isSuccess()) {
throw new PaymentFailedException();
}
// 4. Сохраняю заказ
orderRepository.save(order);
// 5. Возвращаю результат клиенту
return ResponseEntity.ok(order);
}
}
public class SyncClient {
public static void main(String[] args) {
Order order = restTemplate.postForObject(
"http://api.example.com/orders",
createOrderRequest,
Order.class
);
// Блокирован, пока не получит ответ
System.out.println("Order created: " + order);
}
}
Характеристики синхронной коммуникации
✅ Плюсы:
- Просто реализовать
- Понятный flow кода
- Сразу знаешь результат
- Легко handle ошибки
❌ Минусы:
- Зависимость между системами (coupling)
- Если получатель медленный → весь процесс медленный
- Если получатель упал → всё падает
- Плохая масштабируемость (нужно много потоков)
- Timeout проблемы
Проблема синхронной коммуникации
Сценарий:
order-service → payment-service → bank-api
Если bank-api медленный (5 секунд):
- order-service тоже медленный
- пользователь ждёт 5 секунд на каждый заказ
- при 1000 одновременных запросов → 5000 потоков заблокировано!
2. Асинхронная коммуникация
Принцип
Отправитель НЕ блокируется, продолжает работу
Отправитель: Отправляю сообщение в очередь
↓
Сразу продолжаю работу
↓
Получатель обрабатывает в своём темпе
Пример: Message Queue (Kafka, RabbitMQ)
@RestController
public class OrderController {
@PostMapping("/orders")
public ResponseEntity<Order> createOrder(@RequestBody CreateOrderRequest req) {
// 1. Создаю заказ
Order order = orderService.create(req);
// 2. Сохраняю в БД
orderRepository.save(order);
// 3. Отправляю сообщение в Kafka (не блокирую!)
kafkaTemplate.send("payment-topic", new PaymentEvent(
order.getId(),
order.getAmount()
));
// 4. СРАЗУ возвращаю результат
return ResponseEntity.accepted().body(order);
// Платёж будет обработан в background
}
}
@Service
public class PaymentProcessor {
@KafkaListener(topics = "payment-topic", groupId = "payment-service")
public void processPayment(PaymentEvent event) {
// Эта функция выполняется В ОТДЕЛЬНОМ потоке
// Получатель обрабатывает в своём темпе
try {
paymentService.charge(event.getAmount());
// Если ошибка → send to dead-letter queue
} catch (PaymentFailedException e) {
kafkaTemplate.send("payment-failed-topic", event);
}
}
}
Характеристики асинхронной коммуникации
✅ Плюсы:
- Слабое связывание (loose coupling)
- Получатель может быть медленный — не влияет на отправителя
- Высокая масштабируемость (потребители обрабатывают в очереди)
- Отказоустойчивость (если получатель упал → message ждёт)
- Лучший throughput
❌ Минусы:
- Сложнее в реализации
- Не сразу знаешь результат
- Обработка ошибок сложнее (retry logic, DLQ)
- Нужна очередь (infrastructure)
- Данные могут быть в intermediate states
Сравнение диаграмм
Синхронная
Польз. Order Service Payment Service Bank
│ │ │ │
├─ POST /orders ─────────────────→
│ │ │ │
│ ├─ charge() ───────────────────→
│ │ │ блокирован │
│ БЛОКИРОВАН │ │
│ │ │← результат─┤
│ │← результат ──────┤ │
│← 200 OK ────┤ │ │
│ │ │ │
Асинхронная
Польз. Order Service Kafka Payment Service
│ │ │ │
├─ POST /orders ────────────┥ │
│← 202 Accepted ───┤ │
│ (сразу!) │ │ │
│ │ │ │
│ обрабатывает │ │ │
│ ├─ send message ────→
│ │ │ │
│ │ │ обрабатывает
│ │ │ в своём темпе
│ │ │ │
Выбор между ними
Используй синхронную, если:
✅ Нужен сразу результат
✅ Simple request-response flow
✅ Система small (<10 RPS)
✅ Требуется ACID (транзакции)
✅ REST API, где результат обязателен
Используй асинхронную, если:
✅ Результат не нужен сразу
✅ Высокая нагрузка (>100 RPS)
✅ Получатель может быть медленный
✅ Отказоустойчивость важна
✅ Микросервисная архитектура
✅ Loose coupling нужен
Практические примеры
Пример 1: Email отправка
Синхронно (плохо)
@PostMapping("/register")
public ResponseEntity<User> register(@RequestBody RegisterRequest req) {
User user = createUser(req);
// БЛОКИРУЕМСЯ на отправку email (5 секунд!)
emailService.sendWelcomeEmail(user.getEmail());
return ResponseEntity.ok(user);
// пользователь ждёт 5 сек, пока отправим email
}
Асинхронно (хорошо)
@PostMapping("/register")
public ResponseEntity<User> register(@RequestBody RegisterRequest req) {
User user = createUser(req);
userRepository.save(user);
// Отправляем в Kafka (instant)
kafkaTemplate.send("email-topic", new EmailEvent(
user.getEmail(),
"Welcome"
));
// Сразу возвращаем (пользователь не ждёт)
return ResponseEntity.ok(user);
}
Пример 2: Платёж
Синхронно (может быть OK)
@PostMapping("/checkout")
public ResponseEntity<Order> checkout(@RequestBody OrderRequest req) {
Order order = createOrder(req);
// НУЖНО знать результат платежа (success/fail)
PaymentResult result = paymentGateway.charge(order.getAmount());
if (!result.isSuccess()) {
return ResponseEntity.badRequest().build();
}
orderRepository.save(order);
return ResponseEntity.ok(order);
}
Асинхронно (для больших систем)
@PostMapping("/checkout")
public ResponseEntity<Order> checkout(@RequestBody OrderRequest req) {
Order order = createOrder(req);
order.setStatus(OrderStatus.PENDING_PAYMENT); // Промежуточный статус
orderRepository.save(order);
// Асинхронный платёж
kafkaTemplate.send("payment-topic", new PaymentEvent(
order.getId(),
order.getAmount()
));
// Возвращаем сразу
return ResponseEntity.accepted().body(order);
}
// Payment consumer
@KafkaListener(topics = "payment-topic")
public void processPayment(PaymentEvent event) {
try {
PaymentResult result = paymentGateway.charge(event.getAmount());
if (result.isSuccess()) {
// Update order
Order order = orderRepository.findById(event.getOrderId()).orElse(null);
order.setStatus(OrderStatus.PAID);
orderRepository.save(order);
// Отправить notification
kafkaTemplate.send("order-paid-topic", order);
}
} catch (Exception e) {
// Send to DLQ (Dead Letter Queue)
kafkaTemplate.send("payment-failed-topic", event);
}
}
Hybrid подход
Можно комбинировать оба подхода:
@PostMapping("/orders")
public ResponseEntity<Order> createOrder(@RequestBody OrderRequest req) {
// 1. Синхронно создаём заказ (нужен результат)
Order order = orderService.create(req);
orderRepository.save(order);
// 2. Асинхронно обрабатываем (не нужен результат)
kafkaTemplate.send("order-processing-topic", order);
return ResponseEntity.ok(order);
}
Timeout и Retry в синхронной коммуникации
// Важно! Всегда используй timeout
public void callRemoteService() {
RestTemplate restTemplate = new RestTemplate();
// Без timeout → может зависнуть на 60+ сек
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
// С timeout
String response = restTemplate.getForObject(
"http://slow-service.com/api",
String.class
);
}
// Лучше: с CircuitBreaker
@Service
public class RemoteCallService {
@CircuitBreaker(failureThreshold = 5, delay = 1000)
public String callRemoteService() {
return restTemplate.getForObject("http://...", String.class);
}
}
Итог
| Аспект | Синхронная | Асинхронная |
|---|---|---|
| Блокировка | Да (ждёт ответ) | Нет (сразу продолжает) |
| Coupling | Плотное | Слабое |
| Результат | Сразу известен | Позже |
| Scalability | Плохо | Отлично |
| Complexity | Просто | Сложнее |
| Reliability | Зависит от получателя | Независимо |
| Latency | Зависит от всех | Низко |
| Throughput | Ограничено | Высокий |
Правило большого пальца:
- Синхронная = когда результат критичен (checkout)
- Асинхронная = когда масштабируемость критична (notifications, analytics)