go 调用 rabbitmq

395 阅读2分钟
  • 生产者

    package product
    
    import (
    	"fmt"
    	"github.com/streadway/amqp"
    )
    
    func Producer()  {
    	var(
    		conn *amqp.Connection
    		err error
    		ch *amqp.Channel
    	)
    	
    	//链接rbmq
    	if conn, err = amqp.Dial("amqp://liulong:liulong@127.0.0.1:5672/"); err!=nil{
    		fmt.Println("amqp.Dial err :", err)
    		return
    	}
    	defer conn.Close()
    	
    	//声明信道
    	if ch, err = conn.Channel(); err!=nil{
    		fmt.Println("conn.Channel err: ", err)
    		return
    	}
    	defer ch.Close()
    
    	//声明交换器
    	if err = ch.ExchangeDeclare(
    		"long123",              //交换器名称
    		amqp.ExchangeDirect,      //交换器模式
    		true,              //持久化保存
    		false,           //是否自动删除
    		false,	        //是否为内置交换器((只能通过交换器将消息路由到此交互器,不能通过客户端发送消息
    		false,           //是否等待服务器返回创建成功的信号ok
    		nil,		//其他参数
    		); err!=nil{
    		fmt.Println("ch.ExchangeDeclare err: ", err)
    		return
    	}
    
    	//发送消息
    	//1.当 mandatory 参数设为 true 时,交换器无法根据自身的类型和路由键找到一个符合条件的队列,
    	// 那么 RabbitMQ 会调用 Basic.Return 命令将消息返回给生产者,可调用ch.NotifyReturn接收
    	//2.当 imrnediate 参数设为 true 时,如果交换器在将消息路由到队列时发现队列上并不存在 任何消费者,
    	// 那么这条消息将不会存入队列中,当与路由键匹配的所有队列都没有消费者时,该消息会返回至生产者
    	//3.概括来说mandatory参数告诉服务器至少将该消息路由到一个队列中,否则将消息返回给生产者。 
    	// imrnediate 参数告诉服务器,如果该消息关联的队列上有消费者,则立刻投递: 如果所有匹配的队列上都没有消费者,
    	// 则直接将消息返还给生产者, 不用将消息存入队列而等待消费者了
    	err = ch.Publish(
    		"long123",   //交换器
    		"abc_key",	  //路由key
    		false,  
    		false,
    		amqp.Publishing{
    		Headers: amqp.Table{},
    		ContentType:"text/plain",
    		Body:[]byte("hello world"),  //消息内容
    		DeliveryMode:amqp.Persistent,  //设置消息持久化
    		Priority:0,                    //消息级别
    	},
    		); 
        if err!=nil{		fmt.Println("ch.Publish err: ", err)
    		return
    	}
    		
    
    }

  • 消费者

    package consum
    
    import (
    	"fmt"
    	"github.com/streadway/amqp"
    	"time"
    )
    
    func Consumer()  {
    
    	var(
    		conn *amqp.Connection
    		ch *amqp.Channel
    		queue amqp.Queue
    		err error
    		delvers <- chan amqp.Delivery
    		message amqp.Delivery
    		ok bool
    	)
    
    	//链接rbmq
    	if conn, err = amqp.Dial("amqp://liulong:liulong@127.0.0.1:5672/");err!=nil{
    		fmt.Println("amqp.Dial err: ", err)
    		return
    	}
    
    	//声明信道
    	if ch, err = conn.Channel(); err!=nil{
    		fmt.Println("conn.Channel err: ", err)
    		return
    	}
    
    	//设置未确认的最大消息数
    	if err = ch.Qos(3, 0, false); err!=nil{
    		fmt.Println("ch.Qos err: ", err)
    		return
    	}
    
    	//声明交换机
    	if err = ch.ExchangeDeclare(
    		"long123",
    		amqp.ExchangeDirect,   //交换机模式direct
    		true,          //持久化
    		false,      //自动删除
    		false,        //是否是内置交互器,(只能通过交换器将消息路由到此交互器,不能通过客户端发送消息
    		false,
    		nil,
    		); err!=nil{
    		fmt.Println("ch.ExchangeDeclare: ", err)
    		return
    	}
    		
    	//声明队列
    	if queue, err = ch.QueueDeclare(
    		"abc",       //队列名称
    		true,      //是否是持久化
    		false,   //是否不需要确认,自动删除消息
    		false,   //是否是排他队列
    		false,    //是否等待服务器返回ok
    		nil,
    		); err!=nil{
    		fmt.Println("ch.QueueDeclare err: ", err)
    		return
    	}
    
    
    	//将交换器和队列/路由key绑定
    	if err = ch.QueueBind(queue.Name, "abc_key", "long123", false, nil); err!=nil{
    		fmt.Println("ch.QueueBind err: ", err)
    		return
    	}
    
    
    
    	//开启推模式消费
    	delvers, err = ch.Consume(
    		queue.Name,
    		"",
    		false,
    		false,
    		false,
    		false,
    		nil,
    	)
    
    	if err!=nil{
    		fmt.Println("ch.Consume err: ", err)
    	}
    
    	//消费接收到的消息
    	for{
    		select {
    		case message, ok = <- delvers:
    			if !ok{
    				return
    			}
    			go func() {
    				//处理消息
    				time.Sleep(time.Second*3)
    				//确认接收到的消息
    				if err = message.Ack(true); err!=nil{
    					fmt.Println("d.Ack err: ", err)
    					return
    				}
    				fmt.Println("已确认", string(message.Body))
    			}()
    		case <-time.After(time.Second*1):
    
    		}
    	}
    }