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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章