Let's learn RabbitMQ2: Basic applications of the six modes of RabbiMQ

Let's learn RabbitMQ2: Basic applications of the six modes of RabbiMQ

Hi, everyone, I'm a little devil. Let's start learning Open Source Components today and share them while learning.

The outline of the article is as follows:

  • RabbitMQ Membership
  • Six working mode codes for RabbitMQ

RabbitMQ Membership

  • Producer producer
  • consumer
  • Switch exchange

For accepting, distributing messages

  • Message message
  • queue

Messages for storing producers

  • channel AMQP

Channel used for message push

  • Connect connections

TCP Connection between Generator or Consumer and Rabbit

  • Routing key routingKey

Used to assign generator's data to switches

  • Binding Key

Messages used to bind switches to queues

  • Connection Manager ConnectionFactory

Manager for establishing a connection between an application and Rabbit, used in program code

Six working mode codes for RabbitMQ

single mode

  • Message Generator Queues Messages
  • The consumer of the message listens on the message queue and consumes it if there is a message in the queue

The catalog is as follows:

.
├── consumer.go
├── go.mod
├── go.sum
├── main.go
└── xmtmq
    └── xmtmq.go

The actual codes are as follows:

The coding ideas for each pattern are as follows:

Producer/Consumer

  • Connect server to RabbitMQ
  • Initialize connection
  • Initialize channel
  • Initialize switch exchange
  • Initialize queue
  • Use routing key, bind queue bind, key
  • Production/consumption message produce, consume

Message xmtmq.go

package xmtmq

import (
   "github.com/streadway/amqp"
   "log"
)
// single mode
// Define the data structure of RabbitMQ
// go get github.com/streadway/amqp

type RabbitMQ struct {
   conn      *amqp.Connection // Connect
   channel   *amqp.Channel    // passageway
   QueueName string           // Queue name
   Exchange  string           // Switch
   Key       string           // Routing Key
   MQUrl     string           // Virtual Machine Address for MQ
}

// New a RabbitMQ
func NewRabbitMQ(rbt *RabbitMQ) {
   if rbt == nil || rbt.QueueName == ""  || rbt.MQUrl == "" {
      log.Panic("please check QueueName,Exchange,MQUrl ...")
   }

   conn, err := amqp.Dial(rbt.MQUrl)
   if err != nil {
      log.Panicf("amqp.Dial error : %v", err)
   }
   rbt.conn = conn

   channel, err := rbt.conn.Channel()
   if err != nil {
      log.Panicf("rbt.conn.Channel error : %v", err)
   }
   rbt.channel = channel
}


func RabbitMQFree(rbt *RabbitMQ){
   if rbt == nil{
      log.Printf("rbt is nil,free failed")
      return
   }
   rbt.channel.Close()
   rbt.conn.Close()
}
func (rbt *RabbitMQ) Init() {
   // Application queue
   _, err := rbt.channel.QueueDeclare(
      rbt.QueueName, // Queue name
      true,          // Is it persistent
      false,         // Whether to delete automatically
      false,         // Is it exclusive
      false,         // Is Blocking
      nil,           // Other parameters
   )
   if err != nil {
      log.Printf("rbt.channel.QueueDeclare error : %v", err)
      return
   }
}


// Production message

func (rbt *RabbitMQ) Produce(data []byte) {

   // Add data to the queue
   err := rbt.channel.Publish(
      rbt.Exchange,        // Switch
      rbt.QueueName,       // Queue name
      false,    // If true, failing to find a qualified queue based on its exchange type and routekey rule will return the message to the sender
      false,    // If true, when exchange sends a message to the queue and finds that there are no consumers in the queue, it returns the message to the sender
      amqp.Publishing{
         ContentType: "text/plain",
         Body:        data,
      },
   )
   if err != nil {
      log.Printf("rbt.channel.Publish error : %v", err)
      return
   }
   return
}

