簡單模式
生產者的消息被負載均衡到各個消費者去,一條消息只會被一個消費者消費,不會產生一條消息重複消費的問題
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