The use of golang rabbitmq

Keywords: Go github RabbitMQ

The previous articles mentioned the fanout type exchange similar to broadcast, which supports the classified direct type exchange. Using the example of log in the exchange of direct type, we can distinguish the logs of info, debug, warn and error types. However, there may be further requirements in practice. I hope to see the error log information of the system kernel and the debug log of the interface that takes the longest to request. For such a requirement, you can use the exchange of topic type.

The exchange method using topic type is as follows

(1) exchange of the same topic type is declared in both producer and consumer

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

(2) specify the routing key when publishing messages in producer

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

(3) bind queue to exchange in consumer

err = ch.QueueBind(
                        q.Name,         // queue name
                        "error.kernel", // routing key
                        "logs_topic",   // exchange
                        false,
                        nil)
routing key definition

routing key can explicitly specify an explicit match or use wildcards to match.
The wildcard "ා" represents zero or more words
The wildcard "*" represents a word
If the routing key is specified as ා, all messages will be accepted, similar to the exchange of fanout type
The routing key without the wildcard "ා" or "*" accepts the specified message, similar to the exchange of direct type
routing key uses a hierarchy separated by ".".

For example:
"info.payment.vip" is an info message that only uses vip payment.
"info.payment. *" accepts all payment info messages

The specific code is as follows
conf.go

consumer.go

package main

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

    "github.com/streadway/amqp"
)

/*


./consumer "#" info.payment.* *.log debug.payment.#

*/

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
        "topic",             //exchange kind
        true,                //durable
        false,               //autodelete
        false,
        false,
        nil,
    )

    failOnError(err, "Failed to declare exchange")

    if len(os.Args) < 2 {
        log.Println(len(os.Args))
        log.Println(`"Arguments error(Example: ./consumer "#" info.payment.* *.log debug.payment.#"`)
        return
    }

    topics := os.Args[1:]
    topicsCnt := len(topics)

    for routing := 0; routing < topicsCnt; routing++ {
        go func(routingNum int) {

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

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

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

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

            failOnError(err, "Failed to register a consumer")

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

        }(routing)
    }

    <-forever
}

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

producer.go

package main

import (
    config "binTest/rabbitmqTest/t1/l5/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
        "topic",             //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 topic msg1 msg2 msg3")
        return
    }

    routingKey := os.Args[1]

    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)
    }
}

Operation result
consumer

producer

According to the results, we can see that
consumer specifies 4 routing key s

  • Receive all messages All messages from producer will be received
  • "info.payment. *" accepts all info.payment messages.
    The following message from producer will be received
    ./producer info.payment.googlepay "start payment at 16:00"
  • "*. Log" accepts all messages with log as the second level
    The following message from producer will be received
    ./producer info.log "start recording payment log"
  • "Debug.payment. ා" receives all messages sent to the routing key starting with debug.payment.
    The following message from producer will be received
    ./producer debug.payment.Alipay "10 yuan payment at 15:25" "1000 dollors payment at 15:26" "10 pounds payment at 15:27"
    The following messages will also be received (because ා represents zero or more words)
    ./producer debug.payment.payinfo.Alipay "test payment info"

The detailed code is as follows
https://github.com/BinWang-sh...

Posted by sssphp on Wed, 20 Nov 2019 00:24:27 -0800