Питання 18 · Розділ 17

Що таке патерн Bulkhead

Structured Java interview answer with junior, middle, and senior-level explanation.

Мовні версії: English Russian Ukrainian

🟢 Junior Level

Bulkhead (перебірка) — патерн, який ізолює ресурси для різних операцій, щоб збій в одній не впливав на інші.

Аналогія з життя: корабель розділений на відсіки (bulkheads). Якщо один відсек затоне — корабель не потоне цілком.

Без Bulkhead:
Thread Pool [====================]
Усі виклики ділять один пул → один повільний сервіс займає усі потоки

З Bulkhead:
Thread Pool A [========] → Сервіс A
Thread Pool B [========] → Сервіс B
Thread Pool C [========] → Сервіс C
Сервіс A повільний → впливає тільки на Pool A

Коли НЕ використовувати Bulkhead

  • Один виклик до всього сервісу — якщо сервіс атомарний, розділення потоків безглузде
  • Мало потоків — overhead на управління пулами більше вигоди
  • Повністю асинхронна система — backpressure вирішує проблему інакше

🟡 Middle Level

Реалізація з Resilience4j

BulkheadConfig config = BulkheadConfig.custom()
    .maxConcurrentCalls(10)  // максимум 10 одночасних викликів
    .maxWaitDuration(Duration.ofSeconds(1))  // чекати 1 сек якщо full
    .build();

// maxWaitDuration — скільки потік чекає, якщо bulkhead повний.
// Після закінчення — BulkheadFullException (не timeout!).
// ThreadPool bulkhead ставить в чергу, Semaphore — блокує або кидає.

Bulkhead bulkhead = Bulkhead.of("backend", config);

Supplier<String> decorated = Bulkhead.decorateSupplier(bulkhead,
    () -> backendService.call());

Типи Bulkhead

1. Semaphore:

Ліміт одночасних викликів
Легкий, no thread overhead

2. Thread Pool:

Окремий пул потоків для кожного сервісу
Ізоляція на рівні потоків

Типові помилки

  1. Занадто малий ліміт:
    maxConcurrentCalls = 2 → більшість запитів rejected
    Потрібно налаштувати за метриками
    

🔴 Senior Level

Архітектурні Trade-offs

Thread Pool Semaphore
Повна ізоляція (свої потоки), але overhead на кожен потік Легше (менше пам’яті), але немає ізоляції потоків — усі в одному thread pool
Thread isolation Немає thread isolation
Більше ресурсів Менше overhead

Production Experience

resilience4j:
  bulkhead:
    instances:
      userService:
        maxConcurrentCalls: 20
      paymentService:
        maxConcurrentCalls: 10
      searchService:
        maxConcurrentCalls: 30

Best Practices

✅ Окремий bulkhead на кожен зовнішній сервіс
✅ Ліміти за метриками
✅ Моніторьте rejection rate
✅ Комбінуйте з Circuit Breaker

❌ Один bulkhead на все
❌ Занадто малі ліміти
❌ Без моніторингу

🎯 Шпаргалка для співбесіди

Обов’язково знати:

  • Bulkhead ізолює ресурси (thread pool) для різних операцій
  • Аналогія: відсіки корабля — один потонув, корабель не потонув
  • Два типи: Thread Pool (повна ізоляція, overhead) і Semaphore (легший, немає thread isolation)
  • Без Bulkhead один повільний сервіс забирає усі потоки спільного пулу
  • maxConcurrentCalls налаштовується за метриками для кожного сервісу окремо
  • Комбінуйте з Circuit Breaker для максимального захисту
  • НЕ потрібен для одного атомарного виклику, малого числа потоків, повністю асинхронних систем

Часті уточнюючі питання:

  • Thread Pool vs Semaphore? Thread Pool = свої потоки, повна ізоляція, більше overhead. Semaphore = блокує або кидає, легший.
  • Як налаштувати maxConcurrentCalls? За метриками: спостерігайте нормальне навантаження, поставте з запасом.
  • Що буде при занадто малому ліміті? Більшість запитів rejected — BulkheadFullException.
  • Навіщо окремий bulkhead на кожен сервіс? Щоб повільний Payment Service не впливав на User Service.

Червоні прапорці (НЕ говорити):

  • “Bulkhead = Circuit Breaker” — ні, Bulkhead ізолює ресурси, CB блокує виклики
  • “Один bulkhead на все достатньо” — ні, тоді немає ізоляції
  • “maxConcurrentCalls = 2 — хороший захист” — ні, більшість запитів будуть rejected
  • “Semaphore не потрібен, тільки Thread Pool” — Semaphore легший, підходить для багатьох випадків

Пов’язані теми:

  • [[17. Як забезпечити відмовостійкість мікросервісів]]
  • [[5. Що таке патерн Circuit Breaker]]
  • [[6. Як працює Circuit Breaker і які у нього стани]]
  • [[19. Що таке патерн Retry і як його правильно використовувати]]
  • [[15. Як організувати комунікацію між мікросервісами]]