每次当amqp.Dial是线程安全时是否创建连接或者不是go lang

时间:2016-03-23 13:09:40

标签: go rabbitmq rabbitmqctl

正如RabbitMQ文档中提到的那样,tcp连接的成本很高。因此,为此引入了渠道概念。现在我遇到了这个example。在main()中,每次发布消息时都会创建连接。 conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")。 不应该全局声明一次,如果连接像singleton对象那样关闭,应该有故障转移机制。如果amqp.Dial是线程安全的,我认为它应该是

编辑问题:

我正在以下列方式处理连接错误。我在一个频道上听,并在出错时创建一个新的连接。但是当我杀死现有连接并尝试发布消息时。我收到以下错误。

错误:

2016/03/30 19:20:08 Failed to open a channel: write tcp 172.16.5.48:51085->172.16.0.20:5672: use of closed network connection
exit status 1
7:25 PM

代码:

 func main() {

        Conn, err := amqp.Dial("amqp://guest:guest@172.16.0.20:5672/")
        failOnError(err, "Failed to connect to RabbitMQ")
         context := &appContext{queueName: "QUEUENAME",exchangeName: "ExchangeName",exchangeType: "direct",routingKey: "RoutingKey",conn: Conn}
        c := make(chan *amqp.Error)

        go func() {
            error := <-c
            if(error != nil){                
                Conn, err = amqp.Dial("amqp://guest:guest@172.16.0.20:5672/")            
                failOnError(err, "Failed to connect to RabbitMQ")            
                Conn.NotifyClose(c)                                           
            }            
        }()

        Conn.NotifyClose(c)
        r := web.New()
        // We pass an instance to our context pointer, and our handler.
        r.Get("/", appHandler{context, IndexHandler})
        graceful.ListenAndServe(":8086", r)  

    }

1 个答案:

答案 0 :(得分:9)

当然,您不应为每个请求创建连接。使其成为全局变量或在启动时初始化的application context的更好部分。

您可以使用Connection.NotifyClose注册频道来处理连接错误:

func initialize() {
  c := make(chan *amqp.Error)
  go func() {
    err := <-c
    log.Println("reconnect: " + err.Error())
    initialize()
  }()

  conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
  if err != nil {
    panic("cannot connect")
  }
  conn.NotifyClose(c)

  // create topology
}