// Consumer News
func (rbt *RabbitMQ) Consume() {

   // Consumption data
   msg, err := rbt.channel.Consume(
      rbt.QueueName,    // Queue name
      "xmt",    // Name of the consumer
      true,     // Whether to auto-answer
      false,    // Is it exclusive
      false,    // true means that messages from producers in the same Conenction cannot be delivered to consumers in this Connection
      false,    // Is Blocking
      nil,         // Other Properties
   )

   if err != nil {
      log.Printf("rbt.channel.Consume error : %v", err)
      return
   }

   for data := range msg {
      log.Printf("received data is %v", string(data.Body))
   }

}

main.go

package main

import (
   "fmt"
   "log"
   "time"
   "xmt/xmtmq"
)

/*
RabbimtMQ single Model Case
 Scenario: Use of simple message queues, one producer and one consumer
 Production message
*/

func main() {
    // Set Log
   log.SetFlags(log.Llongfile | log.Ltime | log.Ldate)

   rbt := &xmtmq.RabbitMQ{
      QueueName: "xmtqueue",
      MQUrl:     "amqp://guest:guest@127.0.0.1:5672/xmtmq",
   }

   xmtmq.NewRabbitMQ(rbt)

   var index = 0

   for {
       // Production message
      rbt.Produce([]byte(fmt.Sprintf("hello wolrd %d ", index)))
      log.Println("Send Successfully ", index)
      index++
      time.Sleep(1 * time.Second)
   }

}

consumer.go

package main

import (
   "log"
   "xmt/xmtmq"
)

func main() {

   log.SetFlags(log.Llongfile | log.Ltime | log.Ldate)

   rbt := &xmtmq.RabbitMQ{
      QueueName: "xmtqueue",
      MQUrl:     "amqp://guest:guest@127.0.0.1:5672/xmtmq",
   }

   xmtmq.NewRabbitMQ(rbt)
   rbt.Consume()
}

Open 2 terminals while running

Terminal 1:go run main.go

Terminal 2:go run consumer.go

work mode

Multiple consumers consume messages in the same queue. Queues poll to send messages to consumers on average, where resources are competitive

When a producer produces messages faster than a consumer consumes, consider using the work work mode, which can increase processing speed and load

The work mode is similar to the single mode except that the work mode has a few more consumers than the single mode

Start a terminal 3:go run consumer.go based on single mode

publish / subscribe mode

The publish / subscribe publish subscription mode has one more switch than the Work queues mode, where resources are shared

For scenes

  • Mass mailing
  • Group Chat
  • Broadcasting (Advertising, etc.)

The directory is consistent with the above codes:

xmtmq.go

Start using switch exchange, fanout type

The production side sends the message to the switch first, and then the switch sends the message to the bound queue. Each bound queue receives the message sent by the production side

package xmtmq

import (
   "github.com/streadway/amqp"
   "log"
)

// publish mode
// Define the data structure of RabbitMQ
// go get github.com/streadway/amqp

type RabbitMQ struct {
   conn      *amqp.Connection // Connect
   channel   *amqp.Channel    // passageway
   QueueName string           // Queue name
   Exchange  string           // Switch
   Key       string           // Routing Key
   MQUrl     string           // Virtual Machine Address for MQ
}

// New a RabbitMQ
func NewRabbitMQ(rbt *RabbitMQ) {
   if rbt == nil || rbt.Exchange == "" || rbt.MQUrl == "" {
      log.Panic("please check Exchange,MQUrl ...")
   }

   conn, err := amqp.Dial(rbt.MQUrl)
   if err != nil {
      log.Panicf("amqp.Dial error : %v", err)
   }
   rbt.conn = conn

   channel, err := rbt.conn.Channel()
   if err != nil {
      log.Panicf("rbt.conn.Channel error : %v", err)
   }
   rbt.channel = channel
}

func RabbitMQFree(rbt *RabbitMQ) {
   if rbt == nil {
      log.Printf("rbt is nil,free failed")
      return
   }

   rbt.channel.Close()
   rbt.conn.Close()
}

