Avatar
1
Hihi Teacher
Hihi Teacher
Gửi email trong Spring Boot và RabbitMQ
Hi xin chào mọi người!

Hiện tại em đang tìm hiểu về RabbitMQ sẵn tiện làm thử ứng dụng phổ biến nhất là gửi email dùng Spring + RabbitMQ.

Em đang bật chế độ manual cho ack khi nhận tin nhắn từ RabbitMQ ở RabbitListener

Luồng xử lý của em cơ bản là như thế này:

  • Khi gửi mail thành công sẽ gọi câu lệnh basic.Ack để thông báo là nhận thành công và RMQ sẽ xóa tin nhắn đó khỏi Queue.
  • Khi gửi thất bại (nhảy vào catch) thì sẽ gọi câu lệnh basic.Nack để gửi tin nhắn trở lại Queue.

Nhưng vấn đề em gặp phải là nếu gọi câu lệnh basic.Nack  thì sẽ bị 1 vòng lặp vô tận => tin nhắn khi requeue xong lại nhận xong lại requeue vô tận.

Mọi người cho em hỏi là trong trường hợp của em thì nên xử lý như thế nào là ổn nhất với tin nhắn đang bị lỗi đó ạ (Tại vì nếu loop vô tận như v thì sẽ ko ổn tí nào).Có nên lưu tin nhắn ở đâu đó xong 1 khoảng thời gian sau resend 1 số lần nhất định thì có được không ạ?

Cảm ơn mọi người!

  • Answer
spring rabbitmq
Remain: 5
1 Answer
Avatar
tvd12 Teacher
tvd12 Teacher
Thật tệ là ack và MQ không hay như những gì chúng ta tưởng, cụ thể là trong trường hợp gửi mail này. Rõ ràng là khi 1 mail bị gửi lỗi thì nó có thể bị lỗi vĩnh viễn và tạo ra 1 vòng lặp vô hạn nếu cố nhét mail trở lại queue.

Cách giải quyết ở đây là hãy lưu mail vào 1 bảng trong database có cấu trúc kiểu thế này: Mail(id, title, content, sendErrorCount, status, sendAt), và em có thể tạo ra 1 vòng lặp kiểu thế này:

int maxSleepTime = 100;
int maxSendErrorTimes = 3;
long nextMailId = 0;
while(true) {
  long startTime = System.currentTimeMillis();
  get list mail có status = UNSENT and sendErrorCount  nextMailId
  nếu list mail rỗng thì:
    Thread.sleep(maxSleepTime)
    nextMailId = 0; // xoay vòng xử lý
  nếu có mail:
    nextMailId = mailList.last.id
    send mail
    nếu send thành công thì cập nhật trạng thái status = SENT
    nếu send lỗi thì tăng sendErrorCount lên 1 đơn vị và save mail
}

Như vậy thì em vẫn có thể xử lý toàn bộ số mail và sẽ chặn được việc loop vô hạn thông qua maxSendErrorTimes.

  • 0
  • Reply
Ví dụ em có 1 con service gửi Mail trong 1 hệ thống microservices.Theo em hiểu thì cái anh trả lời ở trên có phải là thêm vào mail service 1 con scheduler để chạy 1 khoảng thời gian nhất định theo định kỳ lấy những record unsent đi gửi lại phải ko ạ ?  –  Hihi 1656594196000
Đúng rồi em ạ.  –  monkey 1656612779000
Anh ơi tại sao code ở trên anh lại cho Thread.Sleep vậy anh?

Làm như v có tác dụng là gì v ạ ?

 –  Hihi 1656629169000
Để cho CPU không bị lên 100% em ạ, giả sử không có mail nào cần gửi thì cpu cứ thực hiện vòng lặp cũng không để làm gì.  –  monkey 1656629276000
Anh cho em hỏi thêm là nếu theo như anh nói thì cái Thread.sleep nó chỉ áp dụng cho trường hơp ví dụ While(true) ở trên thôi.Còn trên thực tế khi làm email service thì scheduler ko cần dùng Thread.sleep đúng ko ạ ?  –  Hihi 1656629708000
Nếu em đang dùng scheduler rồi thì không cần sleep em ạ, chỉ khi nào dùng while(true) mới cần sleep thôi  –  monkey 1656629775000