RabbitMQ消息队列在Golang中的简单使用

本文介绍了如何在macOS上安装RabbitMQ,包括使用Homebrew安装Erlang和RabbitMQ,以及启用RabbitMQ管理插件。接着,详细阐述了在Go语言中使用streadway/amqp库实现RabbitMQ的Simple、Work、订阅(Pub/Sub)和Routing四种模式,展示了如何创建连接、发布和消费消息。
摘要由CSDN通过智能技术生成
  • AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。
    AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。
  • RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

macOS中安装RabbitMQ:

  1. 安装Erlang环境

brew install erlang

  1. 安装rabbitmq

brew install rabbitmq

  1. 安装RabbitMQ可视化监控工具:

cd /usr/local/Celler/rabbitmq/3.8.11
sudo sbin/rabbitmq-plugins enable rabbitmq_management

  1. 配置环境变量

open ~/.zshrc
// 添加以下两行
export RABBIT_HOME = /usr/local/Celler/3.8.11
export PATH = $PATH:RABBIT_HOME/sbin
source ~/.zshrc

  1. 后台启动rabbitmq

sudo rabbitmq-server -detached

  1. 停止rabbitMQ

rabbitmqctl stop


在golang中尝试RabbitMQ的几种模式:
i: 安装amqp库

go get github.com/streadway/amqp

ii: 定义url

// url格式:amqp://账号:密码@rabbitmq服务地址/vhost
const MQURL = "amqp://chensir:chensir@127.0.0.1:5672/chen"

iii: 定义RabbitMQ对象结构体

type RabbitMQ struct {
	conn *amqp.Connection
	channel *amqp.Channel
	// 队列名称
	QueueName string
	// 交换机
	Exchange string
	// key
	Key string
	// 链接信息
	Mqurl string
}
1. Simple模式

i: 创建RabbitMQ结构体实例

func NewRabbitMQ(queueName string, exchange string, 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.failOnError(err, "创建链接错误")
	rabbitmq.channel, err = rabbitmq.conn.Channel()
	rabbitmq.failOnError(err, "获取channel失败")
	return rabbitmq
}

ii: Simple模式下生产者

func (r *RabbitMQ) PublishSimple(message string){
	// 1. 申请队列,如果队列不存在,自动创建;如果存在则跳过创建,保证消息能发送到队列中
	_, err := r.channel.QueueDeclare(
		r.QueueName,
		//控制是否持久化
		false,
		// 是否自动删除
		false,
		// 是否具有排他性
		false,
		// 是否阻塞
		false,
		// 额外属性
		nil)
	if err != nil {
		fmt.Println(err)
	}
	// 发送消息到队列中
	r.channel.Publish(
		r.Exchange,
		r.QueueName,
		// 如果为true和exchage类型和routKey规则,如果无法找到符合条件的队列,那么会把消息返回给发送者
		false,
		// 如果为true, 当exchange发送消息到队列后发现队列上没有绑定消费者,则会把消息还给发送者
		false,
		amqp.Publishing{
			ContentType: "text/plain",
			Body: []byte(message),
		})
}

iii: Simple模式下消费者

func (r *RabbitMQ) ConsumeSimple(){
	// 尝试申请队列
	_, err := r.channel.QueueDeclare(
		r.QueueName,
		//控制是否持久化
		false,
		// 是否自动删除
		false,
		// 是否具有排他性
		false,
		// 是否阻塞
		false,
		// 额外属性
		nil)
	if err != nil {
		fmt.Println(err)
	}
	// 接收消息
	msgs, err := r.channel.Consume(
		r.QueueName,
		// 用来区分多个消费者的key
		"",
		// 是否自动应到
		true,
		// 是否具有排他性
		false,
		// 如果设置为true,表示不能将同一个connection中发送的消息传递给这个connection中的消费者
		false,
		// 队列消费是否为阻塞
		false,
		nil)
	if err != nil {
		fmt.Println(err)
	}

	// 消费消息
	forever := make(chan bool)
	go func(){
		for d := range msgs {
			log.Printf("Receive a message: %s", d.Body)
		}
	}()
	log.Println("[*] waiting for message, To exit press Ctrl + c")
	<-forever
}
2. Work模式:
  • Work模式的生产消费和Simple模式相同,只是在Simple模式下,可以创建多个消费者对消息队列进行消费。在Work模式下,消息只能被一个消费者消费掉
3. 订阅模式:

i: 订阅模式下创建RabbitMQ实例

func NewRabbitMQPubSub(exchangeName string) *RabbitMQ {
	// 指定交换机名称, 而队列名称则为空即可
	rabbitmq := NewRabbitMQ("", exchangeName, "")
	var err error
	rabbitmq.conn, err = amqp.Dial(rabbitmq.Mqurl)
	rabbitmq.failOnError(err, "failed to connect rabbitmq")
	// 获取channel
	rabbitmq.channel, err = rabbitmq.conn.Channel()
	rabbitmq.failOnError(err, "failed to open a channel")
	return rabbitmq
}

