This article uses Go language as an example to explain the key points of RabbitMQ client development. First execute the command to install the amqp dependency package:

go get github.com/rabbitmq/amqp091-go

connect RabbitMQ

Establish connection

func Dial(url string) (*Connection, error)
  • url: RabbitMQ server url, for example: amqp://admin:admin@127.0.0.1:5672/

Create channel

func (c *Connection) Channel() (*Channel, error)

Connection can be used to create multiple Channel instances, but Channel instances cannot be shared between threads. The application should open up a Channel for each thread. In some cases, Channel operations can run concurrently, but in other cases, it will cause communication errors and also affect the operation of the publisher confirm mechanism. Therefore, sharing Channel instances between multiple threads is not thread-safe.

uses switch and queue

declare switch

func (ch *Channel) ExchangeDeclare(name, kind string, durable, autoDelete, internal, noWait bool, args Table) error
  • name: The name of the switch.
  • kind: The type of the switch, such as fanout, direct, topic.
  • durable: Whether the setting is durable. Set to persistent to save the switch to disk, and the related information will not be lost when the server restarts.
  • autoDelete: Set whether to delete automatically. is that at least one queue or switch is bound to this switch. When all queues or switches bound to this switch are unbound, the switch will be deleted automatically. Note that this parameter should not be mistakenly interpreted as "When all the clients connected to this switch are disconnected, RabbitMQ will automatically delete this switch".
  • internal: Set whether it is a built-in switch. is set to true, it means that it is a built-in switch, and the client program cannot directly send messages to this switch, but can only be routed to the switch through the switch.
  • noWait: Whether to wait for the server to return without blocking. set to true, it will not block waiting for the return information from RabbitMQ Server (in fact, the server will not return). At this time, using this switch immediately may cause an exception. It is recommended to set it to false.
  • args: Some other structured parameters, such as alternate-exchange, etc.

There is another similar method ExchangeDeclarePassive with exactly the same parameters. This method is mainly used to detect whether the corresponding exchange exists, if it exists, it will return normally, if it does not exist, an exception will be thrown, and the Channel will also be closed.

delete switch

func (ch *Channel) ExchangeDelete(name string, ifUnused, noWait bool) error
  • name: The name of the switch.
  • ifUnused: Set whether to delete the switch when it is not in use. If set to true, the switch will only be deleted if it is not used; if set to false, the switch will be deleted anyway.
  • noWait: Whether to wait for the server to return without blocking, it is recommended to set it to false.

declare queue

func (ch *Channel) QueueDeclare(name string, durable, autoDelete, exclusive, noWait bool, args Table) (Queue, error)
  • name: The name of the queue.
  • durable: Whether the setting is durable. The persistent queue will be saved to disk, and it can be guaranteed that the queue and messages will not be lost when the server is restarted (not lost is relative, if there is no time to save the message during the downtime, it will still be lost).
  • autoDelete: Set whether to delete automatically. automatic deletion is that at least one consumer is connected to this queue, and then all consumers connected to this queue will be deleted automatically. can’t erroneously interpret this parameter as "when all clients connected to this queue are disconnected, this queue will be automatically deleted", because the producer client creates this queue, or when no consumer client connects to this queue , This queue will not be deleted automatically.
  • exclusive: Set whether to be exclusive. If a queue is declared as an exclusive queue, the queue is only visible to the connection where it was first declared, and is automatically deleted when the connection is disconnected. has a few points to note: Exclusive queues are visible based on connections, and different channels of the same connection can access the exclusive queue created by the same connection at the same time; if a connection has declared an exclusive queue, other connections are not allowed to establish an exclusive queue with the same name. Queue; even if the queue is persistent, once the connection is closed or the client exits, the exclusive queue will be automatically deleted. This kind of queue is suitable for application scenarios where a client sends and reads messages at the same time.
  • noWait: Whether to wait for the server to return without blocking, it is recommended to set it to false.
  • args: Set some other parameters of the queue, such as x-message-ttl, x-expires, etc.

Both the producer and the consumer can use queueDeclare to declare a queue, but if the consumer subscribes to another queue on the same channel, the queue can no longer be declared. You must unsubscribe first, and then put the channel in "transmission" mode before you can declare the queue.

