Docker 安装RabbitMQ和延时插件,并且通过golang 创建Exchange和Queue,发送延时消息,设置消息持久化。

  1. 安装通过docker compose方式安装。

    version: '3'
    services:
      rabbitmq:
        image: rabbitmq:4-management
        container_name: rabbitmq
        hostname: rabbitmq-node1
        ports:
          - "5672:5672"
          - "15672:15672"
        volumes:
          - ./data:/var/lib/rabbitmq
          - ./myplugins:/myplugins
          # 配置文件
          - ./rabbitmq.conf:/etc/rabbitmq/conf.d/rabbitmq.conf
          # 日志目录
          - ./log:/var/log/rabbitmq
          # tracing日志目录     
          - ./trace-log:/var/tmp/rabbitmq-tracing
        environment:
          - RABBITMQ_PLUGINS_DIR=/plugins:/myplugins
          - RABBITMQ_DEFAULT_USER=test
          - RABBITMQ_DEFAULT_PASS=test1234
        restart: always
    

    镜像用 rabbitmq:4-management, 自带web后台,且该镜像Erlang的版本为27.3.2,高于26,后续安装延时插件对Erlang版本有要求,请注意。指定插件目录为/myplugins并做映射。

  2. 在官方插件目录找到rabbitmq_delayed_message_exchange插件,访问github地址https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases,下载rabbitmq_delayed_message_exchange-v4.0.7.ez,将该文件复制到映射的插件目录 myplugins。

  3. 用docker exec -it rabbitmq bash, 进入容器 执行命令:rabbitmq-plugins enable rabbitmq_delayed_message_exchange,看到插件启用成功。重启容器。在后台 http://<IP地址>:15672/#/exchanges 交换机界面,选择新建交换时有一个type值为:x-delayed-message,表示插件安装成功。

  4. golang 代码发送延时消息

    package mq
    
    import (
    	"fmt"
    	amqp "github.com/rabbitmq/amqp091-go"
    	"log"
    	"time"
    )
    
    const (
    	exName  = "test_exchange"
    	qName   = "test_queue"
    	routKey = "test_key"
    )
    
    // 发送延时消息
    func send() {
    	conn, err := amqp.Dial("amqp://<帐号>:<密码>@<IP地址>:5672/")
    	defer conn.Close()
    	ch, err := conn.Channel()
    	if err != nil {
    
    	}
    	defer ch.Close()
    	// 延时交换机
    	err = ch.ExchangeDeclare(
    		exName,              // 名称
    		"x-delayed-message", // 类型:延时消息
    		true,                // true:持久化
    		false,               // auto-deleted
    		false,               // internal
    		false,               // no-wait
    		amqp.Table{
    			"x-delayed-type": "topic", // 延时消息的类型direct、topic、fanout、headers
    		},
    	)
    	// 普通交换机
    	/*	err = ch.ExchangeDeclare(
    		exName,   // name
    		"direct", // type
    		true,     // durable
    		false,    // auto-deleted
    		false,    // internal
    		false,    // no-wait
    		nil,      // arguments
    	)*/
    	// 声明queue
    	q, err := ch.QueueDeclare(
    		qName, // name
    		true,  // true:持久化
    		false, // false:不自动删除
    		false, // false:非排他,其他连接可用
    		false, // no-wait
    		nil,   // arguments
    	)
    	// 绑定queue到exchange
    	err = ch.QueueBind(
    		q.Name,  // queue name
    		routKey, // routing key
    		exName,  // exchange
    		false,
    		nil)
    
    	fmt.Println("QueueBind", err)
    	// 发送消息
    	body := "Hello RabbitMQ! " + time.Now().Format("2006-01-02 15:04:05")
    	fmt.Println("body", body)
    	err = ch.Publish(
    		exName,  // exchange
    		routKey, // routing key
    		false,   // mandatory
    		false,   // immediate
    		amqp.Publishing{
    			DeliveryMode: amqp.Persistent, // 持久化
    			ContentType:  "text/plain",
    			Body:         []byte(body),
    			Headers: amqp.Table{
    				"x-delay": 60000, // 延时时间,单位毫秒
    			},
    		})
    	fmt.Println("Publish", err)
    
    }
    
    // 消费
    func consume() {
    	conn, err := amqp.Dial("amqp://<帐号>:<密码>@<IP地址>:5672/")
    	if err != nil {
    		log.Fatalf("Failed to connect to RabbitMQ: %v", err)
    	}
    	defer conn.Close()
    	ch, err := conn.Channel()
    	if err != nil {
    		log.Fatalf("Failed to open a channel: %v", err)
    	}
    	defer ch.Close()
    
    	msgs, err := ch.Consume(
    		qName, // 队列名称
    		"",    // 消费者标签
    		false, // false: 需要手动确认才会删除消息
    		false, // 排他性
    		false, // 不返回消息到队列
    		false, // 不等待服务器确认
    		nil,   // 其他参数
    	)
    	if err != nil {
    		log.Fatalf("Failed to register a consumer: %v", err)
    	}
    	for msg := range msgs {
    		fmt.Printf("Received message: %s\n", msg.Body)
    		//msg.Ack(false) // 手动确认才会删除消息
    	}
    }
    
  5. 问题:目前发现修改docker compose 中设置的密码,重新构建 docker compose up -d --build ,密码不会生效,需要删除映射的 data目录下的文件,重建构建,这样会丢失原数据。一旦重新构建需要再次进入容器执行:rabbitmq-plugins enable rabbitmq_delayed_message_exchange,开启插件。把执行命令加在docker compose 文件又报错无法启动。

  6. 配置 rabbitmq.conf

    log.file.level = debug
    #log.file = /var/log/rabbitmq/rabbitmq.log
    #log.file.name = rabbitmq.log
    log.file.rotation.date = $D0
    log.file.rotation.count = 5
    log.file.rotation.compress = true
    log.console.formatter = json
    log.queue.level = debug
    log.queue.file = queue.log
    
  7. 开启tracing ,进入容器执行命令

    rabbitmq-plugins enable rabbitmq_tracing
    rabbitmqctl trace_on
    
  8. 在后台的Admin -> Tracing,下就可以添加tracing,容器重启后之前添加的tracing 就会消失,注意!不知道机器直接安装的是否有这个问题。

posted @ 2025-04-09 14:17  熊先生不开玩笑  阅读(87)  评论(0)    收藏  举报