RabbitMq简单模式-工作模式

简单模式

生产者的消息被负载均衡到各个消费者去,一条消息只会被一个消费者消费,不会产生一条消息重复消费的问题

rabbitmq的数据源格式 

amqp://user:pass@IP:5672/VirtualHost

 RabbitMq结构体

type RabbitMq struct {
         conn    *amqp.Connection
         channel *amqp.Channel
         //队列名称
         QueueName string
         //交换机
         Exchange string
         //key
         Key   string
         MqUrl string
}

创建RabbitMq实例

错误处理函数failOnErr是在有错误的时候打印后面的参数和错误信息
func NewRabbitMq(queueName, exchange, key string) *RabbitMq {
   rabbitmq := &RabbitMq{
      QueueName: queueName,
      Exchange:  exchange,
      Key:       key,
      MqUrl:     MQURL,
   }
   var err error
   //创建rabbitmq连接
   rabbitmq.conn, err = amqp.Dial(rabbitmq.MqUrl)
   rabbitmq.failOnErr(err, "创建连接错误")
   rabbitmq.channel, err = rabbitmq.conn.Channel()
   rabbitmq.failOnErr(err, "获取channel失败")
   return rabbitmq
}

RabbitMq销毁函数 

func (r *RabbitMq) Destroy() {
   r.channel.Close()
   r.conn.Close()
}

以上是RabbitMq模块的基础模块,其他模式都是在以上基础上做扩展开发的

首先我们看Simple简单模式

简单模式下创建rabbitmq实例,只需要传入队列名称

func NewRabbitMqSimple(queueName string) *RabbitMq {
	return NewRabbitMq(queueName, "", "")
}

简单模式下生产者代码,

使用channel.QueueDeclare申请队列,然后通过channel.Publish中把消息推送到队列中

func (r *RabbitMq) PublishSimple(message string) {
	//1 申请队列,如果队列不存在则申请队列,如果存在则跳过创建,保证队列存在消息能在队列中
	_, err := r.channel.QueueDeclare(
		//队列名称
		r.QueueName,
		//是否持久化
		false,
		//是否自动删除
		false,
		//是否具有排他性(不常用,消息只对自己账号可见)
		false,
		//是否阻塞
		false,
		//额外属性
		nil)
	if err != nil {
		fmt.Printf("queue declare failed, error:%+v\n", err)
		return
	}

	//2发送消息到队列中
	r.channel.Publish(
		//交换机
		"", //简单模式为空
        //routingKey
		r.QueueName,
		//mandatory如果为true会根据exchange类型和routekey规则,
		//如果无法找到符合条件的队列就把消息返还给发送者
		false,
		//immediate如果为true,当exchage发送消息到队列后,
		//如果发现队列上没有绑定消费者就把消息返还给发送者
		false,
		//发送的信息
		amqp.Publishing{
			ContentType: "text/plain",
			Body:        []byte(message),
		})

}

 简单模式下消费者代码

申请channel队列,然后通过channel.Consume获得生产者的消息

