- 生产者在发送消息的时候如果不设置 mandatory 参数, 那么消息在未被路由的情况下将会丢失: 如果设置了 mandatory 参数,那么需要添加 ReturnListener (监听生产者返回)的编程逻辑,生产者的代码将变得复杂。如果既不想复杂化生产者的编程逻辑,又不想消息丢失,那么可以使用备份交换器, 这样可以将未被路由的消息存储在 RabbitMQ 中,再在需要的时候去处理这些消息。
package product
import (
"fmt"
"github.com/streadway/amqp"
)
func ProducerBackup() {
var(
conn *amqp.Connection
err error
ch *amqp.Channel
queue amqp.Queue
n int
)
if conn, err = amqp.Dial("amqp://liulong:liulong@127.0.0.1:5672/"); err!=nil{
fmt.Println("amqp.Dial err :", err)
return
}
defer conn.Close()
if ch, err = conn.Channel(); err!=nil{
fmt.Println("conn.Channel err: ", err)
return
}
defer ch.Close()
fmt.Println("n", n)
if err = ch.ExchangeDeclare(
"backup_exchange",
amqp.ExchangeFanout,
true,
false,
false,
false,
nil,
); err!=nil{
fmt.Println("ch.ExchangeDeclare err: ", err)
return
}
argsExchange := make(map[string]interface{})
argsExchange["alternate-exchange"] = "backup_exchange"
if err = ch.ExchangeDeclare(
"long_direct",
amqp.ExchangeDirect,
true,
false,
false,
false,
argsExchange,
); err!=nil{
fmt.Println("ch.ExchangeDeclare err: ", err)
return
}
queue, err = ch.QueueDeclare("zhe", true, false, false, false, nil)
if err !=nil{
fmt.Println("ch.QueueDeclare err :", err)
return
}
if err = ch.QueueBind(queue.Name, "zhe_mess", "long_direct", false, nil);err!=nil{
fmt.Println("ch.QueueBind err: ", err)
return
}
if err = ch.Publish(
"long_direct",
"zhe_mess",
false,
false,
amqp.Publishing{
Headers: amqp.Table{},
ContentType:"text/plain",
Body:[]byte("hello world"),
DeliveryMode:amqp.Persistent,
Priority:0,
},
); err!=nil{
fmt.Println("ch.Publish err: ", err)
return
}
}
- 如果设置的备份交换器不存在,则消息丢失
- 如果备份交换器没有绑定任何队列,则消息丢失
- 如果备份交换器没有任何匹配的队列,则消息丢失
- 如果备份交换器和 mandatory 参数一起使用,那么 mandatory 参数无效