ii: 订阅模式下生产信息

func (r *RabbitMQ) PublishPub(message string){
	// 尝试创建交换机
	err := r.channel.ExchangeDeclare(
		r.Exchange,
		// 交换机类型为广播类型
		"fanout",
		true,
		false,
		false,
		false,
		nil)
	r.failOnError(err, "failed to declare an exchange")
	// 发送消息
	err = r.channel.Publish(
		r.Exchange,
		"",
		false,
		false,
		amqp.Publishing{
			ContentType: "text/plain",
			Body: []byte(message),
		})
	r.failOnError(err, "failed to send a message")
}

iii: 订阅模式下接收消息

func (r *RabbitMQ) ReceiveSub(){
	err := r.channel.ExchangeDeclare(
		r.Exchange,
		"fanout",
		true,
		false,
		// YES表示这个exchange不可以被client用来推送消息,仅用来进行exchange和exchange之间的绑定
		false,
		false,
		nil)
	r.failOnError(err, "failed to declare an exchange")
	// 创建队列
	q, err := r.channel.QueueDeclare(
		"",  // 随机生产队列名称
		false,
		false,
		true,
		false,
		nil)
	// 绑定队列到exchange中
	r.failOnError(err, "failed to declare a queue")
	err = r.channel.QueueBind(
		q.Name,
		// 在Pub/Sub模式下,这里的key要为空
		"",
		r.Exchange,
		false,
		nil)

	// 消费消息
	message, err := r.channel.Consume(
		q.Name,
		"",
		true,
		false,
		false,
		false,
		nil)
	forever := make(chan bool)
	go func(){
		for d := range message {
			log.Printf("Receive a message: %s", d.Body)
		}
	}()
	log.Println("退出请按: Ctrl + c")
	<-forever
}
  • 订阅模式下,是通过交换机将生产的消息广播到绑定到交换机上的多个队列中,需要指定创建的交换机类型为“fanout”类型
4. Routing模式:
  • Routing模式和订阅模式的代码也类似,不同指出在与:
  1. 创建RabbitMQ实例时需要指定RoutingKey
func NewRabbitMQRouting(exchangeName string, routingKey string) *RabbitMQ {
   rabbitmq := NewRabbitMQ("", exchangeName, routingKey)
   var err error
   rabbitmq.conn, err = amqp.Dial(rabbitmq.Mqurl)
   rabbitmq.failOnError(err, "failed to connect rabbitmq")
   // 获取channel
   rabbitmq.channel, err = rabbitmq.conn.Channel()
   rabbitmq.failOnError(err, "failed to open a channel")
   return rabbitmq
}
  1. 在生产消息和消费消息时创建交换机的过程中都需要指定交换机类型为“direct"
  2. 在发送消息时,需要指定消费队列的key, 这个key需要和相应的消费队列一一对应
  • Routing模式就是在订阅模式的基础上,明确指定消息的消费队列。

-------本文结束

Golang 调用 RabbitMQ消息队列监控 API 可以使用标准的 `net/http` 包来发送 HTTP 请求并处理响应。以下是一个简单的示例代码,用于获取 RabbitMQ 的队列信息: ```go package main import ( "encoding/json" "fmt" "io/ioutil" "net/http" ) type QueueInfo struct { Name string `json:"name"` Messages int `json:"messages"` Consumers int `json:"consumers"` } func main() { // RabbitMQ API URL url := "http://localhost:15672/api/queues" // 创建 HTTP 客户端 client := &http.Client{} // 创建 HTTP 请求 req, err := http.NewRequest("GET", url, nil) if err != nil { fmt.Println("创建请求失败:", err) return } // 设置 Basic Auth 认证(如果需要) req.SetBasicAuth("username", "password") // 发送请求并获取响应 resp, err := client.Do(req) if err != nil { fmt.Println("发送请求失败:", err) return } defer resp.Body.Close() // 读取响应内容 body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("读取响应失败:", err) return } // 解析 JSON 响应 var queues []QueueInfo err = json.Unmarshal(body, &queues) if err != nil { fmt.Println("解析响应失败:", err) return } // 输出队列信息 for _, queue := range queues { fmt.Printf("队列名称: %s\n", queue.Name) fmt.Printf("消息数量: %d\n", queue.Messages) fmt.Printf("消费者数量: %d\n", queue.Consumers) fmt.Println("----------------------") } } ``` 请注意,上述代码的 `url` 变量需要根据你的 RabbitMQ 配置进行相应调整。如果 RabbitMQ 设置了用户名和密码的认证,你需要使用 `SetBasicAuth` 方法设置 Basic Auth 认证信息。 该示例代码发送一个 HTTP GET 请求到 RabbitMQ 的 `/api/queues` 接口,获取所有队列的信息,并将其解析为 `QueueInfo` 结构体。然后,你可以根据需要处理和使用这些队列信息。 希望这个示例能帮助到你。如果有任何其他问题,请随时提问。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值