Chào mọi người, Hệ thống web của em có chức năng cho phép user nhập URL sản phẩm để xử lý. Quá trình này gồm nhiều bước mất thời gian nên em chia nhỏ thành các bước, viết các Worker riêng và dùng RabbitMQ để push/consume message giữa các bước.
Em đang gặp một bài toán về Load-Balancing và đảm bảo tính công bằng (Fairness): Làm sao để tránh tình trạng User A push 1000 URLs làm nghẽn hệ thống, khiến User B push 1 URL sau đó phải chờ rất lâu mới được xử lý?
Hiện tại, em đang giải quyết bằng cách: Tạo cho mỗi user 1 queue riêng (ví dụ: queue.crawl.user-{userId}). Trong Worker, em lấy danh sách các queue này và BasicConsume tất cả trên cùng một channel.
Tuy nhiên, cách này đang gặp vấn đề:
Em đang gặp một bài toán về Load-Balancing và đảm bảo tính công bằng (Fairness): Làm sao để tránh tình trạng User A push 1000 URLs làm nghẽn hệ thống, khiến User B push 1 URL sau đó phải chờ rất lâu mới được xử lý?
Hiện tại, em đang giải quyết bằng cách: Tạo cho mỗi user 1 queue riêng (ví dụ: queue.crawl.user-{userId}). Trong Worker, em lấy danh sách các queue này và BasicConsume tất cả trên cùng một channel.
Tuy nhiên, cách này đang gặp vấn đề:
- Nếu em cấu hình prefetchCount = 1 (để worker lấy lần lượt mỗi queue 1 message, đảm bảo công bằng) thì throughput (hiệu suất) rất thấp, xử lý chậm do overhead mạng của việc ack/fetch từng message.
- Nếu em tăng prefetchCount cao hơn để tối ưu hiệu suất, thì worker lại gom một loạt message của User A (nếu queue của A đang dài), dẫn đến phá vỡ tính công bằng, User B vẫn bị "đói" (starvation).
- Nếu hệ thống có số lượng user lớn (ví dụ 10.000 users) thì việc maintain 10.000 queues liên tục có vẻ không ổn về mặt resource.
- Cách mỗi user 1 queue như em làm có phải là best practice không ạ?
- Có design pattern, plugin nào của RabbitMQ phù hợp để giải quyết trọn vẹn bài toán: Vừa đảm bảo throughput cao, vừa đảm bảo tính công bằng (Fairness) giữa các user không ạ?