【RabbitMQ(一)】docker-compose安装rabbitmq及简单使用Hello World

简介

官网

RabbitMQ是一个消息代理:它接受并转发消息。你可以把它想象成一个邮局:当你把你想要邮寄的邮件放进一个邮箱时,你可以确定邮差先生或女士最终会把邮件送到你的收件人那里。在这个比喻中,RabbitMQ是一个邮箱、一个邮局和一个邮递员。

RabbitMQ和邮局的主要区别在于它不处理纸张,而是接受、存储和转发二进制数据块——消息。

RabbitMQ和一般的消息传递都使用一些术语。

  • 生产仅意味着发送。发送消息的程序是生产者
  • 队列是位于RabbitMQ内部的邮箱的名称。尽管消息通过RabbitMQ和你的应用程序流动,但它们只能存储在队列中。队列只受主机内存和磁盘限制的限制,实际上它是一个大的消息缓冲区。许多生产者可以向一个队列发送消息,而许多消费者可以尝试从一个队列接收数据。
  • 消费与接收具有相似的含义。消费者是一个主要等待接收消息的程序:

请注意,生产者,消费者和代理(broker)不必位于同一主机上。实际上,在大多数应用程序中它们不是。一个应用程序既可以是生产者,也可以是消费者。

安装

编写docker-compose.yml

version: '3'
services:
  rabbitmq:
    image: rabbitmq:3.8.3-management
    container_name: rabbitmq
    restart: always
    hostname: rabbitmq_host
    ports:
      - 15672:15672   # web UI 管理接口
      - 5672:5672	# 生产者和消费者连接使用的接口
    volumes:
      - ./log:/var/log/rabbitmq #挂载 RabbitMQ日志
      - ./data:/var/lib/rabbitmq #挂载 RabbitMQ数据
    environment:
      - RABBITMQ_DEFAULT_USER=root
      - RABBITMQ_DEFAULT_PASS=123456

说明

  1. 15672:UI端使用端口
    5672:golang连接rabbitmq使用的接口
    浏览器访问 ip:15672即可,输入用户名,密码登录。

  2. application.yml文件中推荐为docker容器设置hostname,因为rabbitmq默认使用hostname作为存储数据的节点名,设置hostname可以避免生成随机的节点名,方便追踪数据。官网原文如下

One of the important things to note about RabbitMQ is that it stores data based on what it calls the "Node Name", which defaults to the hostname. What this means for usage in Docker is that we should specify -h/--hostname explicitly for each daemon so that we don't get a random hostname and can keep track of our data:
  1. RABBITMQ_DEFAULT_USER 和 RABBITMQ_DEFAULT_PASS
    用来设置超级管理员的账号和密码,如果不设置,默认都是 guest

  2. docker镜像使用像这样 rabbitmq:3.8.3-management 带有后缀 -management的镜像,之前使用没带这个后缀的镜像,网页访问失败

Hello World使用

首先,使用go get安装amqp

go get github.com/streadway/amqp

生产者

producer.go

package main

import (
	"log"

	"github.com/streadway/amqp"
)

func main() {
    
    
	// 1. 尝试连接RabbitMQ,建立连接
	// 该连接抽象了套接字连接,并为我们处理协议版本协商和认证等。
	conn, err := amqp.Dial("amqp://root:[email protected]:5672/")
	if err != nil {
    
    
		log.Fatalf("%s", "Failed to connect to RabbitMQ", err)
		return
	}
	defer conn.Close()
	// 2. 接下来,我们创建一个通道,大多数API都是用过该通道操作的。
	ch, err := conn.Channel()
	if err != nil {
    
    
		log.Fatalf("%s", "Failed to open a channel", err)
		return
	}
	defer ch.Close()
	// 3. 声明消息要发送到的队列
	q, err := ch.QueueDeclare(
		"hello", // name
		false,   // durable
		false,   // delete when unused
		false,   // exclusive
		false,   // no-wait
		nil,     // arguments
	)
	if err != nil {
    
    
		log.Fatalf("%s", "Failed to declare a queue", err)
		return
	}
	body := "Hello World!"
	// 4.将消息发布到声明的队列
	err = ch.Publish(
		"",     // exchange
		q.Name, // routing key
		false,  // mandatory
		false,  // immediate
		amqp.Publishing{
    
    
			ContentType: "text/plain",
			Body:        []byte(body),
		})
	if err != nil {
    
    
		log.Fatalf("%s", "Failed to publish a message", err)
		return
	}
	log.Printf(" [x] Sent %s", body)
}

消费者

consumer.go

package main

import (
	"log"

	"github.com/streadway/amqp"
)

func main() {
    
    
	// 建立连接
	conn, err := amqp.Dial("amqp://root:[email protected]:5672/")
	if err != nil {
    
    
		log.Fatalf("%s", "Failed to connect to RabbitMQ", err)
		return
	}
	defer conn.Close()

	// 获取channel
	ch, err := conn.Channel()
	if err != nil {
    
    
		log.Fatalf("%s", "Failed to open a channel", err)
		return
	}
	defer ch.Close()

	// 声明队列
	//请注意,我们也在这里声明队列。因为我们可能在发布者之前启动使用者,所以我们希望在尝试使用队列中的消息之前确保队列存在。
	q, err := ch.QueueDeclare(
		"hello", // name
		false,   // durable
		false,   // delete when unused
		false,   // exclusive
		false,   // no-wait
		nil,     // arguments
	)
	if err != nil {
    
    
		log.Fatalf("%s", "Failed to declare a queue", err)
		return
	}
	// 获取接收消息的Delivery通道
	msgs, err := ch.Consume(
		q.Name, // queue
		"",     // consumer
		true,   // auto-ack
		false,  // exclusive
		false,  // no-local
		false,  // no-wait
		nil,    // args
	)
	if err != nil {
    
    
		log.Fatalf("%s", "Failed to register a consumer", err)
		return
	}

	go func() {
    
    
		for d := range msgs {
    
    
			log.Printf("Received a message: %s", d.Body)
		}
	}()

	log.Printf(" [*] Waiting for messages. To exit press CTRL+C")
	select {
    
    }
}

参考文档:
Kafka、RabbitMQ、RocketMQ 之间的区别是什么 ?

RabbitMQ Go语言客户端教程
RabbitMQ官网的Go语言客户端系列教程

猜你喜欢

转载自blog.csdn.net/csdniter/article/details/113339633