【RabbitMQ】fanout type exchange example in golang

煎雞蛋湯發表於2018-07-05

【RabbitMQ】核心概念講到,Exchange有三種型別:

  • fanout
  • direct
  • topic

緊接著的三篇文章將介紹著三種型別,並給出golang的實現,本篇為第一篇,介紹fanout型別(fanout型別的exchange,會將訊息傳送到所有繫結了該exchange的queue上,可以理解成廣播模式)

在我的開發環境中,GOPATH=C:\Users${user_name}\go,在GOPATH\src 目錄下新建fanout專案。在fanout專案中新建兩個檔案:

  • producer.go。負責傳送訊息
  • consumer.go。負責接收訊息

在producer.go中寫入以下程式碼:

package main

import (
        "log"
        "os"

        "github.com/streadway/amqp"
)

func exit_on_error(err error) {
        if err != nil {
                log.Fatal(err)
        }
}

func main() {
        conn, err := amqp.Dial("amqp://<username>:<password>@<host>:<port>/")
        exit_on_error(err)
        defer conn.Close()

        ch, err := conn.Channel()
        exit_on_error(err)
        defer ch.Close()

        err = ch.ExchangeDeclare(
                "example.fanout",   // name
                "fanout", // type
                true,     // durable
                false,    // auto-deleted
                false,    // internal
                false,    // no-wait
                nil,      // arguments
        )
        exit_on_error(err)

        message := os.Args[1]

        err = ch.Publish(
                "example.fanout", // exchange
                "",     // routing key
                false,  // mandatory
                false,  // immediate
                amqp.Publishing{
                        ContentType: "text/plain",
                        Body:        []byte(message),
                },
        )

        log.Printf(" [x] Sent %s", message)
}

producer流程:

  1. 建立exchange
  2. 傳送訊息到exchange(指定routingkey,但fanout型別的exchange不關心routingkey)

在consumer.go中寫入以下程式碼:

package main

import (
        "log"

        "github.com/streadway/amqp"
)

func exit_on_error(err error) {
        if err != nil {
                log.Fatal(err)
        }
}

func main() {
        conn, err := amqp.Dial("amqp://<username>:<password>@<host>:<port>/")
        exit_on_error(err)
        defer conn.Close()

        ch, err := conn.Channel()
        exit_on_error(err)
        defer ch.Close()

        err = ch.ExchangeDeclare(
                "example.fanout",   // name
                "fanout", // type
                true,     // durable
                false,    // auto-deleted
                false,    // internal
                false,    // no-wait
                nil,      // arguments
        )
        exit_on_error(err)

        q, err := ch.QueueDeclare(
                "",    // name
                false, // durable
                false, // delete when usused
                true,  // exclusive
                false, // no-wait
                nil,   // arguments
        )
        exit_on_error(err)

        err = ch.QueueBind(
                q.Name, // queue name
                "",     // routing key
                "example.fanout", // exchange
                false,
                nil,
        )
        exit_on_error(err)

        msgs, err := ch.Consume(
                q.Name, // queue
                "",     // consumer
                true,   // auto-ack
                false,  // exclusive
                false,  // no-local
                false,  // no-wait
                nil,    // args
        )
        exit_on_error(err)

        forever := make(chan bool)

        go func() {
                for d := range msgs {
                        log.Printf(" [x] %s", d.Body)
                }
        }()

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

說明:conn, err := amqp.Dial("amqp://<username>:<password>@<host>:<port>/")使用<username>等變數,需要替換成實際環境引數

consumer流程:

  1. 申明exchange
  2. 宣告queue
  3. 將queue繫結到exchange
  4. 訂閱queue

特別說明:如果將producer.go和consumer.go放到同一個目錄下,IDE會報錯,同一個main package中有兩個main function,可以忽略

執行producer:

go run producer.go <message>

執行consumer(為了測試效果,開啟兩個以上終端,執行以下命令):

go run consumer.go

執行結果示例:
這裡寫圖片描述

相關文章