func (rbt *RabbitMQ) Init() {
   // 1. Create Switches
   err := rbt.channel.ExchangeDeclare(
      rbt.Exchange,        // Switch
      amqp.ExchangeFanout, // Switch Type
      true,                // Is it persistent
      false,               //Whether to delete automatically
      false,               //true means that this exchange cannot be used by client s to push messages, only to bind between exchange and exchange
      false,               // Is Blocking
      nil,                 // Other Properties
   )
   if err != nil {
      log.Printf("rbt.channel.ExchangeDeclare error : %v", err)
      return
   }

}

// Production message publish

func (rbt *RabbitMQ) PublishMsg(data []byte) {

   // 1. Add data to the queue
   err := rbt.channel.Publish(
      rbt.Exchange, // Switch
      "",           // Queue name
      false,        // If true, failing to find a qualified queue based on its exchange type and routekey rule will return the message to the sender
      false,        // If true, when exchange sends a message to the queue and finds that there are no consumers in the queue, it returns the message to the sender
      amqp.Publishing{
         ContentType: "text/plain",
         Body:        data,
      },
   )
   if err != nil {
      log.Printf("rbt.channel.Publish error : %v", err)
      return
   }
   return

}

// Consumer News
func (rbt *RabbitMQ) SubscribeMsg() {

   // 1. Create Queues
   q, err := rbt.channel.QueueDeclare(
      "", // Here we pass in empty, then the name of the randomly generated queue
      true,
      false,
      false,
      false,
      nil,
   )
   if err != nil {
      log.Printf("rbt.channel.QueueDeclare error : %v", err)
      return
   }

   // 2. Binding Queue
   err = rbt.channel.QueueBind(
      q.Name,       // Queue name
      "",           // In publish mode, the key is empty here
      rbt.Exchange, // Switch name
      false,        // Is Blocking
      nil,          // Other Properties
   )
   if err != nil {
      log.Printf("rbt.channel.QueueBind error : %v", err)
      return
   }

   // 3. Consumption data
   msg, err := rbt.channel.Consume(
      q.Name, // Queue name
      "xmt",  // Name of the consumer
      true,   // Whether to auto-answer
      false,  // Is it exclusive
      false,  // true means that messages from producers in the same Conenction cannot be delivered to consumers in this Connection
      false,  // Is Blocking
      nil,    // Other Properties
   )

   if err != nil {
      log.Printf("rbt.channel.Consume error : %v", err)
      return
   }

   for data := range msg {
      log.Printf("received data is %v", string(data.Body))
   }

}

main.go

package main

import (
   "fmt"
   "log"
   "time"
   "xmt/xmtmq"
)

/*
RabbimtMQ publish Model Case
 Scenarios: mass mailing, group chat, broadcast (advertising)
Production message
*/

func main() {

   log.SetFlags(log.Llongfile | log.Ltime | log.Ldate)

   rbt := &xmtmq.RabbitMQ{
      Exchange:  "xmtPubEx",
      MQUrl:     "amqp://guest:guest@127.0.0.1:5672/xmtmq",
   }

   xmtmq.NewRabbitMQ(rbt)
   rbt.Init()

   var index = 0

   for {
      rbt.PublishMsg([]byte(fmt.Sprintf("hello wolrd %d ", index)))
      log.Println("Send Successfully ", index)
      index++
      time.Sleep(1 * time.Second)
   }

   xmtmq.RabbitMQFree(rbt)

}

consumer.go

package main

import (
   "log"
   "xmt/xmtmq"
)

func main() {

   log.SetFlags(log.Llongfile | log.Ltime | log.Ldate)

   rbt := &xmtmq.RabbitMQ{
      Exchange: "xmtPubEx",
      MQUrl:     "amqp://guest:guest@127.0.0.1:5672/xmtmq",
   }

   xmtmq.NewRabbitMQ(rbt)
   rbt.SubscribeMsg()
   xmtmq.RabbitMQFree(rbt)
}

