Windows下安装RabbitMQ + Go交互丨学习记录

436 阅读4分钟

零、前言

本文记录了笔者在学习消息队列和RabbitMQ的基础知识的过程,

在RabbitMQ-下,也就是本文中,我们介绍如何在Windows下的Docker中安装RabbitMQ;

并使用Golang测试RabbitMQ。

若笔者有任何疏忽纰漏之处,烦请不吝赐教。

本文会不断的补充、修改和完善,期待您的宝贵意见。


一、环境准备

环境:

  • Windows 10
  • Docker
  • VSCode
  • 勤劳的双手

笔者致力于创作上至老奶奶,下至小狗狗都能看懂的教程!

二、 Docker下安装RabbitMQ

拉取镜像:

在cmd中直接输入以下即可,实测不需要打开管理员权限,也不需要切换目录;

docker search rabbitMq
​
docker pull docker.io/rabbitmq:3.8-management

创建容器:

进入 Docker Desktop 查看镜像ID,当然你也可以docker images

image.png 将其复制并在cmd中输入以下指令来创建rabbitMq容器:

docker run --name rabbitmq -d -p 15672:15672 -p 5672:5672 818bf18535d7

参数说明:

  • --name是容器名称,这里我们使用的是rabbitmq
  • -d是令容器后台运行
  • -p是设置容器内部端口号与主机的映射,web端口默认值为15672,数据通信端口默认值为5672

如果返回一大串容器ID那就说明创建成功啦!

image.png

查看状态:

这个时候我们可以查看容器是否在运行,当然你也可以使用docker ps来查看

image.png 同样的,我们在这里把容器ID复制下来之后使用docker logs -f <ID>可以查看容器的日志;

特别地,容器的ID可以简写,前提是保证前缀不与其他容器的相同。

就像这样:

image.png


三、 Web端的简单测试

进入Web端:

首先进入cmd输入ipconfig获取本机IP:

image.png

随后输入<IP>:15672进入RabbitMQ的Web端,

例如笔者就是192.168.1.4:15672,随后出现如下界面:

image.png

这个时候我们还没有创建任何账户,默认使用guest进行登录(账密都是):

image.png

Oh非常好,我们看到了想要的界面!


创建新的账户:

人活一世,总不能连个名字都没有,接下来我们就来创建一个新的账户,

毕竟guest有各种访问限制;

我们首先进入容器docker exec -i -t <容器ID> bin/bash

当然你也可以使用点击即送的方法进入,不过这次并不推荐:

image.png

随后添加用户rabbitmqctl add_user <username> <password>

方便起见,我们就用root了,如下:

root@638f5fe7d784:/# rabbitmqctl add_user root 13243546
Adding user "root" ...
Done. Don't forget to grant the user permissions to some virtual hosts! See 'rabbitmqctl help set_permissions' to learn more.

这个时候root还不是"root"呀,我们不能袖手旁观,需要赋予权限

rabbitmqctl set_permissions -p / root ".*" ".*" ".*"

这样可能还不够,还需要给其赋予administrator的角色:

rabbitmqctl set_user_tags root administrator

查看所用用户:

rabbitmqctl list_users

以上的cmd效果:

root@638f5fe7d784:/# rabbitmqctl set_permissions -p / root ".*" ".*" ".*"
Setting permissions for user "root" in vhost "/" ...
root@638f5fe7d784:/# rabbitmqctl set_user_tags root administrator
Setting tags for user "root" to [administrator] ...
root@638f5fe7d784:/# rabbitmqctl list_users
Listing users ...
user    tags
guest   [administrator]
root    [administrator]

回到Web端,再次登录:

这时可以关闭退出容器了,直接exit + 右上角关闭cmd即可;

然后Log Out一下guest账户,重新输入刚才的账户:

可以看到,我们卷土重来了!

image.png


四、 Go + RabbitMQ实现HelloWorld

没错,你没有看错,又是HelloWorld,话不多说让我们进入正题:

打开cmd,进入你想要的项目文件夹,老规矩go mod init <...>

go mod init go-rabbitmq-demo
go: creating new go.mod: module go-rabbitmq-demo
code .  // 打开我们亲爱的VSCode

随后创建send.go

引入github.com/streadway/amqpgo mod tidy

辅助函数

定义一个辅助函数用于检查每个amqp调用的返回值;

发送方和接收方最好都要有;

// 定义辅助函数func failOnError(err error, msg string) {
   if err != nil {
      log.Fatalf("%s: %s", msg, err)
   }
}

send.go主函数

func main() {
    // 建立与 RabbitMQ 的连接
    // 配置连接套接字,定义连接的协议与身份验证
    conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
    failOnError(err, "Failed to connect to RabbitMQ")
    defer conn.Close()
​
    // 创建通道来传递消息
    ch, err := conn.Channel()
    failOnError(err, "Failed to open a channel")
    defer ch.Close()
​
    // 声明要发送到的队列
    q, err := ch.QueueDeclare(
        "hello",
        false,
        false,
        false,
        false,
        nil,
    )
    failOnError(err, "Failed to declare a queue")
    // ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    // defer cancel()
​
    body := "Hello World!"// 将消息发布到声明的队列
    err = ch.Publish(
        "",
        q.Name,
        false,
        false,
        amqp.Publishing{
            ContentType: "text/plain",
            Body:        []byte(body),
        })
    failOnError(err, "Failed to publish a message")
    // log.Printf(" [x] Sent %s\n", body)
}

receive.go主函数

func main() {
    // 建立与 RabbitMQ 的连接
    conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
    failOnError(err, "Failed to connect to RabbitMQ")
    defer conn.Close()
​
    // 获取通道
    ch, err := conn.Channel()
    failOnError(err, "Failed to open a channel")
    defer ch.Close()
​
    // 声明队列
    q, err := ch.QueueDeclare(
        "hello",
        false,
        false,
        false,
        false,
        nil,
    )
    failOnError(err, "Failed to declare a queue")
​
    msgs, err := ch.Consume(
        q.Name, // queue
        "",     // consumer
        true,   // auto-ack
        false,  // exclusive
        false,  // no-local
        false,  // no-wait
        nil,    // args
    )
    failOnError(err, "Failed to register a consumer")
​
    var forever chan struct{}
​
    go func() {
        for d := range msgs {
            log.Printf("Received a message: %s", d.Body)
        }
    }()
​
    log.Printf(" [*] Waiting for messages. To exit press CTRL+C")
    <-forever
}
​

运行!

分别在两个cmd里面执行go run send.gogo run receive.go

注意,send可以执行多次之后再执行receive,也可以先开启receive,读者不妨自己尝试一下;

我们可以在Web端看到,Channel中有数据的情况:

image.png

终端的情况是这样的:

image.png

文件目录结构

很简单,就这四个东西:

image.png


THE END.