如何检测死RabbitMQ连接

时间:2017-02-01 23:43:23

标签: go rabbitmq amqp

我在Go中有一个RabbitMQ使用者脚本(这是RabbitMQ tutorial使用streadway/amqp库的简单脚本)

问题在于,如果rabbitmq-server停止,则消费者脚本不会退出,当再次启动rabbitmq-server时,消费者不再接收消息。

有没有办法检测消费者连接是否已死并重新连接或至少终止消费者脚本?

我知道它设定默认值为10秒。连接的心跳间隔,是否可以使用它?

感谢您的帮助

    func main() {
        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(
            "test_task_queue", // name
            true,         // durable
            false,        // delete when unused
            false,        // exclusive
            false,        // no-wait
            nil,          // arguments
        )
        failOnError(err, "Failed to declare a queue")

        err = ch.Qos(
            1,     // prefetch count
            0,     // prefetch size
            false, // global
        )
        failOnError(err, "Failed to set QoS")

        msgs, err := ch.Consume(
            q.Name, // queue
            "",     // consumer
            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 {
                log.Printf("Received a message: %s", d.Body)
                d.Ack(false)
                dot_count := bytes.Count(d.Body, []byte("."))
                t := time.Duration(dot_count)
                time.Sleep(t * time.Second)
                log.Printf("Done")
            }
        }()

        log.Printf(" [*] Waiting for messages. To exit press CTRL+C")
        <-forever
    }

2 个答案:

答案 0 :(得分:11)

amqp.Connection有方法NotifyClose(),它返回信号传输传输或协议错误。 像

这样的东西
for {  //reconnection loop
    conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/") //setup
    notify := conn.NotifyClose(make(chan *amqp.Error)) //error channel
...
    ch, err := conn.Channel()
    msgs, err := ch.Consume(
...
    for{  //receive loop
        select {  //check connection
            case err = <-notify:
            //work with error
            break //reconnect
        case d = <- msgs:
            //work with message
        ...
        }
    }
}

答案 1 :(得分:0)

尚未发现go-amqp库实现了连接池的断开连接和重新连接功能。
github上有一个基于Amqp二级打包的开源代码。 支持断开连接和异常重新连接后重新连接。该代码也相对易于使用,并且每个服务都有一个连接和通道。

Git地址:https://github.com/billmi/go-rabbit

示例代码:

package main
 
import (
    "go-rabbit/rabbit"
)
 
/*
    support isconnection and reconnection function
    And Failure re-send function
    @author : Bill
*/
func main() {
    var(
        addr = "amqp://guest:guest@localhost:5672/"
        queue = "testQueue"
        exchange = "test_exchange"
        routerKey = "/test"
        msg = "test1!"
 
        //delay
        delayQueue = "delay_queue"
        delayExchange = "delay_exchange"
        delayRouterKey = "delay_exchange"
        prefix = "v1_prefix"
        sep = "_"
        eType = "F"
        _ttl = 60 * 1000
    )
 
    var rabbitProduct1 = rabbit.NewRabbitProduct(addr,_ttl,prefix,sep,delayExchange,delayQueue,delayRouterKey)
    // register recycle
    go rabbitProduct1.InitDefdelay(false)
    go rabbitProduct1.InitDefdelay(true)
    go rabbitProduct1.RegisterDelayWithPreFix("delay_queue","delay_exchange","delay_exchange")
 
    // ttl is dead recycle time if ttl > 0 then recycle
    rabbitProduct1.PubMessage(true,eType,queue,exchange,routerKey,msg,rabbitProduct1.GetBool(1),rabbitProduct1.GetBool(0),_ttl)
 
}

希望它会帮助您或给您一些想法