1.配置qq郵箱的賬号、密碼;配置rabbitmq的ip、使用者名、密碼
qq郵箱配置
rabbitmq配置
2.聲明隊列、交換機、讓隊列綁定交換機,并且攜帶路由key(用的是路由模式)
設定消息和交換機持久性,是為了防止消息丢失
隊列交換機綁定
3.為了保證生産者不丢失消息,需要讓生産者确認消息
消息有一個唯一的消息id,mq收到消息後,會傳回一個結果給發送者,表示消息處理成功
傳回的結果有兩種方式
a.發送者确認:消息沒有投遞到交換機,則傳回ack,反之則傳回nack
b.發送者回執:消息到交換機了,但是沒有路由到隊列,則傳回ack,以及路由失敗的原因。
發送者确認和發送者回執
消息投遞成功後,調用updateMailSendLogStatus方法,修改消息資料庫消息表中等于msgId的記錄的狀态字段(status等于1代表消息發送成功)
調用發送者确認和發送者回執方法
消息表
4.錄入使用者資訊後,生成唯一的msgId,并且将消息發送給消費者
消息發送代碼
5.消費者接收消息,開啟手動确認模式,傳回消息給生産者
使用redis,查詢redis緩存是否存在msgId,如果存在直接将該消息标記為已消費(先判斷redis是否存在msgId是為了避免消息重複消費,保證了接口的幂等性。channel.basicAck(tag, false):标記該消息已經成功消費了),否則,發送郵件(發送郵件即消費消息)
使用redis,避免消息重複消費
6.redis不存在msgId,則消費該消息
如果redis不存在msgId,說明消息沒有被消費過,則可以消費消息。發送完郵件後,将msgId存入到redis中,下次同樣的消息來後,就不會被消費。
消費消息
7.消費失敗重試機制
使用Quartz定時任務架構,定時掃描資料庫消息表中,狀态等于0的記錄(狀态等于0代表消息投遞中,消息者還沒有消費到消息),對這些記錄進行周遊,并判斷記錄中重試次數:count是否大于3,小于等于3,則再次對消息發送;反之,重試次數大于3,則将資料庫這條記錄的狀态直接設定為:消息投遞失敗。
消費失敗重試
總結:
消息可靠性保證:
1.發送者确認和發送者回執
2.消息和隊列持久化
3.消費者失敗重置