Kafka Fetch and HTTP Polling
❓Trong xây dựng mô hình realtime chatting, dùng Kafka lưu messages với websocket là giao thức truyền event thì có tối ưu hơn việc sử dụng thuần Kafka không.
Trước khi đi sâu vào so sánh, hãy cùng tìm hiểu cách mỗi phương pháp hoạt động. Cụ thể là giữa HTTP Polling và Kafka Consumer Fetch (Optimized Pull).
HTTP Polling (Traditional Pull)
Cách hoạt động:
Client liên tục gửi request hỏi server theo chu kỳ (ví dụ: mỗi 1 giây) dù server có dữ liệu mới hay không.
Server luôn phải trả lời ngay lập tức (có thể trả về
204 No Content
nếu không có dữ liệu).Ưu điểm: Đơn giản, dễ triển khai.
Nhược điểm:
Lãng phí tài nguyên (nhiều request rỗng).
Độ trễ cao (nếu dữ liệu mới xuất hiện ngay sau khi polling, client phải đợi đến chu kỳ tiếp theo).
Kafka Consumer Fetch (Optimized Pull)
Cách hoạt động:
Consumer gửi fetch request đến Kafka broker, nhưng broker có thể không trả lời ngay lập tức.
Broker giữ kết nối mở (long-polling) đến khi:
Có đủ dữ liệu theo cấu hình (ví dụ:
fetch.min.bytes=1
).Hết thời gian chờ (
fetch.max.wait.ms=500
).
Ưu điểm:
Giảm request rỗng: Broker chỉ trả về dữ liệu khi có message mới hoặc hết timeout.
Giảm độ trễ: Nếu message xuất hiện ngay sau fetch request, broker trả về ngay.
Nhược điểm:
Consumer vẫn phải chủ động gửi request (không phải push thực sự).
So sánh số Request rỗng
Giả sử:
Thời gian quan sát: 10 phút = 600 giây
Không có tin nhắn nào trong suốt 10 phút
HTTP Polling (1 giây/lần)
Mỗi giây gửi 1 request → tổng số request:
600s1s/request=600
Kafka Fetch (timeout 1000ms = 1 giây)
Mỗi request chờ tối đa 1000ms (1 giây).
Nếu không có dữ liệu, broker sẽ đóng request sau 1000ms → Consumer phải gửi lại request mới ngay lập tức.
Số request trong 600 giây:
600s1s/request=600
→ Thoạt nhìn, số request là như sau. Tuy nhiên ta cần xem xét cơ chế tối ưu của Kafka.
Kafka Fetch tối ưu hơn nhờ cơ chế "long-polling"
Điểm khác biệt chính:
HTTP Polling:
Mỗi request độc lập, server luôn trả lời ngay (kể cả rỗng).
Tốn tài nguyên cho cả request và response.
Kafka Fetch:
Broker giữ kết nối mở đến khi có dữ liệu hoặc hết timeout (500ms).
Nếu không có dữ liệu, broker chỉ gửi 1 response rỗng sau 500ms.
Consumer không cần gửi request mới liên tục (vì 1 request có thể chờ đến 500ms).
Sự tối ưu của Kafka Fetch:
1 request Kafka sẽ mở kết nối tồn tại trong 1 giây (không phải gửi mới mỗi 1 giây). Do đó nếu message tới trong đoạn thời gian đó thì sẽ được gửi ngay lập tức tới client chứ không cần phải đợi tới chu kì sau như HTTP Polling. Điều này giúp giảm độ trễ message tới client.
Mỗi request trong Kafka tiêu tốn ít tài nguyên hơn so với HTTP Polling, vì không cần thiết lập lại kết nối hay gửi các header lặp lại. Nhờ sử dụng kết nối TCP liên tục, mỗi request cũng nhẹ hơn.
Ngoài
fetch.max.wait.ms
, ta còn có thể thiết lậpfetch.min.bytes
để chỉ định lượng dữ liệu tối thiểu mà consumer muốn nhận trước khi Kafka gửi phản hồi. Điều này giúp giảm số lần request nếu lượng dữ liệu nhỏ, tối ưu hiệu suất truyền tải.
Ví dụ
HTTP Polling (1s):
Tin nhắn đến tại thời điểm
t = 1000.5ms
.Client chỉ nhận được ở request tiếp theo (
t = 2000ms
) → độ trễ 999.5ms.
Kafka Fetch (1s):
Tin nhắn đến tại
t = 1000.5ms
.Request hiện tại đang chờ (timeout tại
t = 2000ms
) → nhận ngay ởt = 1000.5ms
.Độ trễ ≈ 0ms.
→ Kafka giảm độ trễ từ 999.5ms xuống ~0ms trong trường hợp này.
Kết luận
Kafka “không hoàn toàn im lặng” khi không có message, nhưng cơ chế long-polling giúp:
Giảm số lần trả về response rỗng thực tế. Nếu có message trong khoảng thời gian chờ thì sẽ không trả về response rỗng.
Giảm độ trễ khi message mới xuất hiện. Do thiết lập kết nối duy trì trong 1 khoảng thời gian và sẽ đẩy message tới client ngay nếu có.
Tiết kiệm tài nguyên mạng so với HTTP Polling truyền thống nhờ sử dụng kết nối TCP.
Last updated