The actions performed are consistent with those described above

Terminal 1:go run main.go

Terminal 2:go run consumer.go

Terminal 3:go run consumer.go

The obvious differences between the effect and the single and work models above are: publishing subscription cases, producer-produced messages, and consumers consuming the content they produce.

routing mode

Message producers send messages to switches, which, according to routing, are messages currently generated by strings that carry routing characters (the method of objects). Switches, based on routing keys, can only match message queues corresponding to routing keys, so that consumers can consume messages.

Scenarios: Get the corresponding function string from the system's code logic, throw message tasks into the corresponding queue for business scenarios, such as handling errors, handling specific messages, and so on

Producer process:

Declare queues and switch -> Create Connection -> Create Channel -> Channel Claim Switch -> Channel declaration queue -> Bind a queue to a switch through a channel and specify the queue's routingkey(Wildcards) -> Make a message -> Send message and specify routingkey(Wildcards)

Consumer Processing:

Declare queues and switch -> Create Connection -> Create Channel -> Channel Claim Switch -> Channel declaration queue -> Bind queues to switches through channels and specify routingkey(Wildcards) -> Rewrite Message Consumption Method -> Execute Message Method

The directory structure is as follows:

.
├── consumer2.go
├── consumer.go
├── go.mod
├── go.sum
├── main.go
└── xmtmq
    └── xmtmq.go

xmtmq.go

  • Switches used are of direct type

  • Use routing keys

package xmtmq

import (
   "github.com/streadway/amqp"
   "log"
)

// routing mode
// Define the data structure of RabbitMQ
// go get github.com/streadway/amqp

type RabbitMQ struct {
   conn      *amqp.Connection // Connect
   channel   *amqp.Channel    // passageway
   QueueName string           // Queue name
   Exchange  string           // Switch
   Key       string           // Routing Key
   MQUrl     string           // Virtual Machine Address for MQ
}

// New a RabbitMQ
func NewRabbitMQ(rbt *RabbitMQ) {
   if rbt == nil || rbt.Exchange == "" || rbt.QueueName == "" || rbt.Key == "" || rbt.MQUrl == "" {
      log.Panic("please check Exchange,,QueueName,Key,MQUrl ...")
   }

   conn, err := amqp.Dial(rbt.MQUrl)
   if err != nil {
      log.Panicf("amqp.Dial error : %v", err)
   }
   rbt.conn = conn

   channel, err := rbt.conn.Channel()
   if err != nil {
      log.Panicf("rbt.conn.Channel error : %v", err)
   }
   rbt.channel = channel
}

func RabbitMQFree(rbt *RabbitMQ) {
   if rbt == nil {
      log.Printf("rbt is nil,free failed")
      return
   }

   rbt.channel.Close()
   rbt.conn.Close()
}

func (rbt *RabbitMQ) Init() {
   // 1. Create Switches
   err := rbt.channel.ExchangeDeclare(
      rbt.Exchange, // Switch
      amqp.ExchangeDirect,     // Switch Type
      true,         // Is it persistent
      false,        //Whether to delete automatically
      false,        //true means that this exchange cannot be used by client s to push messages, only to bind between exchange and exchange
      false,        // Is Blocking
      nil,          // Other Properties
   )
   if err != nil {
      log.Printf("rbt.channel.ExchangeDeclare error : %v", err)
      return
   }

   // 2. Create Queues
   _, err = rbt.channel.QueueDeclare(
      rbt.QueueName, // Here we pass in empty, then the name of the randomly generated queue
      true,
      false,
      false,
      false,
      nil,
   )
   if err != nil {
      log.Printf("rbt.channel.QueueDeclare error : %v", err)
      return
   }

   // 3. Binding Queue
   err = rbt.channel.QueueBind(
      rbt.QueueName, // Queue name
      rbt.Key,       // routing, key needs to be filled in here
      rbt.Exchange,  // Switch name
      false,         // Is Blocking
      nil,           // Other Properties
   )
   if err != nil {
      log.Printf("rbt.channel.QueueBind error : %v", err)
      return
   }

}

