The use of golang rabbitmq

Keywords: Go github RabbitMQ

In the second chapter, we talked about the exchange of fanout type. The fanout type exchange will send messages to all the queues that are bound with it, without distinguishing and filtering. But in reality, we often need to have filtering conditions to separate different messages and send them to different queues. For example, the log of the system. We need to send the received logs to different queues according to info, debug, warn, err, and use different consumer s to handle these different logs.
In order to achieve this function, we can

  • ExchangeDeclare specifies type as direct
    err = ch.ExchangeDeclare(
        "syslog_direct", //exchange name
        "direct",        //exchange kind
        true,            //durable
        false,           //autodelete
        false,
        false,
        nil,
    )
  • Producer specifies routing key when publishing
err = ch.Publish(
            "syslog_direct", //exchange
            routingKey,      //routing key
            false,
            false,
            amqp.Publishing{
                ContentType: "text/plain",
                Body:        []byte(msgBody),
            })
  • Consumer specifies routing key when QueueBind
err = ch.QueueBind(
                q.Name,
                routingKey,      //routing key
                "syslog_direct", //exchange
                false,
                nil,
            )

The specific test code is as follows:
conf.go

package config

const (
    RMQADDR      = "amqp://guest:guest@172.17.84.205:5672/"
    EXCHANGENAME = "syslog_direct"
    CONSUMERCNT  = 4
)

var (
    RoutingKeys [4]string = [4]string{"info", "debug", "warn", "error"}
)

producer.go

package main

import (
    config "binTest/rabbitmqTest/t1/l4/conf"
    "fmt"
    "log"
    "os"

    "github.com/streadway/amqp"
)

func main() {

    conn, err := amqp.Dial(config.RMQADDR)
    failOnError(err, "Failed to connect to RabbitMQ")
    defer conn.Close()

    ch, err := conn.Channel()
    failOnError(err, "Failed to open a channel")
    defer ch.Close()

    err = ch.ExchangeDeclare(
        config.EXCHANGENAME, //exchange name
        "direct",            //exchange kind
        true,                //durable
        false,               //autodelete
        false,
        false,
        nil,
    )

    failOnError(err, "Failed to declare exchange")

    if len(os.Args) < 3 {
        fmt.Println("Arguments error(ex:producer info/debug/warn/error msg1 msg2 msg3")
        return
    }

    routingKey := os.Args[1]

    validKey := false
    for _, item := range config.RoutingKeys {
        if routingKey == item {
            validKey = true
            break
        }
    }

    if validKey == false {
        fmt.Println("Arguments error, no valid routing key specified.(ex:producer info/debug/warn/error msg1 msg2 msg3")
        return
    }
    msgs := os.Args[2:]

    msgNum := len(msgs)

    for cnt := 0; cnt < msgNum; cnt++ {
        msgBody := msgs[cnt]
        err = ch.Publish(
            config.EXCHANGENAME, //exchange
            routingKey,          //routing key
            false,
            false,
            amqp.Publishing{
                ContentType: "text/plain",
                Body:        []byte(msgBody),
            })

        log.Printf(" [x] Sent %s", msgBody)
    }
    failOnError(err, "Failed to publish a message")

}

func failOnError(err error, msg string) {
    if err != nil {
        fmt.Printf("%s: %s\n", msg, err)
    }
}

consumer.go

package main

import (
    config "binTest/rabbitmqTest/t1/l4/conf"
    "fmt"
    "log"

    "github.com/streadway/amqp"
)

func main() {

    conn, err := amqp.Dial(config.RMQADDR)
    failOnError(err, "Failed to connect to RabbitMQ")
    defer conn.Close()

    forever := make(chan bool)

    ch, err := conn.Channel()
    failOnError(err, "Failed to open a channel")
    defer ch.Close()

    err = ch.ExchangeDeclare(
        config.EXCHANGENAME, //exchange name
        "direct",            //exchange kind
        true,                //durable
        false,               //autodelete
        false,
        false,
        nil,
    )

    failOnError(err, "Failed to declare exchange")

    for routing := 0; routing < config.CONSUMERCNT; routing++ {
        go func(routingNum int) {

            q, err := ch.QueueDeclare(
                "",
                false, //durable
                false,
                true,
                false,
                nil,
            )

            failOnError(err, "Failed to declare a queue")

            err = ch.QueueBind(
                q.Name,
                config.RoutingKeys[routingNum],
                config.EXCHANGENAME,
                false,
                nil,
            )
            failOnError(err, "Failed to bind exchange")

            msgs, err := ch.Consume(
                q.Name,
                "",
                true, //Auto Ack
                false,
                false,
                false,
                nil,
            )

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

            for msg := range msgs {
                log.Printf("In %s consume a message: %s\n", config.RoutingKeys[routingNum], msg.Body)
            }

        }(routing)
    }

    <-forever
}

func failOnError(err error, msg string) {
    if err != nil {
        fmt.Printf("%s: %s\n", msg, err)
    }
}

The detailed code can be obtained from here (l4):
https://github.com/BinWang-sh...

Posted by tommyboy123x on Tue, 19 Nov 2019 08:29:00 -0800