Go中的RabbitMQ消费者

时间:2016-04-05 07:38:51

标签: go rabbitmq rabbitmq-exchange rabbitmqctl

我正在尝试在Go中编写RabbitMQ Consumer。假设从队列中一次取出5个对象并处理它们。此外,假设确认是否成功处理了否则发送到死信队列5次然后丢弃,它应该无限运行并处理消费者的取消事件。 我几乎没有问题:

  1. RabbitMq-go Reference中是否有BasicConsumer vs EventingBasicConsumer的概念?
  2. RabbitMQ中的Model是什么,它是否在RabbitMq-go中?
  3. 如何在遇到死信队列失败时发送对象,并在ttl
  4. 之后再次对其进行重新排队
  5. 以下代码中consumerTag函数中ch.Consume参数的重要性
  6. 我们应该在这种情况下使用channel.Get()还是channel.Consume()
  7. 我需要在下面的代码中进行哪些更改才能满足上述要求。我问这个是因为我找不到像RabbitMq-Go那样的文档。

       func main() {
    
            consumer()        
        }
    
        func consumer() {
    
            objConsumerConn := &rabbitMQConn{queueName: "EventCaptureData", conn: nil}      
            initializeConn(&objConsumerConn.conn)
    
    
            ch, err := objConsumerConn.conn.Channel()
            failOnError(err, "Failed to open a channel")
            defer ch.Close()
    
            msgs, err := ch.Consume(
                    objConsumerConn.queueName, // queue
                    "demo1",     // consumerTag
                    false,   // auto-ack
                    false,  // exclusive
                    false,  // no-local
                    false,  // no-wait
                    nil,    // args
            )
            failOnError(err, "Failed to register a consumer")
    
            forever := make(chan bool)
    
            go func() {
                for d := range msgs {                  
                    k := new(EventCaptureData)
                    b := bytes.Buffer{}
                    b.Write(d.Body)
                    dec := gob.NewDecoder(&b)  
                    err := dec.Decode(&k)
                    d.Ack(true)  
    
                    if err != nil { fmt.Println("failed to fetch the data from consumer", err); }
                        fmt.Println(k)                        
                }
            }()      
    
            log.Printf(" Waiting for Messages to process. To exit press CTRL+C ")
            <-forever
    
        }
    

    编辑问题:

    我已根据链接link1 link2中的建议延迟了对邮件的处理。但问题是即使在ttl之后,消息也从死信队列回到原始队列。我正在使用RabbitMQ 3.0.0。谁能指出问题是什么?

1 个答案:

答案 0 :(得分:2)

  

是否存在BasicConsumer与EventingBasicConsumer的概念   RabbitMq-go参考?

不完全相同,但Channel.GetChannel.Consume调用提供了类似的概念。使用Channel.Get,您有一个非阻塞调用,如果有可用的话,会收到第一条消息,或者返回ok=false。使用Channel.Consume,排队的消息将传递到频道。

  

RabbitMQ中的模型是什么,它是否在RabbitMq-go中?

如果你在C#RabbitMQ中引用IModelConnection.CreateModel,那就是来自C#lib,而不是来自RabbitMQ本身。这只是试图从RabbitMQ“频道”术语中抽象出来,但它从未流行起来。

  

如果在死信队列失败时再次发送对象   在ttl

之后重新排队

delivery.Nack方法与requeue=false一起使用。

  

ch.Consume中consumerTag参数的意义是什么   函数在下面的代码中

ConsumerTag只是一个消费者标识符。它可用于取消channel.Cancel的渠道,并识别负责交付的消费者。随channel.Consume一起发送的所有邮件都会设置ConsumerTag字段。

  

我们应该在这种情况下使用channel.Get()channel.Consume()吗?

我认为channel.Get()几乎不会优于channel.Consume()。使用channel.Get,您将轮询队列并浪费CPU无所事事,这在Go中没有意义。

  

我需要在下面的代码中进行哪些更改才能满足上述要求   要求。

  1. 由于您一次批量处理5个,因此您可以使用从消费者渠道接收的goroutine,一旦获得5个交付,您可以调用另一个函数来处理它们。

  2. 要确认或发送到死信队列,您将使用delivery.Ackdelivery.Nack功能。您可以使用multiple=true并为批次调用一次。一旦消息进入死信队列,您必须检查delivery.Headers["x-death"]标题是否已被删除多少次,并在已经重试5次时调用delivery.Reject

  3. 使用channel.NotifyCancel处理取消事件。