There is also a queueDeclarePassive method with exactly the same parameters. This method is used to detect whether the corresponding queue exists. If it exists, it will return normally. If it does not exist, an exception will be thrown and the Channel will be closed.

delete queue

func (ch *Channel) QueueDelete(name string, ifUnused, ifEmpty, noWait bool) (int, error)
  • name: The name of the queue.
  • ifUnused: Set whether to delete the queue when it is not used.
  • ifEmpty: Set whether the queue can be deleted only when the queue is empty (there is no accumulation of messages).
  • noWait: Whether to wait for the server to return without blocking, it is recommended to set it to false.

Clear the queue

func (ch *Channel) QueuePurge(name string, noWait bool) (int, error)
  • name: The name of the queue.
  • noWait: Whether to wait for the server to return without blocking, it is recommended to set it to false.

queue binding

func (ch *Channel) QueueBind(name, key, exchange string, noWait bool, args Table) error
  • name: The name of the queue.
  • key: The key used to bind the queue and the exchange.
  • exchange: The name of the exchange.
  • noWait: Whether to wait for the server to return without blocking, it is recommended to set it to false.
  • args: Define some binding parameters.

Queue

func (ch *Channel) QueueUnbind(name, key, exchange string, args Table) error
  • name: The name of the queue.
  • key: The key used to bind the queue and the exchange.
  • exchange: The name of the exchange.
  • args: Define some parameters for unbinding.

switch binding

func (ch *Channel) ExchangeBind(destination, key, source string, noWait bool, args Table) error
  • destination: Destination switch, usually an internal switch.
  • key: The key used to bind the source switch and the destination switch.
  • source: Source switch.
  • nowait: Whether to wait for the server to return without blocking, it is recommended to set it to false.
  • args: Define some binding parameters.

The producer sends the message to the source switch, and the source switch finds the matching destination switch according to the routing key, and forwards the message to the destination switch, and then stores it in the queue bound to the destination switch.

Send message

func (ch *Channel) Publish(exchange, key string, mandatory, immediate bool, msg Publishing) error
  • exchange: The name of the exchange, indicating which exchange the message needs to be sent to. If set to an empty string, the message will be sent to the default exchange.
  • key: routing key, the exchange stores the message in the corresponding queue according to the routing key.
  • mandatory: It is recommended to be false, and there is a special chapter to explain it later.
  • immediate: It is recommended to be false, which will be explained in a special chapter later.
  • msg: The message to be sent. msg corresponds to a Publishing structure. There are many attributes in the Publishing structure. Except for a few comments, most of them are rarely used.
type Publishing struct {
    // headers类型交换器会使用
    Headers Table

        // 属性
    ContentType     string    // 消息类型
    ContentEncoding string    // 消息编码
    DeliveryMode    uint8     // 是否持久化,0或1非持久化,2持久化
    Priority        uint8     // 优先级,0 - 9
    CorrelationId   string    // 关联id,有助于将RPC响应与请求相关联
    ReplyTo         string    // RPC响应的回调地址,常用于命名回调队列
    Expiration      string    
    MessageId       string    
    Timestamp       time.Time 
    Type            string    
    UserId          string    
    AppId           string    

    // 消息体
    Body []byte
}

Consumer news

RabbitMQ has two consumption modes: Push mode and Pull mode.

Push mode

In the push mode, messages can be consumed through continuous subscription.

func (ch *Channel) Consume(queue, consumer string, autoAck, exclusive, noLocal, noWait bool, args Table) (<-chan Delivery, error)
  • queue: The name of the queue.
  • consumer: Consumer tag, used to distinguish different consumers.
  • autoAck: Set whether to automatically confirm, it is recommended to set it to false.
  • exclusive: Set whether to be exclusive, exclusive means that the current queue can only be used by one consumer.
  • noLocal: Set to true to indicate that the message sent by the producer in the same Connection cannot be sent to the consumer in this Connection.
  • nowait: Whether to wait for the server to return without blocking, it is recommended to set it to false.
  • args: Set other parameters of the consumer.

This function returns a one-way Delivery type channel. It traverses the channel. If there is a message, it will be processed, and if there is no message, it will be blocked. If you need to cancel the subscription, you can call the Cancel method:

