GH GambleHub

Пули з'єднань і latency

Пули з'єднань і latency

1) Навіщо потрібні пули

З'єднання коштують дорого (TCP/TLS handshakes, аутентифікація, warm-up). Пул дозволяє:
  • Перевикористати готові коннекти (keep-alive) → нижче TTFB.
  • Контролювати паралелізм і давати backpressure замість лавини ретраїв.
  • Зменшувати хвости p95/p99 за рахунок правильного розміру і таймаутів.

Ключові ризики: черги очікування в пулі, head-of-line blocking, контеншен за коннекти і шторм ретраїв.

2) База математики: як рахувати розмір пулу

Використовуємо закон Літтла: `L = λ × W`. Для пулу це означає:
  • «λ» - середній потік запитів (RPS).
  • «W» - середня зайнятість з'єднання на запит (service time, включаючи мережеву латентність і роботу віддаленого сервісу).
  • Мінімальний розмір пулу: `N_min ≈ λ × W`.
  • Додайте запас під варіації і p99: headroom 20–50%.
  • Приклад: 300 RPS, середній hold-time 40 ms →'N _ min = 300 × 0. 04 = 12`. Із запасом 50% → 18 конектів.

Якщо хвости великі: враховуйте'W _ p95'або'W _ p99'для критичних шляхів - пули ростуть.

3) Загальні принципи проектування

1. Короткий шлях даних: reuse (keep-alive, HTTP/2/3 мультиплексування).
2. Обмеження паралелізму: краще відмовити швидко (429/503) ніж засмажити бекенд.
3. Таймаути> ретраї: виставляйте малі таймаути і рідкісні ретраї з джиттером.
4. Черги у клієнта коротші, ніж у сервера (швидкий fail-fast).
5. Backpressure: коли пул заповнений - негайно NACK/помилка/колбек «пізніше».
6. Ізоляція пулів по цілях: DB, кеш, зовнішні PSP - свої ліміти.

4) HTTP/1. 1 vs HTTP/2/3, keep-alive

HTTP/1. 1: один запит на конект одночасно (практично); потрібен пул з кількома конектами на хост.
HTTP/2: мультиплексування потоків в одному TCP; менше конектів, але можливий HOL-blocking на TCP при втраті пакетів.
HTTP/3 (QUIC): потокова незалежність поверх UDP - менше HOL-проблем, швидше перші байти.

Налаштування, які допомагають:
  • keep-alive timeout 30-90s (за профілем), ліміт запитів на конект (graceful recycle).
  • Передпрогрів (preconnect) при старті воркера.
  • Обмеження макс. потоків на HTTP/2 (наприклад, 100-200).
NGINX (upstream keepalive):
nginx upstream backend {
server app-1:8080;
server app-2:8080;
keepalive 512;
keepalive_requests 1000;
keepalive_timeout 60s;
}
proxy_http_version 1. 1;
proxy_set_header Connection "";
Envoy (HTTP/2 pool):
yaml http2_protocol_options:
max_concurrent_streams: 200 common_http_protocol_options:
idle_timeout: 60s max_connection_duration: 3600s

5) Пули БД: PgBouncer, HikariCP, драйвери

Мета - обмежити конкурентні транзакції і тримати короткі утримання конекту.

5. 1 PgBouncer (PostgreSQL)

Режими: `session` / `transaction` / `statement`. Для API - частіше transaction.
Важливі параметри: `pool_size`, `min_pool_size`, `reserve_pool_size`, `server_idle_timeout`, `query_wait_timeout`.

ini
[databases]
appdb = host=pg-primary port=5432 dbname=appdb

[pgbouncer]
pool_mode = transaction max_client_conn = 5000 default_pool_size = 100 min_pool_size = 20 reserve_pool_size = 20 query_wait_timeout = 500ms server_idle_timeout = 60 server_reset_query = DISCARD ALL

5. 2 HikariCP (Java)

Малі, швидкі коннекти, жорсткі таймаути.

properties dataSourceClassName=org. postgresql. ds. PGSimpleDataSource maximumPoolSize=30 minimumIdle=5 connectionTimeout=250 validationTimeout=200 idleTimeout=30000 maxLifetime=1800000 leakDetectionThreshold=5000
Правила:
  • `maximumPoolSize ≈ RPS × W × headroom`.
  • 'connectionTimeout'сотні мілісекунд, не секунди.
  • Увімкніть leak detection.

5. 3 Go/Node/Python - приклади

Go http. Client (reuse + timeouts):
go tr:= &http. Transport{
MaxIdleConns:    512,
MaxIdleConnsPerHost: 128,
IdleConnTimeout:   60 time. Second,
TLSHandshakeTimeout: 2 time. Second,
}
c:= &http. Client{
Transport: tr,
Timeout:  2 time. Second ,//general
}
Node. js keep-alive агент:
js const http = require('http');
const agent = new http. Agent({ keepAlive: true, maxSockets: 200, maxFreeSockets: 64, timeout: 60000 });
psycopg / SQLAlchemy (Python):
python engine = create_engine(
url, pool_size=30, max_overflow=10, pool_recycle=1800, pool_pre_ping=True, pool_timeout=0. 25
)

6) Черги очікування і tail-latency

Хвости виникають, коли:
  • Пул менше, ніж'λ × W'→ зростає черга очікування конекту.
  • Нерівність навантаження (bursts) без буфера і лімітів.
  • Довгі запити займають конект і створюють HOL.
Контрзаходи:
  • Розділяйте пули за типами запитів (швидкі/повільні).
  • Впроваджуйте таймаут очікування конекту (client-side). Якщо закінчився - швидкий NACK.
  • Outlier detection і circuit-breaking на маршрутах (Envoy, HAProxy).
  • Квоти на «важкі» маршрути, окремий пул для звітів/експортів.
