发布与订阅模式
生产者的消息会被所有的消费者获取
发布订阅模式下创建RabbitMq实例
发布订阅模式queueName必须为空,要传入交换机exChangeName的名称,routingkey为空
func NewRabbitMqPubSub(exchangeName string) *RabbitMq {
//创建mq实例
rabbitmq := NewRabbitMq("", exchangeName, "")
return rabbitmq
}
发布订阅模式下生产者
1、生产者首先必须尝试创建交换机,(尝试创建表示如果交换机存在就直接使用,自己理解),ExchangeDeclare的第二个参数kind必须为fanout
2、推送消息使用的是channel.Pubish发送消息,队列名称必须为空,传入交换机Exchange名称
func (r *RabbitMq) PublishPub(message string) {
//尝试创建交换机
err := r.channel.ExchangeDeclare(
r.Exchange,
//是在127.0.0.1:15672后台的exchange中看到
"fanout",
//是否持久化
false,
//
false,
//如果internal设置为true,表示exchage不可以被client用来推送消息,仅用来进行exchange和exchage之间的绑定
false,
false,
nil)
r.failOnErr(err, "failed to declare an exchange")
//2. 发送消息
r.channel.Publish(
//交换机
r.Exchange,
"",
//mandatory如果为true会根据exchange类型和routekey规则,
//如果无法找到符合条件的队列就把消息返还给发送者
false,
//immediate如果为true,当exchage发送消息到队列后,
//如果发现队列上没有绑定消费者就把消息返还给发送者
false,
//发送的信息
amqp.Publishing{
ContentType: "text/plain",
Body: []byte(message),
})
}
发布订阅模式下的消费者
1、消费者尝试创建交换机channel.ExchangeDeclare也是使用fanout模式
2、尝试创建队列channel.QueueDeclare
3、绑定队列到交换机中channel.Queuebind
4、消费channel.Consume消费消息
func (r *RabbitMq) RecivedSub() {
//尝试创建交换机
err := r.channel.ExchangeDeclare(
r.Exchange,
//是在127.0.0.1:15672后台的exchange中看到
"fanout",
//是否持久化
false,
false,
//如果internal设置为true,表示exchage不可以被client用来推送消息,仅用来进行exchange和exchage之间的绑定
false,
false,
nil)
r.failOnErr(err, "failed to declare an exchange")
//2 尝试创建队列
q, err := r.channel.QueueDeclare(
"",
false,
false,
true,
false,
nil)
r.failOnErr(err, "failed to declare an queue")
//3 绑定队列到exchange中
err = r.channel.QueueBind(
q.Name,
//在pub和sub模式下这里的key要为空
"",
r.Exchange,
false,
nil)
//消费消息
msgs, err := r.channel.Consume(
q.Name,
"",
true,
false,
false,
false,
nil)
if err != nil {
fmt.Printf("channel.Consume failed, error:%+v\n", err)
return
}
forever := make(chan bool)
go func() {
for d := range msgs {
//实现我们要处理的逻辑函数
log.Printf("Received a message:%s", d.Body)
}
}()
log.Printf("[*] Waiting for message, exit to press CTRL + C")
<-forever
}
使用案例
生产者
package main
import (
"rabbitmq/RabbitMq"
"strconv"
"time"
)
func main(){
rabbitmq := RabbitMq.NewRabbitMqPubSub("newProduct")
for i:=0;i<100;i++ {
rabbitmq.PublishPub("订阅发布模式生产消息 imooc" + strconv.Itoa(i))
time.Sleep( 10 * time.Millisecond)
}
}
消费者
package main
import "rabbitmq/RabbitMq"
func main(){
rabbitmq := RabbitMq.NewRabbitMqPubSub("newProduct")
rabbitmq.RecivedSub()
}
===================================================
package main
import "rabbitmq/RabbitMq"
func main(){
rabbitmq := RabbitMq.NewRabbitMqPubSub("newProduct")
rabbitmq.RecivedSub()
}
分析:
发布订阅模式下:生产者生产的消息会被所有的消费者获取到
输出结果
消费者1输出结果
2019/07/04 11:35:16 [*] Waiting for message, exit to press CTRL + C
2019/07/04 11:35:20 Received a message:订阅发布模式生产消息 imooc0
2019/07/04 11:35:20 Received a message:订阅发布模式生产消息 imooc1
2019/07/04 11:35:20 Received a message:订阅发布模式生产消息 imooc2
2019/07/04 11:35:20 Received a message:订阅发布模式生产消息 imooc3
2019/07/04 11:35:20 Received a message:订阅发布模式生产消息 imooc4
2019/07/04 11:35:20 Received a message:订阅发布模式生产消息 imooc5
2019/07/04 11:35:20 Received a message:订阅发布模式生产消息 imooc6
2019/07/04 11:35:20 Received a message:订阅发布模式生产消息 imooc7
2019/07/04 11:35:20 Received a message:订阅发布模式生产消息 imooc8
2019/07/04 11:35:20 Received a message:订阅发布模式生产消息 imooc9消费者2输出结果
2019/07/04 11:35:16 [*] Waiting for message, exit to press CTRL + C
2019/07/04 11:35:20 Received a message:订阅发布模式生产消息 imooc0
2019/07/04 11:35:20 Received a message:订阅发布模式生产消息 imooc1
2019/07/04 11:35:20 Received a message:订阅发布模式生产消息 imooc2
2019/07/04 11:35:20 Received a message:订阅发布模式生产消息 imooc3
2019/07/04 11:35:20 Received a message:订阅发布模式生产消息 imooc4
2019/07/04 11:35:20 Received a message:订阅发布模式生产消息 imooc5
2019/07/04 11:35:20 Received a message:订阅发布模式生产消息 imooc6
2019/07/04 11:35:20 Received a message:订阅发布模式生产消息 imooc7
2019/07/04 11:35:20 Received a message:订阅发布模式生产消息 imooc8
2019/07/04 11:35:20 Received a message:订阅发布模式生产消息 imooc9