func (r *RabbitMq) ConsumeSimple() {
	//1 申请队列,如果队列不存在则申请队列,如果存在则跳过创建,保证队列存在消息能在队列中
	_, err := r.channel.QueueDeclare(
		//队列名称
		r.QueueName,
		//是否持久化
		false,
		//是否自动删除
		false,
		//是否具有排他性(不常用,消息只对自己账号可见)
		false,
		//是否阻塞false是阻塞
		false,
		//额外属性
		nil)
	if err != nil {
		fmt.Printf("queue declare failed, error:%+v\n", err)
		return
	}

	//2接收消息
	msgs, err := r.channel.Consume(
		//队列名称
		r.QueueName,
		//用来区分多个消费者,为空不区分
		"",
		//autoAck是否自动应答,如果把消息消费了,主动告诉rabbitmq服务器
		true,
		//是否具有排他性,只能查看到我自己账号创建的消息,和pulish对应
		false,
		//noLocal如果设置为true,不能将同一个connection发送的消息,传递给同一个connection中的其他消费者
		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 (
	"fmt"
	"rabbitmq/RabbitMq"
)

func main(){
	rabbitmq := RabbitMq.NewRabbitMqSimple("imoocSimple")

	rabbitmq.PublishSimple("hello imooc")
	fmt.Printf("发送成功!\n")
}

消费者

package main

import "rabbitmq/RabbitMq"

func main(){
	rabbitmq := RabbitMq.NewRabbitMqSimple("imoocSimple")

	rabbitmq.ConsumeSimple()
}

生产者把消息("hello imooc")推送到rabbitmq服务器

消费者获取到生产者的消息,并打印

输出结果为:

2019/07/04 11:12:35 [*] Waiting for message, exit to  press CTRL + C
2019/07/04 11:12:46 Received a message:hello imooc

rabbitmq简单模式下的工作模式

上面的案例是一对一的模式,如果要使用一对多、多对多的模式,就是在简单模式下多个生产者多个消费者 

生产者

package main

import (
	"rabbitmq/RabbitMq"
	"strconv"
	"time"
)

func main(){
	rabbitmq := RabbitMq.NewRabbitMqSimple("imoocSimple")
	for i:=0;i<10;i++ {
		rabbitmq.PublishSimple("one hello imooc" + strconv.Itoa(i))
		time.Sleep( 100 * time.Millisecond)
	}
}

======================================
package main

import (
	"rabbitmq/RabbitMq"
	"strconv"
	"time"
)

func main(){
	rabbitmq := RabbitMq.NewRabbitMqSimple("imoocSimple")
	for i:=0;i<10;i++ {
		rabbitmq.PublishSimple("two hello imooc" + strconv.Itoa(i))
		time.Sleep( 100 * time.Millisecond)
	}
}

消费者

package main

import "rabbitmq/RabbitMq"

func main(){
	rabbitmq := RabbitMq.NewRabbitMqSimple("imoocSimple")

	rabbitmq.ConsumeSimple()
}

==========================================
package main

import "rabbitmq/RabbitMq"

func main(){
	rabbitmq := RabbitMq.NewRabbitMqSimple("imoocSimple")

	rabbitmq.ConsumeSimple()
}

分析:

多个生产者往同一个队列中推送消息,消费者平均获取各个生产者消息,每个消息只会被消费一次,不会出现重复模式

消费者1输出结果

2019/07/04 11:19:58 [*] Waiting for message, exit to  press CTRL + C
2019/07/04 11:20:02 Received a message:one hello imooc1
2019/07/04 11:20:02 Received a message:one hello imooc3
2019/07/04 11:20:02 Received a message:one hello imooc5
2019/07/04 11:20:02 Received a message:one hello imooc7
2019/07/04 11:20:03 Received a message:one hello imooc9
2019/07/04 11:20:04 Received a message:two hello imooc1
2019/07/04 11:20:04 Received a message:two hello imooc3
2019/07/04 11:20:04 Received a message:two hello imooc5
2019/07/04 11:20:05 Received a message:two hello imooc7
2019/07/04 11:20:05 Received a message:two hello imooc9

消费者2输出结果

2019/07/04 11:19:55 [*] Waiting for message, exit to  press CTRL + C
2019/07/04 11:20:02 Received a message:one hello imooc0
2019/07/04 11:20:02 Received a message:one hello imooc2
2019/07/04 11:20:02 Received a message:one hello imooc4
2019/07/04 11:20:02 Received a message:one hello imooc6
2019/07/04 11:20:02 Received a message:one hello imooc8
2019/07/04 11:20:04 Received a message:two hello imooc0
2019/07/04 11:20:04 Received a message:two hello imooc2
2019/07/04 11:20:04 Received a message:two hello imooc4
2019/07/04 11:20:05 Received a message:two hello imooc6
2019/07/04 11:20:05 Received a message:two hello imooc8

发布了166 篇原创文章 · 获赞 26 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/qq_28710983/article/details/94600262