// Production message publish

func (rbt *RabbitMQ) ProduceRouting(data []byte) {

   // 1. Add data to the queue
   err := rbt.channel.Publish(
      rbt.Exchange, // Switch
      rbt.Key,      // key
      false,        // If true, failing to find a qualified queue based on its exchange type and routekey rule will return the message to the sender
      false,        // If true, when exchange sends a message to the queue and finds that there are no consumers in the queue, it returns the message to the sender
      amqp.Publishing{
         ContentType: "text/plain",
         Body:        data,
      },
   )
   if err != nil {
      log.Printf("rbt.channel.Publish error : %v", err)
      return
   }

   return
}

// Consumer News
func (rbt *RabbitMQ) ConsumeRoutingMsg() {

   // 4. Consumption data
   msg, err := rbt.channel.Consume(
      rbt.QueueName, // Queue name
      "",     // Name of the consumer
      true,   // Whether to auto-answer
      false,  // Is it exclusive
      false,  // true means that messages from producers in the same Conenction cannot be delivered to consumers in this Connection
      false,  // Is Blocking
      nil,    // Other Properties
   )

   if err != nil {
      log.Printf("rbt.channel.Consume error : %v", err)
      return
   }


   for data := range msg {
      log.Printf("received data is %v", string(data.Body))
   }

}

main.go

package main

import (
   "fmt"
   "log"
   "time"
   "xmt/xmtmq"
)

/*
RabbimtMQ routing Model Case
 Scenarios: Get the corresponding function string from the system's code logic, throw message tasks into the corresponding queue for business scenarios, such as handling errors, handling specific messages, and so on
 Production message
*/

func main() {

   log.SetFlags(log.Llongfile | log.Ltime | log.Ldate)

   rbt1 := &xmtmq.RabbitMQ{
      Exchange: "xmtPubEx2",
      Key: "xmt1",
      QueueName: "Routingqueuexmt1",
      MQUrl:     "amqp://guest:guest@127.0.0.1:5672/xmtmq",
   }

   xmtmq.NewRabbitMQ(rbt1)
   rbt1.Init()


   rbt2 := &xmtmq.RabbitMQ{
      Exchange: "xmtPubEx2",
      Key: "xmt2",
      QueueName: "Routingqueuexmt2",
      MQUrl:     "amqp://guest:guest@127.0.0.1:5672/xmtmq",
   }

   xmtmq.NewRabbitMQ(rbt2)
   rbt2.Init()


   var index = 0

   for {
      rbt1.ProduceRouting([]byte(fmt.Sprintf("hello wolrd xmt1  %d ", index)))
      log.Println("Send Successfully xmt1  ", index)

      rbt2.ProduceRouting([]byte(fmt.Sprintf("hello wolrd xmt2  %d ", index)))
      log.Println("Send Successfully xmt2  ", index)


      index++
      time.Sleep(1 * time.Second)
   }


   xmtmq.RabbitMQFree(rbt1)
   xmtmq.RabbitMQFree(rbt2)

}

consumer.go

package main

import (
   "log"
   "xmt/xmtmq"
)

func main() {

   log.SetFlags(log.Llongfile | log.Ltime | log.Ldate)

   rbt := &xmtmq.RabbitMQ{
      Exchange: "xmtPubEx2",
      Key: "xmt1",
      QueueName: "Routingqueuexmt1",
      MQUrl:     "amqp://guest:guest@127.0.0.1:5672/xmtmq",
   }

   xmtmq.NewRabbitMQ(rbt)
   rbt.ConsumeRoutingMsg()
   xmtmq.RabbitMQFree(rbt)
}

consumer2.go

package main

import (
   "log"
   "xmt/xmtmq"
)