func (ch *Channel) Cancel(consumer string, noWait bool) error
  • consumer: Consumer tag, used to distinguish different consumers.
  • nowait: Whether to wait for the server to return without blocking, it is recommended to set it to false.

pull mode

func (ch *Channel) Get(queue string, autoAck bool) (msg Delivery, ok bool, err error)
  • queue: The name of the queue.
  • autoAck: Set whether to automatically confirm, it is recommended to set it to false.

In push mode, the channel is set to receive mode until the subscription of the queue is cancelled. During the receiving mode, RabbitMQ will continuously push messages to consumers (of course, the number of push messages will still be limited by Qos). If you only want to get a single message from the queue instead of continuous subscription, it is recommended to use the pull mode. However, the Get method cannot be placed in a loop to replace the push mode. This will seriously affect the performance of RabbitMQ. If you want to achieve high throughput, consumers should use the push model.

Consumer confirmation and rejection

In order to ensure that the message reaches the consumer reliably from the queue, RabbitMQ provides a message confirmation mechanism. Consumers can specify the autoAck parameter when subscribing to the queue. When autoAck is equal to false, RabbitMQ will wait for the consumer to explicitly reply to the confirmation signal before deleting the message. When autoAck is equal to true, RabbitMQ will automatically set the sent message as confirmation, and then delete it, regardless of whether the consumer actually consumes these messages.

When the autoAck parameter is set to false, for the RabbitMQ server, the message in the queue is divided into two parts: one is waiting for delivery to the consumer, and the other is the message that has been delivered to the consumer, but the consumer has not yet been received Confirmation signal message. If RabbitMQ has not received the consumer's confirmation signal, and the consumer who consumes this message has been disconnected, RabbitMQ will arrange the message to re-enter the queue and wait for delivery to the next consumer (of course it may still be the original one consumer).

RabbitMQ does not set an expiration time for unconfirmed messages. The only basis for it to determine whether the message needs to be re-delivered to the consumer is whether the consumer connection that consumes the message has been disconnected.

confirmation message

func (ch *Channel) Ack(tag uint64, multiple bool) error
func (d Delivery) Ack(multiple bool) error
  • tag: can be regarded as the number of the message.
  • multiple: Set whether to confirm in batches. true means to confirm all messages that have not been confirmed by the current consumer before the number is tag, and false means to confirm only messages with the number tag.

Reject message

func (ch *Channel) Reject(tag uint64, requeue bool) error
func (d Delivery) Reject(requeue bool) error 
  • tag: can be regarded as the number of the message.
  • requeue: Set whether to re-add the message to the queue. If set to true, RabbitMQ will re-store the message in the queue so that it can be sent to the next subscribed consumer; if set to false, the message will be removed from the queue immediately.

Bulk rejection message

func (ch *Channel) Nack(tag uint64, multiple bool, requeue bool) error
func (d Delivery) Nack(multiple, requeue bool) error
  • tag: can be regarded as the number of the message.
  • multiple: Set whether to reject in batches.
  • requeue: Set whether to re-add the message to the queue.

Note: Set the requeue in the Reject or Nack method to false to enable the "dead letter queue" function. Dead letter queues can track problems by detecting rejected or undelivered messages.

Recovery message

func (ch *Channel) Recover(requeue bool) error
  • requeue: Set whether to re-add the message to the queue.

This method is used to request RabbitMQ to resend unconfirmed messages. If the requeue parameter is set to true, the unconfirmed message will be re-added to the queue, so that the same message may be assigned to a different consumer than before. If the requeue parameter is set to false, then the same message will be assigned to the same consumer as before.

Note: The delivery confirmation and rejection methods actually call the Channel's method of the same name. Generally, it is recommended to use the Delivery method.

Close the connection

func (ch *Channel) Close() error
func (c *Connection) Close() error

It is a good habit to explicitly close the Channel, but it is not necessary. When the Connection is closed, the Channel will be closed automatically.

You can also register listeners for connections and channels to listen for close events:

func (c *Connection) NotifyClose(receiver chan *Error) chan *Error
func (ch *Channel) NotifyClose(c chan *Error) chan *Error

与昊
225 声望636 粉丝

IT民工,主要从事web方向,喜欢研究技术和投资之道


引用和评论

0 条评论