Connection pool: 45ms mở kết nối mới vs. 0,2ms mượn lại
Tóm tắt
Mỗi kết nối mới tới database phải qua bắt tay TCP, TLS và xác thực — khoảng 45ms trong video. Connection pool giữ sẵn một nhóm kết nối để mượn lại trong ~0,2ms. Khi lưu lượng vượt số kết nối trong pool, request phải chờ đến lượt.
Mỗi lần ứng dụng mở một kết nối mới tới database, nó phải bắt tay TCP, thương lượng TLS và xác thực — trong video là khoảng 45ms trước khi chạy được một câu truy vấn. Với một truy vấn chỉ mất 2ms, bạn trả phí kết nối gấp hơn 20 lần thời gian làm việc thật. Connection pool giữ sẵn một nhóm kết nối để mượn lại trong khoảng 0,2ms. Khi lưu lượng vượt số kết nối trong pool, request phải chờ đến lượt.
Ba tình huống
| Tình huống | Thời gian lấy kết nối | Ghi chú |
|---|---|---|
| Không có pool | ~45ms mỗi request | TCP → TLS → AUTH lặp lại mỗi lần |
| Có pool, tải nhẹ | ~0,2ms | Mượn lại kết nối có sẵn, không bắt tay lại |
| Burst 14 request, pool 4 kết nối | 10ms, 20ms, 30ms… | 10 request xếp hàng chờ kết nối rảnh |
Hết burst, các kết nối rảnh bị đóng theo idle timeout.
Các tham số quan trọng
| Tham số | Ý nghĩa |
|---|---|
| Kích thước tối đa | Số kết nối đồng thời tối đa tới database |
| Kích thước tối thiểu | Số kết nối giữ sẵn kể cả khi rảnh |
| Thời gian chờ lấy kết nối | Chờ bao lâu trước khi báo lỗi nếu pool cạn |
| Idle timeout | Sau bao lâu kết nối rảnh bị đóng |
| Max lifetime | Tuổi thọ tối đa của một kết nối để tránh kết nối cũ bị lỗi |
Pool to hơn chưa chắc nhanh hơn
Database có giới hạn số kết nối và tài nguyên (CPU, bộ nhớ, khóa). Quá nhiều kết nối hoạt động cùng lúc khiến chúng tranh chấp nhau và làm tất cả chậm đi. Thường pool nhỏ hơn mà đủ dùng cho kết quả tốt hơn. Cách chọn hợp lý là bắt đầu nhỏ, đo, rồi tăng khi có bằng chứng.
Các lỗi thường gặp
- Rò rỉ kết nối: không trả kết nối về pool sau khi dùng; pool cạn dần và ứng dụng treo.
- Giữ kết nối quá lâu: mở transaction rồi làm việc khác (gọi API ngoài) trước khi commit.
- Kết nối chết: sau khi database restart hoặc timeout phía mạng; cần kiểm tra/validate kết nối khi mượn.
- Mỗi instance một pool: nhiều instance nhân số kết nối và có thể vượt giới hạn database.
Áp dụng thế nào?
- Luôn dùng pool cho ứng dụng có lưu lượng ổn định (HikariCP cho Java, pgBouncer cho PostgreSQL, pool có sẵn trong hầu hết ORM).
- Đo “thời gian chờ lấy kết nối” như một chỉ số riêng — nó tăng là dấu hiệu pool quá nhỏ hoặc query giữ kết nối quá lâu.
- Serverless: mỗi instance có pool riêng dễ làm cạn kết nối DB — dùng proxy như RDS Proxy hoặc pgBouncer.
- Giữ transaction ngắn để kết nối sớm được trả lại.
Nguồn & tham khảo
- About Pool Sizing — HikariCP