func main() {

   log.SetFlags(log.Llongfile | log.Ltime | log.Ldate)

   rbt := &xmtmq.RabbitMQ{
      Exchange: "xmtPubEx2",
      Key:      "xmt2",
      QueueName: "Routingqueuexmt2",
      MQUrl:    "amqp://guest:guest@127.0.0.1:5672/xmtmq",
   }

   xmtmq.NewRabbitMQ(rbt)
   rbt.ConsumeRoutingMsg()
   xmtmq.RabbitMQFree(rbt)
}

topic mode

Topic mode, where a message is retrieved by multiple consumers and the target queue of the message is available with the BindingKey wildcard

Topics mode is actually a routing mode

The biggest difference between them is that Topics mode sends messages and consumer messages by matching them with wildcards

  • A * number means you can use a word with it
  • A #number means that you can use zero or more words together

The coded case remains the same as the routing pattern above, except the exchange is of top type

The following are the switches and queues involved in the above modes

rpc mode

RPC remote procedure calls, client calls server-side methods remotely, and uses MQ to make RPC asynchronous calls

The directory structure is:

.
├── consumer.go
├── go.mod
├── go.sum
├── main.go
└── xmtmq
    └── xmtmq.go
  • Clients are both producers and consumers, sending RPC call messages to RPC request queues and listening for RPC response queues
  • The server listens for messages from the RPC request queue, executes the server-side method after receiving the message, and gets the result returned by the method
  • The server sends the results of the RPC method to the RPC response queue.
  • Client listens on RPC response queue and receives the result of RPC call

xmtmq.go

package xmtmq

import (
   "github.com/streadway/amqp"
   "log"
   "math/rand"
)

// rpc mode
// Define the data structure of RabbitMQ
// go get github.com/streadway/amqp

type RabbitMQ struct {
   conn      *amqp.Connection // Connect
   channel   *amqp.Channel    // passageway
   QueueName string           // Queue name
   Exchange  string           // Switch
   Key       string           // Routing Key
   MQUrl     string           // Virtual Machine Address for MQ
}

// New a RabbitMQ
func NewRabbitMQ(rbt *RabbitMQ) {
   if rbt == nil || rbt.QueueName == "" || rbt.MQUrl == "" {
      log.Panic("please check QueueName,Exchange,MQUrl ...")
   }

   conn, err := amqp.Dial(rbt.MQUrl)
   if err != nil {
      log.Panicf("amqp.Dial error : %v", err)
   }
   rbt.conn = conn

   channel, err := rbt.conn.Channel()
   if err != nil {
      log.Panicf("rbt.conn.Channel error : %v", err)
   }
   rbt.channel = channel
}

func RabbitMQFree(rbt *RabbitMQ) {
   if rbt == nil {
      log.Printf("rbt is nil,free failed")
      return
   }
   rbt.channel.Close()
   rbt.conn.Close()
}

// Production message

func (rbt *RabbitMQ) Produce(data []byte) {

   // Application queue
   q, err := rbt.channel.QueueDeclare(
      rbt.QueueName, // Queue name
      true,          // Is it persistent
      false,         // Whether to delete automatically
      false,         // Is it exclusive
      false,         // Is Blocking
      nil,           // Other parameters
   )
   if err != nil {
      log.Printf("rbt.channel.QueueDeclare error : %v", err)
      return
   }

   err = rbt.channel.Qos(1, 0, false)
   if err != nil {
      log.Printf("rbt.channel.Qos error : %v", err)
      return
   }

   d, err := rbt.channel.Consume(
      q.Name,
      "",
      false,
      false,
      false,
      false,
      nil)
   if err != nil {
      log.Printf("rbt.channel.Consume error : %v", err)
      return
   }

   for msg := range d {
      log.Println("received msg is  ", string(msg.Body))
      err := rbt.channel.Publish(
         "",
         msg.ReplyTo,
         false,
         false,
         amqp.Publishing{
            ContentType:   "test/plain",
            CorrelationId: msg.CorrelationId,
            Body:          data,
         })
      if err != nil {
         log.Printf("rbt.channel.Publish error : %v", err)
         return
      }
      msg.Ack(false)
      log.Println("svr response ok ")
   }

   return
}
func randomString(l int) string {
   bytes := make([]byte, l)
   for i := 0; i < l; i++ {
      bytes[i] = byte(rand.Intn(l))
   }
   return string(bytes)
}

