1. 封裝程式碼
package rabbitmq
import (
"fmt"
"log"
"strconv"
"strings"
"yoyo/pkg/config"
"github.com/streadway/amqp"
)
type Message struct {
DelayTime int
Body string
}
type MessageQueue struct {
conn *amqp.Connection
ch *amqp.Channel
ExchangeName string
RouteKey string
QueueName string
}
type Consumer func(amqp.Delivery)
func NewRabbitMQ(exchange, route, queue string) MessageQueue {
var messageQueue = MessageQueue{
ExchangeName: exchange,
RouteKey: route,
QueueName: queue,
}
conn, err := amqp.Dial(fmt.Sprintf(
"amqp://%s:%s@%s:%s%s",
config.Viper.GetString("rabbitmq.username"),
config.Viper.GetString("rabbitmq.password"),
config.Viper.GetString("rabbitmq.host"),
config.Viper.GetString("rabbitmq.port"),
"/"+strings.TrimPrefix(config.Viper.GetString("rabbitmq.vhost"), "/"),
))
failOnError(err, "Failed to connect to RabbitMQ")
messageQueue.conn = conn
ch, err := conn.Channel()
failOnError(err, "Failed to open a channel")
messageQueue.ch = ch
messageQueue.declareExchange(exchange, nil)
return messageQueue
}
func (mq *MessageQueue) SendMessage(message Message) {
err := mq.ch.Publish(
mq.ExchangeName,
mq.RouteKey,
false,
false,
amqp.Publishing{
ContentType: "text/plain",
Body: []byte(message.Body),
},
)
failOnError(err, "send common msg err")
}
func (mq *MessageQueue) SendDelayMessage(message Message) {
delayQueueName := mq.QueueName + "_delay:" + strconv.Itoa(message.DelayTime)
delayRouteKey := mq.RouteKey + "_delay:" + strconv.Itoa(message.DelayTime)
dq := mq.declareQueue(
delayQueueName,
amqp.Table{
"x-dead-letter-exchange": mq.ExchangeName,
"x-dead-letter-routing-key": mq.RouteKey,
},
)
mq.bindQueue(dq.Name, delayRouteKey, mq.ExchangeName)
err := mq.ch.Publish(
mq.ExchangeName,
delayRouteKey,
false,
false,
amqp.Publishing{
ContentType: "text/plain",
Body: []byte(message.Body),
Expiration: strconv.Itoa(message.DelayTime * 1000),
},
)
failOnError(err, "send delay msg err")
}
func (mq *MessageQueue) Consume(fn Consumer) {
q := mq.declareQueue(mq.QueueName, nil)
mq.bindQueue(q.Name, mq.RouteKey, mq.ExchangeName)
err := mq.ch.Qos(1, 0, false)
failOnError(err, "Failed to set QoS")
msgs, err := mq.ch.Consume(
q.Name,
"",
false,
false,
false,
false,
nil,
)
failOnError(err, "Failed to register a consumer")
go func() {
for d := range msgs {
fn(d)
d.Ack(false)
}
}()
log.Printf(" [*] Waiting for logs. To exit press CTRL+C")
}
func (mq *MessageQueue) Close() {
mq.ch.Close()
mq.conn.Close()
}
func (mq *MessageQueue) declareQueue(name string, args amqp.Table) amqp.Queue {
q, err := mq.ch.QueueDeclare(
name,
true,
false,
false,
false,
args,
)
failOnError(err, "Failed to declare a delay_queue")
return q
}
func (mq *MessageQueue) declareExchange(exchange string, args amqp.Table) {
err := mq.ch.ExchangeDeclare(
exchange,
"direct",
true,
false,
false,
false,
args,
)
failOnError(err, "Failed to declare an exchange")
}
func (mq *MessageQueue) bindQueue(queue, routekey, exchange string) {
err := mq.ch.QueueBind(
queue,
routekey,
exchange,
false,
nil,
)
failOnError(err, "Failed to bind a queue")
}
func failOnError(err error, msg string) {
if err != nil {
log.Fatalf("%s : %s", msg, err)
}
}
2. 消費訊息
func registerRabbitMQConsumer() {
rabbit := rabbitmq.NewRabbitMQ("yoyo_exchange", "yoyo_route", "yoyo_queue")
rabbit.Consume(func(d amqp.Delivery) {
})
}
3. 傳送訊息
rabbit := rabbitmq.NewRabbitMQ("yoyo_exchange", "yoyo_route", "yoyo_queue")
defer rabbit.Close()
rabbit.SendMessage(rabbitmq.Message{Body: "這是一條普通訊息"})
rabbit.SendDelayMessage(rabbitmq.Message{Body: "這是一條延時5秒的訊息", DelayTime: 5})
本作品採用《CC 協議》,轉載必須註明作者和本文連結