本部分主要介绍使用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,将其引用至项目中。
第二步:介绍几个概念
l 生产(Producing)意思就是发送。发送消息的程序就是一个生产者(producer)
l 队列(queue)就是邮箱的名称。消息通过你的应用程序和RabbitMQ进行传输,它们只能存储在队列(queue)中。 队列(queue)容量没有限制,你要存储多少消息都可以——基本上是一个无限的缓冲区。多个生产者(producers)能够把消息发送给同一个队列,同样,多个消费者(consumers)也能从同一个队列(queue)中获取数据
l 消费(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");
}

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

被折叠的 条评论
为什么被折叠?



