NET下RabbitMQ实践[示例篇]
在上一篇文章中,介绍了在window环境下安装erlang,rabbitmq-server,以免配置用户,权限,虚拟机等内容。
今天将会介绍如果使用rabbitmq进行简单的消息入队,出队操作,因为本文演示的环境要用到上文中配置的环境,所以要运行本文sample,请先按上一篇中完成相应环境配置。
首先,我们下载官方的.net客户端软件,链接:http://www.rabbitmq.com/dotnet.html
下载并安装之后,将安装目录下的这两个DLL文件复制到我们示例项目中,并添加引用:
RabbitMQ.Client.dll //基于的发布订阅消息的功能类
RabbitMQ.ServiceModel.dll //包括基于WCF方式发布订阅服务模型类
如下图:

接着,我们创建两个类,一个是ProducerMQ.cs(用于产生消息),一个是CustmerMq.cs(用于消费消息),代码如下:
首先是ProducerMQ:
public class ProducerMQ
{
public static void InitProducerMQ()
{
Uri uri = new Uri("amqp://10.0.4.85:5672/");
string exchange = "ex1";
string exchangeType = "direct";
string routingKey = "m1";
bool persistMode = true;
ConnectionFactory cf = new ConnectionFactory();
cf.UserName = "daizhj";
cf.Password = "617595";
cf.VirtualHost = "dnt_mq";
cf.RequestedHeartbeat = 0;
cf.Endpoint = new AmqpTcpEndpoint(uri);
using (IConnection conn = cf.CreateConnection())
{
using (IModel ch = conn.CreateModel())
{
if (exchangeType != null)
{
ch.ExchangeDeclare(exchange, exchangeType);//,true,true,false,false, true,null);
ch.QueueDeclare("q1", true);//true, true, true, false, false, null);
ch.QueueBind("q1", "ex1", "m1", false, null);
}
IMapMessageBuilder b = new MapMessageBuilder(ch);
IDictionary target = b.Headers;
target["header"] = "hello world";
IDictionary targetBody = b.Body;
targetBody["body"] = "daizhj";
if (persistMode)
{
((IBasicProperties)b.GetContentHeader()).DeliveryMode = 2;
}
ch.BasicPublish(exchange, routingKey,
(IBasicProperties)b.GetContentHeader(),
b.GetContentBody()); }
}
}
}
下面对上面代码进行说明:
1. 定义要链接的rabbitmq-server地址(基于amqp协议):
Uri uri = new Uri("amqp://10.0.4.85:5672/");
2. 定义交换方式
string exchange = "ex1";
string exchangeType = "direct";
string routingKey = "m1";
说明:rabbitmq交换方式分为三种,分别是:
Direct Exchange – 处理路由键。需要将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全匹配。这是一个完整的匹配。如果一个队列绑定到该交换机上要求路由键 “dog”,则只有被标记为“dog”的消息才被转发,不会转发dog.puppy,也不会转发dog.guard,只会转发dog。
Fanout Exchange – 不处理路由键。你只需要简单的将队列绑定到交换机上。一个发送到交换机的消息都会被转发到与该交换机绑定的所有队列上。很像子网广播,每台子网内的主机都获得了一份复制的消息。Fanout交换机转发消息是最快的。
Topic Exchange – 将路由键和某模式进行匹配。此时队列需要绑定要一个模式上。符号“#”匹配一个或多个词,符号“*”匹配不多不少一个词。因此“audit.#”能够匹配到“audit.irs.corporate”,但是“audit.*” 只会匹配到“audit.irs”。
更多内容参见:RabbitMQ 三种Exchange
3. 是否对消息队列持久化保存
bool persistMode = true;
4. 使用ConnectionFactory创建连接,虽然创建时指定了多个server address,但每个connection只与一个物理的server进行连接。
ConnectionFactory cf = new ConnectionFactory();
//使用前文的配置环境信息
cf.UserName = "daizhj";
cf.Password = "617595";
cf.VirtualHost = "dnt_mq";
cf.RequestedHeartbeat = 0;
cf.Endpoint = new AmqpTcpEndpoint(uri);
5. 实例化IConnection对象,并设置交换方式
using (IConnection conn = cf.CreateConnection())
{
using (IModel ch = conn.CreateModel())
{
if (exchangeType != null)
{
ch.ExchangeDeclare(exchange, exchangeType);//,true,true,false,false, true,null);
ch.QueueDeclare("q1", true);//true, true, true, false, false, null);
ch.QueueBind("q1", "ex1", "m1", false, null);
}
....
6. 构造消息实体对象并发布到消息队列上:
IMapMessageBuilder b = new MapMessageBuilder(ch);
IDictionary target = b.Headers;
target["header"] = "hello world";
IDictionary targetBody = b.Body;
targetBody["body"] = "daizhj";
if (persistMode)
{
((IBasicProperties)b.GetContentHeader()).DeliveryMode = 2;
}
//简单发布方式
ch.BasicPublish(exchange, routingKey,
(IBasicProperties)b.GetContentHeader(),
b.GetContentBody());
这样就完成了单条消息的发布。
下面是CustmerMq.cs(用于消费消息)实例代码:
public class CustmerMq
{
public static int InitCustmerMq()
{
string exchange = "ex1";
string exchangeType = "direct";
string routingKey = "m1"; string serverAddress = "10.0.4.85:5672";
ConnectionFactory cf = new ConnectionFactory();
cf.Address = serverAddress;
cf.UserName = "daizhj";
cf.Password = "617595";
cf.VirtualHost = "dnt_mq";
cf.RequestedHeartbeat = 0;
可以看出上面的代码与 ProducerMQ的开头代码类似,下面使用ConnectionFactory来构造链接并接收队列消息:
using (IConnection conn = cf.CreateConnection())
{
using (IModel ch = conn.CreateModel())
{
//普通使用方式BasicGet
//noAck = true,不需要回复,接收到消息后,queue上的消息就会清除
//noAck = false,需要回复,接收到消息后,queue上的消息不会被清除,直到调用channel.basicAck(deliveryTag, false); queue上的消息才会被清除 而且,在当前连接断开以前,其它客户端将不能收到此queue上的消息
BasicGetResult res = ch.BasicGet("q1", false/*noAck*/);
if (res != null)
{
bool t = res.Redelivered;
t = true;
Console.WriteLine(System.Text.UTF8Encoding.UTF8.GetString(res.Body));
ch.BasicAck(res.DeliveryTag, false);
}
else
{
Console.WriteLine("No message!");
}
上面代码比较简单,主要是使用BasicGetResult来进行简单的消息接收,并使用BasicAck方式来告之是否从队列中移除该条消息。这一点很重要,因为在某些应用场景下,比如从队列中获取消息并用它来操作数据库或日志文件时,如果出现操作失败时,则该条消息应该保留在队列中,只到操作成功时才从队列中移除。
当然上面操作只是用于单条数据操作,如果要遍历队列中所有消息,则需要使用如下方式:
while (true)
{
BasicGetResult res = ch.BasicGet("q1", false/*noAck*/);
if (res != null)
{
try
{
bool t = res.Redelivered;
t = true;
Console.WriteLine(System.Text.UTF8Encoding.UTF8.GetString(res.Body));
ch.BasicAck(res.DeliveryTag, false);
}
catch { }
}
else
break;
}
另外,在rabbitmq中,获取消息可以使用两种方式,一种是上面提到的主动获取,另一种是基于订阅模式,即让当前获取消息的线程阻塞,用于绑定到指定的队列上,当有新的消息入队之后,该阻塞线程会被运行,从队列中获取新入队的消息,形如:
//第二种取法QueueingBasicConsumer基于订阅模式
QueueingBasicConsumer consumer = new QueueingBasicConsumer(ch);
ch.BasicConsume("q1", false, null, consumer);
while (true)
{
try
{
BasicDeliverEventArgs e = (BasicDeliverEventArgs)consumer.Queue.Dequeue();
IBasicProperties props = e.BasicProperties;
byte[] body = e.Body;
Console.WriteLine(System.Text.Encoding.UTF8.GetString(body));
//ch.BasicAck(e.DeliveryTag, true);
ProcessRemainMessage();
}
catch (EndOfStreamException ex)
{
//The consumer was removed, either through channel or connection closure, or through the action of IModel.BasicCancel().
Console.WriteLine(ex.ToString());
break;
}
}
这样,就完成了一个简单的发布,消费消息的示例。在接下来的文章中,将会介绍如果基于WCF来发布RABBITMQ服务,敬请关注:)
NET下RabbitMQ实践[示例篇]的更多相关文章
- NET下RabbitMQ实践[配置篇]
这个系列目前计划写四篇,分别是配置,示例,WCF发布,实战.当然不排除加餐情况. 介绍: rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.他遵循Mozilla Publi ...
- NET下RabbitMQ实践[实战篇]
之前的文章中,介绍了如何将RabbitMQ以WCF方式进行发布.今天就介绍一下我们产品中如何使用RabbitMQ的! 在Discuz!NT企业版中,提供了对HTTP错误日志的记录功能 ...
- NET下RabbitMQ实践[WCF发布篇]
在之前的两篇文章中,主要介绍了RabbitMQ环境配置,简单示例的编写.今天将会介绍如何使用WCF将RabbitMQ列队以服务的方式进行发布. 注:因为RabbitMQ的官方.net ...
- 实践详细篇-Windows下使用VS2015编译的Caffe训练mnist数据集
上一篇记录的是学习caffe前的环境准备以及如何创建好自己需要的caffe版本.这一篇记录的是如何使用编译好的caffe做训练mnist数据集,步骤编号延用上一篇 <实践详细篇-Windows下 ...
- 实践详细篇-Windows下使用Caffe训练自己的Caffemodel数据集并进行图像分类
三:使用Caffe训练Caffemodel并进行图像分类 上一篇记录的是如何使用别人训练好的MNIST数据做训练测试.上手操作一边后大致了解了配置文件属性.这一篇记录如何使用自己准备的图片素材做图像分 ...
- Python操作rabbitmq 实践笔记
发布/订阅 系统 1.基本用法 生产者 import pika import sys username = 'wt' #指定远程rabbitmq的用户名密码 pwd = ' user_pwd = p ...
- Tree-Shaking性能优化实践 - 原理篇
Tree-Shaking性能优化实践 - 原理篇 一. 什么是Tree-shaking 先来看一下Tree-shaking原始的本意 上图形象的解释了Tree-shaking 的本意,本文所说的前 ...
- 消息队列那么多,为什么建议深入了解下RabbitMQ?
你为啥要在项目中选择xxx消息中间件? 提起消息队列,也许你的脑海里会不自觉地蹦出好多概念:JMS.Kafka.RocketMQ.AMQP.RabbitMQ.ActiveMQ.Pulsar.Redis ...
- Spring Boot 2.x 快速入门(下)HelloWorld示例详解
上篇 Spring Boot 2.x 快速入门(上)HelloWorld示例 进行了Sprint Boot的快速入门,以实际的示例代码来练手,总比光看书要强很多嘛,最好的就是边看.边写.边记.边展示. ...
随机推荐
- 如何将无线路由器作为交换机,将光猫(路由器A)分出来的一条网线接到自家另一台路由器B上,最大化利用网络资源
从隔壁邻居只接了一条网线过来,由于无线网络的距离有限,不能覆盖到家里任何角落,然而,我又想家里一台台式电脑和无线设备都能够连接wifi进行上网。 摸索了一个上午,知道将家里的无线路由器B当作一个无线A ...
- oracle查询和设置过期时间
第一步:找到oracle 打开enterprise Manager Console如下图: 第二步,找到概要文件: sys 用户进入,找到你的数据库(如:ora8)-“安全性”-"用户&qu ...
- Jplayer(转)
Jplayer必须要加载 1.样式 jplayer.blue.monday.css 2.jq jquery.1.6.2.min.js 当前最新版本为1.6.2 3.jplayer的js jquery ...
- 后台字符串转化成json
function remotecontrol() { var progressbar = $("#progressbar"); $.ajax({ url: myurl, type: ...
- hdu 4707 Pet(DFS水过)
http://acm.hdu.edu.cn/showproblem.php?pid=4707 [题目大意]: Lin Ji 的宠物鼠丢了,在校园里寻找,已知Lin Ji 在0的位置,输入N D,N表示 ...
- 使用Yeoman搭建 AngularJS 应用 (6) —— 让我们搭建一个网页应用
原文地址:http://yeoman.io/codelab/review-generated-files.html 打开mytodo文件夹,你会看到现在的基架.如下图所示 在mytodo文件夹,我们能 ...
- asp.net中js和jquery调用ashx的不同方法分享
代码如下: var xhr = new XMLHttpRequest(); xhr.open("get", 'Controls/gengCart.ashx?C ...
- The 9th Zhejiang Provincial Collegiate Programming Contest->Problem A:A - Taxi Fare
Problem A: Taxi Fare Time Limit: 2 Seconds Memory Limit: 65536 KB Last September, Hangzhou raised th ...
- The 5th Zhejiang Provincial Collegiate Programming Contest------ProblemA:Accurately Say "CocaCola"!
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2965 题意:一群人玩过“7”的游戏,有7的数字或者7的倍数就要喊“coca ...
- Window8 进不了PE如何设置BIOS
如题,如今进入Win8时代,很多新出的机器都自带了WIN8.但是童鞋们想进PE进行操作的时候,发现进不了. 更改BIOS以下2处设置,即可使用第三方引导安装系统:Boot->Launch CSM ...