事务消息与数据库的事务类似,只是MQ的消息是要保证消息是否会全部发送成功,防止消息丢失的一种策略。
  RabbitMQ有两种策略来解决这个问题:
  1.通过AMQP的事务机制实现
  2.使用生产者确认模式实现

  本文讲生产者确认模式。

1. 生产者

using RabbitMQMsgProducer.MessageProducer;
using Microsoft.Extensions.Configuration;
using System;
using System.IO;
using RabbitMQMsgProducer.ExchangeDemo;
using RabbitMQMsgProducer.MessageConfirm;

namespace RabbitMQMsgProducer
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                {
                    // 消息确认模式
                    ProducerMsgConfirm.Send();
                }
                Console.ReadLine();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}
using RabbitMQ.Client;
using System;
using System.Collections.Generic;
using System.Text;

namespace RabbitMQMsgProducer.MessageConfirm
{
    public class ProducerMsgConfirm
    {
        public static void Send()
        {
            ConnectionFactory factory = new ConnectionFactory();
            factory.HostName = "localhost";//服务地址
            factory.UserName = "guest";//用户名
            factory.Password = "guest";//密码 
            string queueName = "MsgConfirmQueue01";
            string exchangeName = "MsgConfirmExchange";
            string routingKeyName = "MsgConfirmRoutingKey";
            using (var connection = factory.CreateConnection())
            {
                using (var channel = connection.CreateModel())
                {
                    Console.WriteLine("the producer is ready . GO !");
                    channel.QueueDeclare(queue: queueName, durable: true, exclusive: false, autoDelete: false, arguments: null);
                    //声明交换机exchange
                    channel.ExchangeDeclare(exchange: exchangeName, type: ExchangeType.Direct, durable: true, autoDelete: false, arguments: null);
                    //绑定exchange和queue
                    channel.QueueBind(queue: queueName, exchange: exchangeName, routingKey: routingKeyName);
                    string message = "";
                    while (true)
                    {
                        message = Console.ReadLine();
                        bool isOk = message.Equals("quit", StringComparison.CurrentCultureIgnoreCase);
                        if (isOk) { break; }
                        var body = Encoding.UTF8.GetBytes(message);
                        try
                        {
                            //开启消息确认模式
                            channel.ConfirmSelect();
                            //发送消息
                            channel.BasicPublish(exchange: exchangeName, routingKey: routingKeyName, basicProperties: null, body: body);
                            if (channel.WaitForConfirms()) //如果一条消息或多消息都确认发送
                            {
                                Console.WriteLine($"the msg : _ {message} _ is send to broker . success .");
                            }
                            else
                            {
                                //可以记录个日志,重试一下,找个重试代码或者中间件;
                            }
                            channel.WaitForConfirmsOrDie();//如果所有消息发送成功 就正常执行;如果有消息发送失败;就抛出异常;
                        }
                        catch (Exception)
                        {
                            Console.WriteLine($"the msg : _ {message} _ is send to broker . fail .");
                        }
                    }
                    Console.Read();
                }
            }
        }
    }
}

 

2. 结果

 

 

 

posted on 2021-01-18 19:48  Fletcher  阅读(150)  评论(0编辑  收藏  举报