// Consumer News
func (rbt *RabbitMQ) Consume() {

   // Application queue
   q, err := rbt.channel.QueueDeclare(
      "",    // Queue name
      true,  // Is it persistent
      false, // Whether to delete automatically
      false, // Is it exclusive
      false, // Is Blocking
      nil,   // Other parameters
   )
   if err != nil {
      log.Printf("rbt.channel.QueueDeclare error : %v", err)
      return
   }

   // Consumption data
   msg, err := rbt.channel.Consume(
      q.Name, // Queue name
      "xmt",  // Name of the consumer
      true,   // Whether to auto-answer
      false,  // Is it exclusive
      false,  // true means that messages from producers in the same Conenction cannot be delivered to consumers in this Connection
      false,  // Is Blocking
      nil,    // Other Properties
   )
   if err != nil {
      log.Printf("rbt.channel.Consume error : %v", err)
      return
   }
   id := randomString(32)
   err = rbt.channel.Publish(
      "",
      rbt.QueueName,
      false,
      false,
      amqp.Publishing{
         ContentType:   "test/plain",
         CorrelationId: id,
         ReplyTo:       q.Name,
         Body:          []byte("321"),
      })
   if err != nil {
      log.Printf("rbt.channel.Publish error : %v", err)
      return
   }

   for data := range msg {
      log.Printf("received data is %v", string(data.Body))
   }
}

main.go

package main

import (
   "fmt"
   "log"
   "xmt/xmtmq"
)

/*
RabbimtMQ rpc Model Case
 Scenario: Use of simple message queues, one producer and one consumer
 Production message
*/

func main() {

   log.SetFlags(log.Llongfile | log.Ltime | log.Ldate)

   rbt := &xmtmq.RabbitMQ{
      QueueName: "xmtqueue",
      MQUrl:     "amqp://guest:guest@127.0.0.1:5672/xmtmq",
   }

   xmtmq.NewRabbitMQ(rbt)

   rbt.Produce([]byte(fmt.Sprintf("hello wolrd")))

}

consumer.go

package main

import (
   "log"
   "math/rand"
   "time"
   "xmt/xmtmq"
)

func main() {

   log.SetFlags(log.Llongfile | log.Ltime | log.Ldate)
   rand.Seed(time.Now().UTC().UnixNano())
   rbt := &xmtmq.RabbitMQ{
      QueueName: "xmtqueue",
      MQUrl:     "amqp://guest:guest@127.0.0.1:5672/xmtmq",
   }

   xmtmq.NewRabbitMQ(rbt)
   rbt.Consume()
}

Let's run the consumer first, run a few more, and you can see that we already have data in our queue. We run two consumers, so here's 2

By running the producer again, you can see that the producer consumes the message sent by the consumer, and through the correlation Id, you can find the queue corresponding to the consumer's monitoring and send the data to the queue

When there is data in the queue that consumers monitor, they take it out for consumption

summary

Six working modes of RabbitMQ:

  • single mode
  • work mode
  • publish / subscribe mode
  • routing mode
  • topic mode
  • rpc mode

Reference material:

RabbitMQ Tutorials

Welcome to Comment, Attention, Collection

Friends, your support and encouragement are my motivation to keep sharing and improve quality

Okay, that's it this time

Technology is open, our mindset should be more open. Embrace change, live in the sun and work hard to move forward.

I'm a little devil. Welcome to your collection. See you next time.

Tags: Go

Posted on Thu, 30 Sep 2021 13:14:46 -0400 by SmoshySmosh