Préface
Mode file d'attente de travail:
Un producteur, plusieurs consommateurs, chaque consommateur reçoit des messages uniques. Lorsque vous exécutez plusieurs threads de travail, ces messages sont partagés entre les threads de travail et interrogés par défaut. Autrement dit, le mode de file d'attente de travail est le même que le mode simple, sauf que le mode simple a un producteur et un consommateur, et le mode de file d'attente de travail a un producteur et plusieurs consommateurs.
Trois threads sont démarrés ici, à savoir producteur, consommateur 1 et consommateur 2. Les codes producteur et consommateur sont fondamentalement les mêmes que le mode simple précédent , avec de légères modifications
Atteindre
Producteur:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
static void Main ( string [] args) { // 1. Créer une fabrique de connexions ConnectionFactory factory = new ConnectionFactory () { HostName = " 127.0.0.1 " , UserName = " guest " , Password = " guest " }; // 2. Create connection var connection = factory.CreateConnection (); // 3. Create a pipe var channel =connection.CreateModel (); // 4. Canal de file d'attente déclarative.QueueDeclare ( " simple " , false , false , false , null ); for ( int i = 0 ; i < 20 ; i ++ ) { string msg = $ " 第 { i + 1} messages " ; // 5. Publier le message channel.BasicPublish ( " " , " simple " , null , Encoding.UTF8.GetBytes (msg)); Console.WriteLine ($ " 已 发送 消息 : {msg} " ); Thread.Sleep ( 1000 ); } channel.Close (); connection.Close (); Console.ReadKey (); }
Consommateurs 1, 2:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
static void Main ( string [] args) { // 初始化 工厂 ConnectionFactory factory = new ConnectionFactory () { HostName = " 127.0.0.1 " , UserName = " guest " , Password = " guest " }; // 创建 连接 en utilisant (IConnection connection = factory.CreateConnection ()) { using (IModel channel =connection.CreateModel ()) { // Déclarer le canal de file d' attente.QueueDeclare ( " simple " , false , false , false , null ); // Créer un objet consommateur var consumer = new EventingBasicConsumer (channel); consumer.Received + = (model , e) => { byte [] message = e.Body.ToArray (); Console.WriteLine ( " Recevoir le message: " +Encoding.UTF8.GetString (message)); // Renvoyer le message de confirmation channel.BasicAck (e.DeliveryTag, false ); }; // Le consommateur commence à écouter channel.BasicConsume ( " simple " , false , consumer); Console.ReadLine (); } } }
Le résultat
À ce moment, le consommateur P écrit un message dans la file d'attente, et le consommateur 1 et le consommateur 2 seront distribués équitablement, comme suit:
Vous pouvez voir qu'un consommateur reçoit des messages singuliers et un autre consommateur reçoit même des messages. Cette situation est due au fait que RabbitMQ commence à distribuer des messages après être entré dans la file d'attente. Il ne vérifie pas si chaque consommateur a le nombre de messages non confirmés, mais les distribue aveuglément à chaque consommateur de manière égale.
Planification des messages
Maintenant, nous changeons ce comportement et définissons BasicQos
Model.BasicQos (0,1, faux);
Cela signifie que RabbitMQ n'enverra pas de nouveaux messages à ce consommateur tant que le consommateur n'aura pas traité et confirmé le message précédent. Lorsque le message du consommateur 1 n'est pas confirmé, le consommateur 1 sera ignoré et envoyé au consommateur 2.
Le code de la consommation est maintenant comme ceci:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
static void Main ( string [] args) { // 初始化 工厂 ConnectionFactory factory = new ConnectionFactory () { HostName = " 127.0.0.1 " , UserName = " guest " , Password = " guest " }; // 创建 连接 en utilisant (IConnection connection = factory.CreateConnection ()) { using (IModel channel =connection.CreateModel ()) { // Déclarer le canal de file d' attente.QueueDeclare ( " simple " , false , false , false , null ); // Informer RabbitMQ qu'il ne distribuera plus au message s'il n'a pas reçu le signal de confirmation de message du Worker actuel Pour garantir une programmation équitable. channel.BasicQos (prefetchSize: 0 , prefetchCount: 1 , global : false ); // Créer un objet consommateur var consumer = new EventingBasicConsumer (channel); consumer.Received + = (model, e) => { byte [] message = e.Body.ToArray (); Console.WriteLine ( " Receive message: " + Encoding.UTF8.GetString (message)); // Renvoyer le message de confirmation channel.BasicAck (e.DeliveryTag, false ); }; // Le consommateur commence à écouter channel.BasicConsume ( " simple " , false , consumer); Console.ReadLine (); } } }
On peut voir que la réception de message actuelle consiste à envoyer des messages à tout consommateur inactif (le traitement est terminé et le message est confirmé), de sorte que la séquence de messages n'est plus qu'un consommateur reçoit des messages singuliers et qu'un consommateur reçoit même des messages.