(基础) RabbitMQ原理及使用


本节内容全部来自于RabbitMQ官网,详情可参考官网链接。
https://www.rabbitmq.com/

Simplest Sample

在这里插入图片描述
一个生产者负责产生消息存入一个消息队列,消息队列Server推送到一个消费者。

Work Queues

在这里插入图片描述
一个生产者产生消息发送到指定的消息队列,消息队列Server通过一定的方式(平均分配,可通过更改channel设置,改变分配策略)推送到一个消费者。

Round-robin dispatching

By default, RabbitMQ will send each message to the next consumer, in sequence. On average every consumer will get the same number of messages. This way of distributing messages is called round-robin. Try this out with three or more workers.

Message acknowledgment

Doing a task can take a few seconds. You may wonder what happens if one of the consumers starts a long task and dies with it only partly done. With our current code, once RabbitMQ delivers a message to the consumer it immediately marks it for deletion. In this case, if you kill a worker we will lose the message it was just processing. We’ll also lose all the messages that were dispatched to this particular worker but were not yet handled.
为了确保消息不丢失,RabitMQ支持消息应答机制。消费者回发一个应答消息给RabitMQ确认接收并处理了该消息,RabitMQ将该消息从队列中删除。
If a consumer dies (its channel is closed, connection is closed, or TCP connection is lost) without sending an ack, RabbitMQ will understand that a message wasn’t processed fully and will re-queue it. If there are other consumers online at the same time, it will then quickly redeliver it to another consumer. That way you can be sure that no message is lost, even if the workers occasionally die.
There aren’t any message timeouts; RabbitMQ will redeliver the message when the consumer dies. It’s fine even if processing a message takes a very, very long time.
Manual message acknowledgments are turned on by default. Use by set autoAck=true
Using this code we can be sure that even if you kill a worker using CTRL+C while it was processing a message, nothing will be lost. Soon after the worker dies all unacknowledged messages will be redelivered.
容易出错点:
It’s a common mistake to miss the basicAck. It’s an easy error, but the consequences are serious. Messages will be redelivered when your client quits (which may look like random redelivery), but RabbitMQ will eat more and more memory as it won’t be able to release any unacked messages.

In order to debug this kind of mistake you can use rabbitmqctl to print the messages_unacknowledged field:
sudo rabbitmqctl list_queues name messages_ready messages_unacknowledged

Message durability

We have learned how to make sure that even if the consumer dies, the task isn’t lost. But our tasks will still be lost if RabbitMQ server stops.
Two things are required to make sure that messages aren’t lost: we need to mark both the queue and messages as durable.
Make sure RabitMQ is durable by channel.queueDeclare(“hello”, durable = true, false, false, null);
This change needs to be applied to both the producer and consumer code.
Mark our messages as persistent - by setting MessageProperties (which implements BasicProperties) to the value PERSISTENT_TEXT_PLAIN。

channel.basicPublish("" , "task_queue",
            MessageProperties.PERSISTENT_TEXT_PLAIN,
            message.getBytes());

Note on message persistence
Marking messages as persistent doesn’t fully guarantee that a message won’t be lost. Although it tells RabbitMQ to save the message to disk, there is still a short time window when RabbitMQ has accepted a message and hasn’t saved it yet. Also, RabbitMQ doesn’t do fsync(2) for every message – it may be just saved to cache and not really written to the disk. The persistence guarantees aren’t strong, but it’s more than enough for our simple task queue. If you need a stronger guarantee then you can use publisher confirms.

即使告诉rabbitmq服务器要同步写,但是rabbitmq也不会每个消息都会去写,所以,如果要更强的机制保证持久化,需要生产者应答。

Fair dispatch

