Từ Hangfire đến RabbitMQ: Loại bỏ việc Polling Cơ sở dữ liệu

Hangfire rất tuyệt vời cho các nhóm nhỏ. Bạn chỉ cần thêm một gói NuGet và trỏ nó đến cơ sở dữ liệu của mình. Bạn sẽ có ngay một trình chạy tác vụ (job runner) và một dashboard hoàn toàn miễn phí. Đối với một dịch vụ duy nhất, thật khó để tìm được giải pháp nào tốt hơn.

Tôi đã sử dụng Hangfire cho SavePosty để xử lý email, webhooks và lấy nội dung. Mọi tác vụ đều hoạt động theo cùng một cách. Tất cả đều thực hiện polling cơ sở dữ liệu Postgres của tôi sau mỗi vài giây để kiểm tra xem có công việc mới hay không.

Cuối cùng, tôi đã chuyển mọi thứ sang RabbitMQ. Dưới đây là lý do tại sao tôi làm vậy và những gì tôi đã mất đi.

Tại sao tôi chuyển đổi:

  • Tải polling tăng theo thời gian, không phải theo khối lượng công việc. Mỗi tác vụ Hangfire sẽ truy cập vào cơ sở dữ liệu của bạn theo một chu kỳ thời gian nhất định. Ngay cả khi không có công việc nào, cơ sở dữ liệu vẫn phải hoạt động liên tục. Chi phí này sẽ tăng dần theo số lượng tác vụ và tần suất polling.
  • Quá nhiều mô hình. Một phần ứng dụng của tôi đã sử dụng RabbitMQ, trong khi phần còn lại sử dụng Hangfire. Điều này đồng nghĩa với việc có hai cách khác nhau để quản lý các tác vụ chạy ngầm. Việc chuyển sang RabbitMQ đã giúp thống nhất mọi thứ.
  • Độ trễ. Một broker sẽ đẩy công việc ngay khi nó vừa đến. Hangfire phải đợi đến lần polling tiếp theo.

Sự đánh đổi:

Hangfire rất dễ thiết lập. Nó sử dụng các bảng SQL hiện có của bạn và có sẵn một dashboard rất tuyệt vời.

RabbitMQ yêu cầu việc quản lý một broker. Nó sử dụng RAM và băng thông mạng thay vì CPU của cơ sở dữ liệu. Bạn sẽ có khả năng mở rộng tốt hơn, nhưng chi phí vận hành (operational overhead) cũng cao hơn.

Cách tôi di chuyển một cách an toàn:

Tôi giữ nguyên logic nghiệp vụ (business logic) của mình. Tôi xây dựng các consumer mỏng (thin consumers) đóng vai trò như một "cửa trước". Consumer này sẽ nhận tin nhắn và chuyển nó cho lớp tác vụ (job class) hiện có.

Tôi tập trung vào hai điều:

  • Sự tương đồng về cơ chế thử lại (Retry parity). Tôi đã thiết lập các cài đặt retry của Hangfire trong RabbitMQ consumer để không làm mất tin nhắn.
  • An toàn về schema. Tôi giữ cho các cột cũ ở trạng thái nullable để không làm hỏng cơ sở dữ liệu trong quá trình triển khai (deploy).

Những gì tôi đã mất:

Nhược điểm lớn nhất là khả năng hiển thị (visibility). Hangfire cho phép bạn nhấp vào một tác vụ thất bại và xem chính xác chuyện gì đã xảy ra. RabbitMQ cho bạn biết có bao nhiêu tin nhắn trong Dead Letter Queue, nhưng nó không cung cấp chế độ xem chi tiết từng tác vụ dễ dàng như vậy. Giờ đây, tôi dựa vào các structured logs thay vì một dashboard.

Lời khuyên của tôi:

Hãy tiếp tục dùng Hangfire nếu:

  • Bạn chỉ chạy một dịch vụ duy nhất.
  • Bạn có một đội ngũ nhỏ.
  • Bạn cần một dashboard dễ dàng để gỡ lỗi (debugging).

Hãy chuyển sang RabbitMQ nếu:

  • Bạn có nhiều dịch vụ.
  • Tải cơ sở dữ liệu từ việc polling của bạn đang ở mức cao.
  • Bạn muốn sử dụng các mô hình pub/sub.

Quyết định phụ thuộc vào hệ thống của bạn, chứ không phải dựa trên một tác vụ đơn lẻ.

Source: https://dev.to/gabrielleroux/from-hangfire-to-rabbitmq-killing-database-polling-in-a-net-app-4og4

Optional learning community: https://t.me/GyaanSetuAi