golang gin 监听rabbitmq队列无限消费

该博客介绍了如何使用Go语言的Gin框架结合RabbitMQ进行消息生产和消费。首先,通过`amqp`库建立与RabbitMQ的连接并声明队列,然后创建生产者发送JSON格式的数据到队列。接着,实现消费者无限循环监听队列,接收到消息后进行处理,处理完成后手动ACK确认。在遇到通道关闭时,能自动重新连接并设置Qos。整个流程确保了消息的可靠传递。
摘要由CSDN通过智能技术生成

golang gin 监听rabbitmq队列无限消费

  1. 连接rabbitmq

    package database
    
    import (
    	"github.com/streadway/amqp"
    	"log"
    	"reflect"
    	"yy-data-processing/common/config"
    )
    
    var RabbitConn *amqp.Connection
    var RabbitChannel *amqp.Channel
    
    func InitRabbitmq() {
    	var err error
    	RabbitConn, err = amqp.Dial(config.Config.RabbitUrl)
    	if err != nil {
    		log.Println("连接RabbitMQ失败")
    		panic(err)
    	}
    	RabbitChannel, err = RabbitConn.Channel()
    	if err != nil {
    		log.Println("获取RabbitMQ channel失败")
    		panic(err)
    	}
    }
    
    // 0表示channel未关闭,1表示channel已关闭
    func CheckRabbitClosed(ch amqp.Channel) int64 {
    	d := reflect.ValueOf(ch)
    	i := d.FieldByName("closed").Int()
    	return i
    }
    
    
  2. 创建生产者

package service

import (
	"encoding/json"
	"github.com/streadway/amqp"
	"log"
	"yy-data-processing/common/config"
	"yy-data-processing/common/database"
	"yy-data-processing/model"
)

func Producer() {
	// 声明队列,没有则创建
	// 队列名称、是否持久化、所有消费者与队列断开时是否自动删除队列、是否独享(不同连接的channel能否使用该队列)
	declare, err := database.RabbitChannel.QueueDeclare(config.Config.HawkSaveQueueName, true, false, false, false, nil)
	if err != nil {
		log.Printf("声明队列 %v 失败, error: %v", config.Config.HawkSaveQueueName, err)
		panic(err)
	}

	request := model.Request{}
	marshal, _ := json.Marshal(request )
	// exchange、routing key、mandatory、immediate
	err = database.RabbitChannel.Publish("", declare.Name, false, false, amqp.Publishing{
		ContentType: "text/plain",
		Body:        []byte(marshal),
	})
	if err != nil {
		log.Printf("生产者发送消息失败, error: %v", err)
	} else {
		log.Println("生产者发送消息成功")
	}
}
  1. 创建消费者

    package service
    
    import (
    	"encoding/json"
    	"log"
    	"os"
    	"strings"
    	"sync"
    	"time"
    	"yy-data-processing/common/config"
    	"yy-data-processing/common/database"
    	"yy-data-processing/model"
    )
    
    func Consumer() {
    	// 声明队列,没有则创建
    	// 队列名称、是否持久化、所有消费者与队列断开时是否自动删除队列、是否独享(不同连接的channel能否使用该队列)
    	_, err := database.RabbitChannel.QueueDeclare(config.Config.QueueName, true, false, false, false, nil)
    	if err != nil {
    		log.Printf("声明队列 %v 失败, error: %v", config.Config.QueueName, err)
    		panic(err)
    	}
        
        err = database.RabbitChannel.Qos(
     		1,     // prefetch count 服务器将在收到确认之前将那么多消息传递给消费者。
     		0,     // prefetch size  服务器将尝试在收到消费者的确认之前至少将那么多字节的交付保持刷新到网络
     		false, // 当 global 为 true 时,这些 Qos 设置适用于同一连接上所有通道上的所有现有和未来消费者。当为 false 时,Channel.Qos 设置将应用于此频道上的所有现有和未来消费者
     	)
     	if err != nil {
     		log.Printf("rabbitmq设置Qos失败, error: %v", err)
     	}
     
    	// 队列名称、consumer、auto-ack、是否独享
    	// deliveries是一个管道,有消息到队列,就会消费,消费者的消息只需要从deliveries这个管道获取
    	deliveries, err := database.RabbitChannel.Consume(config.Config.QueueName, "", false, false, false, false, nil)
    	if err != nil {
    		log.Printf("从队列 %v 获取数据失败, error: %v", config.Config.QueueName, err)
    	} else {
    		log.Println("从消费队列获取任务成功")
    	}
        
        // 阻塞住
    	for {
    		select {
    		case message := <-deliveries:
    			closed := database.CheckRabbitClosed(*database.RabbitChannel)
    			if closed == 1 { // channel 已关闭,重连一下
    				database.InitRabbitmq()
    				err = database.RabbitChannel.Qos(1, 0, false)
     				if err != nil {
     					log.Printf("rabbitmq重连后设置Qos失败, error: %v", err)
     				}
    			} else {
    				msgData := string(message.Body)
    				request := model.Request{}
    				err := json.Unmarshal([]byte(msgData), &request)
    				if err != nil {
    					log.Printf("解析rabbitmq数据 %v 失败, error: %v", msgData, err)
    				} else {
    					// TODO...
                        // 处理逻辑
                        
                        // 处理完毕手动ACK
    					message.Ack(true)
    				}
    			}
    		}
    	}
    }
    
  2. main方法协程调用

    package main
    
    import (
    	"log"
    	"yy-data-processing/common/config"
    	"yy-data-processing/common/database"
    	"yy-data-processing/router"
    	"yy-data-processing/service"
    )
    
    func main() {
    	// 初始化路由
    	routers := router.InitRouters()
    
    	// 初始化RabbitMQ
    	database.InitRabbitmq()
    	go service.Producer()
    	go service.Consumer()
    
    	port := config.Config.Port
    	if err := routers.Run(":" + port); err != nil {
    		log.Printf("启动服务失败: ", err)
    	}
    
    }
    
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值