RabbitMQ安装和使用(二)

本文介绍了如何使用C#语言实现RabbitMQ消息队列的基本应用,包括消息的生产和消费流程,以及消息响应、持久化等高级特性。

本部分主要介绍使用C#语言使用RabbitMQ。

第一步:下载RabbitMQ的客户端程序集下载地址:http://www.rabbitmq.com/releases/rabbitmq-dotnet-client/v3.4.2/rabbitmq-dotnet-client-3.4.2-dotnet-3.5.zip

下载解压后获取RabbitMQ.Client.dll将其引用至项目中。

第二步:介绍几个概念

生产(Producing)意思就是发送。发送消息的程序就是一个生产者(producer)

队列(queue)就是邮箱的名称。消息通过你的应用程序和RabbitMQ进行传输,它们只能存储在队列(queue)中。 队列(queue)容量没有限制,你要存储多少消息都可以——基本上是一个无限的缓冲区。多个生产者(producers)能够把消息发送给同一个队列,同样,多个消费者(consumers)也能从同一个队列(queue)中获取数据

消费(Consuming)和获取消息是一样的意思。一个消费者(consumer)就是一个等待获取消息的程序

第三步:源码

包括两部分源码,源码都有注释,自己看,不多说

Consumer源码以及注释

namespace RabbitMQServer
{
    /// <summary>
    /// 此为消费者服务端端,包含接受处理消息,并告知客户端已经处理结束。
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                //创建目标,并将目标地址、用户名、密码记录
                var factory = new ConnectionFactory();
                factory.HostName = "XXX.XXX.XXX.XXX";
               factory.UserName = "XXX";
               factory.Password = "XXX";
                //建立实例连接
                var connection = factory.CreateConnection();
                //建立连接RabbitMQ通道
                var channel = connection.CreateModel();
                //创建队列“send”,用于接收客户端发送过来的信息,与客户端的发送队列同名
                channel.QueueDeclare("send",true,false,false,null);
                //创建队列“receive”,用于发送至客户端的信息,与客户端的接收队列同名
                channel.QueueDeclare("receive",true,false,false,null);
                //消息持久化
                var properties = channel.CreateBasicProperties();
                properties.SetPersistent(true);
                //用于接收消息
                var consumer = new QueueingBasicConsumer(channel);
                //第二个参数false表示需要回执给rabbitmq,否则rabbitmq一直保存
                channel.BasicConsume("send",false, consumer);
                Console.WriteLine(" waiting for message.");
                while (true)
                {
                    //接收消息并处理
                    var ea = (BasicDeliverEventArgs)consumer.Queue.Dequeue();
                    var body = ea.Body;
                    var message = Encoding.UTF8.GetString(body);
                    Console.WriteLine(DateTime.Now.ToString() +":Received {0}", message);
                    //消息处理完成后告诉客户端我已收到消息
                    var body1 = Encoding.UTF8.GetBytes("I have received the message");
                    channel.BasicPublish("","receive",null, body1);
                    Console.WriteLine(DateTime.Now.ToString() +" send:{0}","I have received the message");
                    //处理完了回执给rabbitmq,如果没有这行代码,RabbitMQ会一直存储这条消息
                    channel.BasicAck(ea.DeliveryTag, true);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                Console.ReadKey();
            }
        }
    }
}

Producer源码及注释:

namespace RabbitMQClient
{
    /// <summary>
    /// 此为生产者客户端,包含发送,确认接收。
    /// </summary>
    class Program
    {
        //连接RabbitMQ通道
        static IModel channel;
        //要发送的信息(二进制)
        static byte[] body1;
        //要发送的信息(字符串)
        static string message1;
        //接收确认信息
        static QueueingBasicConsumer consumer;
        static void Main(string[] args)
        {
            try
            {
                //创建目标,并将目标地址、用户名、密码记录
                var factory = new ConnectionFactory();
                factory.HostName = "XXX.XXX.XXX.XXX";
                factory.UserName = "XXX";
                factory.Password = "XXX";
                //建立实例连接
                var connection = factory.CreateConnection();
                //建立连接RabbitMQ通道
                channel = connection.CreateModel();
                //创建发送队列“send”,所有需要发送数据都通过这个队列
                channel.QueueDeclare("send",false,false,false,null);
                //创建接收队列“receive”,所有需要发送数据都通过这个队列
                channel.QueueDeclare("receive",false,false,false,null);
                //用于接收消息
                consumer = new QueueingBasicConsumer(channel);
                //需要发送的字符串
                message1 = "Hello tt";
                //将字符串转byte
                body1 = Encoding.UTF8.GetBytes(message1);
                //创建一个Timer,每隔十秒向RabbitMQ发送一次消息
                Timer SendMessageTimer =new Timer(SendMessage,null, 0, 10000);
                //开启一个线程,专门接收消息
                Thread thread = new Thread(delegate () { ReceiveMessage(); });
                thread.IsBackground = true;
                thread.Start();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            Console.ReadKey();
        }
        //发送RabbitMQ消息过程
        static void SendMessage(object o)
        {
            try
            {
                //向RabbitMQ发送消息,用send队列
                channel.BasicPublish("","send",null, body1);
                Console.WriteLine(DateTime.Now.ToString() +" send:{0}", message1);
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
        //接收RabbitMQ消息过程
        static void ReceiveMessage()
        {
            try
            {
                //第二个参数false表示需要回执给rabbitmq,否则rabbitmq一直保存
                channel.BasicConsume("receive",false, consumer);
                while (true)
                {
                    var ea = (BasicDeliverEventArgs)consumer.Queue.Dequeue();
                    var body = ea.Body;
                    var message = Encoding.UTF8.GetString(body);
                    Console.WriteLine(DateTime.Now.ToString() +":Received {0}", message);
                    //处理完了回执给rabbitmq,如果没有这行代码,RabbitMQ会一直存储这条消息
                    channel.BasicAck(ea.DeliveryTag, true);
                }
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
    }
}


运行后效果如下:

producer端:

 

consumer端:


此外,通过命令可以查看当前RabbitMQ未被处理的队列消息数量,如图:


第四部分:其他部分

1、消息响应

当处理一个比较耗时得任务的时候,我们想知道消费者(consumers)是否运行到一半就挂掉因此需要消息响应。具体由以上两行代码实现:

channel.BasicConsume("send",false, consumer);//第二个参数如果是true表示不需要消息响应,RabbitMQ将消息给customer后就不管了;false表示需要消息响应,配合下一行代码实现。

channel.BasicAck(ea.DeliveryTag, true);//处理完了回执给rabbitmq,如果没有这行代码,RabbitMQ会一直存储这条消息

2、消息持久化

消息响应保证了即使consumer都挂掉,消息还会在RabbitMQ中存储,若RabbitMQ与consumer都挂了该如何操作,需要持久化操作。通过几行代码实现:

channel.queueDeclare("receive", true, false, false, null);//第二个参数标记为false表示不持久化,true表示持久化,会通知RabbitMQ将信息存储在磁盘上。

var properties = channel.CreateBasicProperties();

properties.SetPersistent(true);

3、轮询分发

当开启多个consumer时,RabbitMQ会根据工作情况,将信息均匀分发给多个consumer。

4、生产者消息响应

可以采用conform模式完成生产者响应,生产者向RabbitMQ发送消息后,若RabbitMQ收到消息会给个反馈表示我收到了,具体代码示例为:

                channel.ConfirmSelect();
                //向RabbitMQ发送消息,用send队列
                channel.BasicPublish("", "send", null, body1);
                if(channel.WaitForConfirms())
                {
                    Console.WriteLine(DateTime.Now.ToString() + "Send sucess");
                }
                else
                {
                    Console.WriteLine(DateTime.Now.ToString() + "Send false");
                }


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值