Envoy circuit breaker (приклад):
yaml circuit_breakers:
thresholds:
- priority: DEFAULT max_connections: 200 max_pending_requests: 100 max_requests: 1000 max_retries: 2

7) Таймаути і ретраї (правильний порядок)

1. Connect timeout (короткий: 50-250 ms всередині DC).
2. TLS handshake timeout (500–1000 ms вне DC).
3. Request/Read timeout (ближче до SLO маршруту).
4. Retry: максимум 1 раз, тільки для ідемпотентних методів; джиттер + backoff.
5. Budget на ретраї: глобальний ліміт у відсотках від RPS (наприклад, ≤ 10%).

8) Keep-alive, Nagle, протоколи

Вимкніть Nagle (TCP_NODELAY) для RPC з малими повідомленнями.
Вмикайте HTTP keep-alive скрізь, де можливо.
Слідкуйте за TIME_WAIT - tune'reuse '/' recycle'тільки якщо розумієте наслідки; краще - reuse конектів, а не тюнінг ядра.
TLS: використовуйте session resumption і ALPN.

9) OS/Kernel тюнінг (з обережністю)

`net. core. somaxconn`, `net. ipv4. ip_local_port_range`, `net. ipv4. tcp_fin_timeout`.
Дескриптори: 'nofile'≥ 64k на процес-проксі.
Баланс IRQ, GRO/LRO - за профілем трафіку.
Пріоритет - профілювати; тюнінг без метрик часто шкодить.

10) Спостережуваність: Що міряти

Pool utilization: зайнято/всього, p50/p95 очікування конекту.
In-flight запити і їх hold-time (зрізи за маршрутами).
Error budget ретраїв: частка повторів.
Connection churn: створення/закриття в секунду.
TCP/TLS: SYN RTT, handshakes, session reuse.
Для БД: active connections, waiting, long transactions, locks.

Графіки: «RPS vs pool wait», «hold-time distribution», «reuse ratio», «circuit trips».

11) Кейс-рецепти

11. 1 API-шлюз → backend

HTTP/2 до бекендів,'max _ concurrent _ streams = 200'.
Пул 20-40 конектів на сервіс на вузол шлюзу.
Таймаути: connect 100ms, per-try 300-500ms, загальний 1-2s, 1 retry з джиттером.

11. 2 Сервіс → PostgreSQL через PgBouncer

'pool _ mode = transaction','default _ pool _ size'за формулою (RPS × W × 1. 3).
У додатку «connectionTimeout≤250ms», короткі транзакції (<100ms).
Важкі звітні запити - окремий пул/репліка.

11. 3 gRPC внутрішній

Один канал (HTTP/2) на цільовий хост з лімітом потоків 100-200.
Deadline на RPC по SLO маршруту, ретраї тільки idempotent.
Семплінг трейсів для довгих RPC і метрики hold-time.

12) Чек-лист впровадження (0-30 днів)

0-7 днів

Заміряйте'W'( hold-time) на ключових маршрутах/клієнтах.
Розрахуйте'N _ min = λ × W'і додайте 30-50% headroom.
Увімкніть keep-alive і короткі таймаути очікування конекту.

8-20 днів

Розділіть пули (швидкі/повільні/зовнішні).
Введіть circuit-breakers і budgets ретраїв.
Додайте дашборди: pool wait p95, reuse ratio, in-flight.

21-30 днів

Прогони навантаженням з бурстами, хаос-тест «падіння бекенду».
Оптимізація по хвостах: ізоляція важких маршрутів, локальні кеші.
Документуйте формули і ліміти в runbook'ax.

13) Анти-патерни

Розмір пулу «навмання» і відсутність headroom.
Великі таймаути очікування конекту → довгі хвости замість швидких відмов.
Багато ретраїв без джиттера і ідемпотентності → шторм.
Один загальний пул на всі типи запитів.
Довгі транзакції тримають конект (DB) → starvation інших.
Відключений keep-alive або занадто маленькі ліміти idle → churn і зростання TTFB.

14) Метрики зрілості

Pool wait p95 в проді <10% від загального p95 маршруту.
Reuse ratio (> 90% для внутрішніх HTTP;> 80% для зовнішніх).
DB txn time p95 < 100–200 ms; частка довгих транзакцій <1%.
Retry rate <5% (і ≤ budget), помилки через timeouts стабільні і передбачувані.
Документований розрахунок пулу для всіх критичних клієнтів.

15) Висновок

Ефективний connection pooling - це інженерія черг + дисципліна таймаутів. Виміряйте'W', розрахуйте пул'λ × W'з запасом, увімкніть keep-alive/HTTP2 +, відокремте повільні шляхи, тримайте короткі таймаути і мінімальні ретраї з джиттером. Додайте спостережуваність «pool wait vs latency» і circuit-breakers - і ви отримаєте низький TTFB, контрольований хвіст p99 і стійкість до сплесків без перегріву бекендів.

Contact

Зв’яжіться з нами

Звертайтеся з будь-яких питань або за підтримкою.Ми завжди готові допомогти!

Telegram
@Gamble_GC
Розпочати інтеграцію

Email — обов’язковий. Telegram або WhatsApp — за бажанням.

Ваше ім’я необов’язково
Email необов’язково
Тема необов’язково
Повідомлення необов’язково
Telegram необов’язково
@
Якщо ви вкажете Telegram — ми відповімо й там, додатково до Email.
WhatsApp необов’язково
Формат: +код країни та номер (наприклад, +380XXXXXXXXX).

Натискаючи кнопку, ви погоджуєтесь на обробку даних.