In the last blog post, I mentioned that if you do a cluster , then the cluster is successful, but how is the queue stored? How are the messages synchronized?
The default, that is, nothing is configured, and a queue is added directly to a node, then it only belongs to this node. All other nodes have is its shadow. Therefore, such as disconnection and reconnection, operation recovery cannot be achieved, and experiments have proved that this is indeed the case. If the node that declares the queue is closed, it is no longer possible to publish messages and consume. This naturally loses the meaning of clusters
So the default mode is generally not used, our choice is the mirror node
Queue mirror In other words, there will be a master corresponding to zero or more slaves
It can also be said to be master-slave replication, each node has the same data, and a node hangs up, the other can be immediately topped
You can also see in the official documentation that the configuration of the mirror is done through the policy policy.
We have three ways to synchronize, generally all is our best choice
all all nodes will be synced
exactly the specified number of nodes are synchronized
nodes with the name specified by nodes are synchronized
A simple example, the following is ha-all is our policy name, followed by ^ha\. It is a regular, and the queue name that satisfies this rule will be mirrored. The way is that all nodes are synchronized
What needs to be explained here is that the policy can be applied to exchange and queue, or you can choose only which one to apply to. The following command is applied to both exchange and queue.
rabbitmqctl set_policy ha-all "^ha\." "{""ha-mode"":""all""}"
Looking at the documentation, it seems that the parameters of apply to are not provided, so the following operations will use the WEB UI. You can see that the creation strategy of the WEB UI provides us with rich options, such as apply to, priority, and other settings
We need to pay attention to the parameters about HA in the above figure
Ha mode synchronization mode
Ha params select other synchronization parameters such as node name
Ha async mode synchronization mode, this needs to be explained in detail, by default. When the node is disconnected, the node is already a backward version. When we start the node again, we need to manually synchronize the data. This is naturally not good. It is the most perfect to automate, so set it to automatic. is the best choice
The following sets up a strategy that works with queue, all nodes in the cluster will be synchronized, and automatically synchronized after disconnection and restart
After the setup is complete, you can see the effect through the code. Because the cluster is used, some changes need to be made when creating a connection. When creating a connection, the ip of the node is put in.
AutomaticRecoveryEnabled disconnection and reconnection, that is, if the current connection is disconnected, it will try to reconnect
TopologyRecoveryEnabled restores the current work process after reconnection, such as channel, queue, published message progress, etc.
var factory = new ConnectionFactory() { UserName = "admin", Password = "admin", AutomaticRecoveryEnabled = true, TopologyRecoveryEnabled = true }; Connection = factory.CreateConnection(new string[3] { "192.168.1.115", "192.168.1.113", "192.168.1.123" });
A test1queue is declared here, and then the message is published. When the node crashes, the code will naturally be abnormal. So try catch up, but that's ok. Because we have set the disconnection and reconnection, it will return to normal after a while
//create and return a new channel using (var channel = RabbitMqHelper.GetConnection().CreateModel()) { channel.QueueDeclare("test1", true, false, false, null); var properties = channel.CreateBasicProperties(); properties.Persistent = true; for (var i = 0; i < 10000; i++) { try { channel.BasicPublish(string.Empty, "test1", properties, Encoding.UTF8.GetBytes($"This is {i} messages")); Thread.Sleep(1000); Console.WriteLine($"Post message{i}"); } catch (Exception ex) { Console.WriteLine(ex.Message); i--;
} } }
After the program runs, it can be seen in the WEB UI. The master node is rabbitimq1, and the rest are slave nodes.
You can see that the node connected to now is rabbitmq2, and now we can hang it up manually
You can see that the application has been reporting errors, so it has been reported for a while, and then it continues to publish messages. This ensures the high availability and reliability of our message queue
PS: If you want to communicate with the technical experts in the industry, please join the qq group (527933790) or pay attention to the WeChat public account (AskHarries), thank you!