In a situation with two workers, when all odd messages are heavy and even messages are light, one worker will be constantly busy and the other one will do hardly any work. Well, RabbitMQ doesn’t know anything about that and will still dispatch messages evenly.
在这里插入图片描述
In order to defeat that we can use the basicQos(Quality of Service) method with the prefetchCount = 1 setting. This tells RabbitMQ not to give more than one message to a worker at a time. Or, in other words, don’t dispatch a new message to a worker until it has processed and acknowledged the previous one.

Note about queue size
If all the workers are busy, your queue can fill up. You will want to keep an eye on that, and maybe add more workers, or have some other strategy.

Publish/Subscribe

In this part we’ll do something completely different – we’ll deliver a message to multiple consumers. This pattern is known as “publish/subscribe”.

The core idea in the messaging model in RabbitMQ is that the producer never sends any messages directly to a queue. Quite often the producer doesn’t even know if a message will be delivered to any queue at all.

Instead, the producer can only send messages to an exchange. An exchange is a very simple thing. On one side it receives messages from producers and the other side it pushes them to queues. The exchange must know exactly what to do with a message it receives. Should it be appended to a particular queue? Should it be appended to many queues? Or should it get discarded. The rules for that are defined by the exchange type.

在这里插入图片描述
There are a few exchange types available: direct, topic, headers and fanout。

channel.exchangeDeclare("logs", "fanout");

Nameless exchange
In previous parts of the tutorial we knew nothing about exchanges, but still were able to send messages to queues. That was possible because we were using a default exchange, which we identify by the empty string ("").

消息只能存放于队列,不能存放在交换机;交换机只能用于消息的传递,消息通道。

Fanout Exchange

but its value is ignored for fanout exchanges.
在这里插入图片描述
Fanout 就是我们熟悉的广播模式或者订阅模式,给Fanout转发器发送消息,绑定了这个转发器的所有队列都收到这个消息。

Direct exchange

在这里插入图片描述
All other messages will be discarded.
Multiple bindings
在这里插入图片描述
In that case, the direct exchange will behave like fanout and will broadcast the message to all the matching queues.

log system
在这里插入图片描述

Topic exchange

it can’t do routing based on multiple criteria.
In our logging system we might want to subscribe to not only logs based on severity, but also based on the source which emitted the log. There can be as many words in the routing key as you like, up to the limit of 255 bytes.
However there are two important special cases for binding keys:
• * (star) can substitute for exactly one word.
• # (hash) can substitute for zero or more words.
在这里插入图片描述
The first word in the routing key will describe speed, second a colour and third a species: “..”.
These bindings can be summarised as:
Q1 is interested in all the orange animals.
Q2 wants to hear everything about rabbits, and everything about lazy animals.
A message with a routing key set to “quick.orange.rabbit” will be delivered to both queues. Message “lazy.orange.elephant” also will go to both of them. On the other hand “quick.orange.fox” will only go to the first queue, and “lazy.brown.fox” only to the second. “lazy.pink.rabbit” will be delivered to the second queue only once, even though it matches two bindings. “quick.brown.fox” doesn’t match any binding so it will be discarded.

Topic exchange

Topic exchange is powerful and can behave like other exchanges.
When a queue is bound with “#” (hash) binding key - it will receive all the messages, regardless of the routing key - like in fanout exchange.
When special characters “*” (star) and “#” (hash) aren’t used in bindings, the topic exchange will behave just like a direct one.

在这里插入图片描述

Remote procedure call (RPC)

But what if we need to run a function on a remote computer and wait for the result? Well, that’s a different story. This pattern is commonly known as Remote Procedure Call or RPC.

在这里插入图片描述

Callback queue

In general doing RPC over RabbitMQ is easy. A client sends a request message and a server replies with a response message. In order to receive a response we need to send a ‘callback’ queue address with the request.

Summerize

FanoutExchange:将消息分发到所有的绑定队列,无routingkey的概念
HeadersExchange:通过添加属性key-value匹配
DirectExchange:按照routingkey分发到指定队列
TopicExchange:多关键字匹配

猜你喜欢

转载自blog.csdn.net/gonghaiyu/article/details/106783987