RabbitMQ .NET Client 实战实验
由于公司业务需求,最近想上RabbitMQ,之前我研究了一段时间微软的MSMQ。开源队列有很多,各有优劣。就先拿RabbitMQ练练手吧。本篇着重代码部分,至于怎么安装,怎么配置不在赘述。而且代码是在RabbitMQ.NET Client 类库基础上实现。
假设阅读本文的人已经安装好RabbitMQ并且做了相应的用户配置。而且项目中已经从nuget安装了rabbitmq.client.dll.我们开始做一个简单的队列发送和接收消息。
- 将需要配置的东西放在配置文件里,例如主机地址,端口,用户名,密码等。
- 实现消息发送端:Product
- 实现消息接收端:Customer
- Demo测试
将以下内容作为可配置部分放在配置文件中
<appSettings>
<!--RabbitMQ-->
<add key="RabbitMQ_HostUri" value="amqp://192.168.1.119:5672/"/>
<add key="RabbitMQ_HostName" value="192.168.1.119"/>
<add key="RabbitMQ_UserName" value="test_user"/>
<add key="RabbitMQ_Password" value=""/>
<add key="RabbitMQ_VirtualHost" value="ms_mq"/>
</appSettings>
由于只是对RabbitMQ.Client.dll中的又一次封装,所以代码不过多解释,其中要注意的就是某些配置问题,例如是否持久化,消息处理模式是怎么样的等等。
首先我们创建一个连接工厂:
public ConnectionFactory CreateFactory()
{
if (_factory == null) { const ushort heartbeat = ;
//主机地址
Uri uri = new Uri(RabbitMQConfig.HostUri); _factory = new ConnectionFactory();
//_factory.HostName = RabbitMQConfig.HostName;
//用户名
_factory.UserName = RabbitMQConfig.UserName;
//密码
_factory.Password = RabbitMQConfig.PassWord;
//虚拟主机名
_factory.VirtualHost = RabbitMQConfig.VirtualHost;
//连接终端
_factory.Endpoint = new AmqpTcpEndpoint(uri); _factory.RequestedHeartbeat = heartbeat;
//自动重连
_factory.AutomaticRecoveryEnabled = true;
}
return _factory;
}
一个简单的消息发布:(对代码研究不够透彻,只能一切从简~~)
public void Publish(string message, string queueName=null)
{
if (queueName == null) {
queueName = _queueName;
} var factory = RabbitMQFactory.Instance.CreateFactory();
using (var connection = factory.CreateConnection())
{
using (var model = connection.CreateModel())
{
//消息持久化,防止丢失
model.QueueDeclare(queueName, RabbitMQConfig.IsDurable, false, false, null);
var properties = model.CreateBasicProperties();
properties.Persistent = RabbitMQConfig.IsDurable;
properties.DeliveryMode = ; //消息转换为二进制
var msgBody = Encoding.UTF8.GetBytes(message);
//消息发出到队列
model.BasicPublish("", queueName, properties, msgBody);
}
}
}
消息接收:
public void Consume() {
var factory = RabbitMQFactory.Instance.CreateFactory();
var connection = factory.CreateConnection();
connection.ConnectionShutdown += Connection_ConnectionShutdown;
ListenChannel = connection.CreateModel();
bool autoDeleteMessage = false;
var queue = ListenChannel.QueueDeclare(_queueName, RabbitMQConfig.IsDurable, false, false, null);
//公平分发,不要同一时间给一个工作者发送多于一个消息
ListenChannel.BasicQos(, , false);
//创建事件驱动的消费者类型,不要用下边的死循环来消费消息
var consumer = new EventingBasicConsumer(ListenChannel);
consumer.Received += Consumer_Received;
//消费消息
ListenChannel.BasicConsume(_queueName, autoDeleteMessage, consumer);
}
我在Customer中定义了一个 ReceiveMessageCallback Func回调,这里就是当客户端从队列接收到消息之后,怎么处理由客户端来决定
public Func<string, bool> ReceiveMessageCallback { get; set; }
处理消息:
private void Consumer_Received(object sender, BasicDeliverEventArgs args) {
try {
var body = args.Body;
var message = Encoding.UTF8.GetString(body);
//将消息业务处理交给外部业务
bool result = ReceiveMessageCallback(message);
if (result) {
if (ListenChannel != null && !ListenChannel.IsClosed) {
ListenChannel.BasicAck(args.DeliveryTag, false);
}
}
else {
}
}
catch (Exception ex) {
throw ex;
}
}
基本代码已经完成,我们写一个测试,消息发送端:
static void Main(string[] args)
{
var testQueueName = "test";
IMessageProduct product = new MessageProduct(testQueueName);
for (int i = ; i < ; i++)
{
Console.WriteLine("正在发送第" + i + "条消息...");
product.Publish("消息体" + i);
} Console.Read();
}
消息接收端:(开多个口接收)
static void Main(string[] args)
{ Parallel.For(, RabbitMQConfig.ThreadCount, i =>
{
IMessageCustomer customer = new MessageCustomer("test");
//开始监听
customer.StartListening();
customer.ReceiveMessageCallback = message =>
{
//客户端处理消息(打印)
Console.WriteLine("接收到消息:" + message);
return true;
};
});
Console.Read();
}
打开发送消息端:

打开消息接收端:

到此为止,RabbitMQ队列的简单测试就完成了,没有介绍什么新知识,基本就是套DLL中的方法,不过也有很多不合理的地方,如果真正应用到项目中,还需要多加测试和修改。
DEMO地址:https://github.com/fanpan26/RabbitMQ.NETClient
RabbitMQ .NET Client 实战实验的更多相关文章
- RabbitMQ 整合 SpringCloud实战
RabbitMQ 整合 SpringCloud实战RabbitMQ 整合 SpringCloud实战rabbitmq-common 子项目rabbitmq-springcloud-consumer 子 ...
- C# RabbitMQ优先级队列实战项目演练
一.需求背景 当用户在商城上进行下单支付,针对客户等级的不同和订单金额的大小划分客户级别,需要优先处理给标识为大订单的客户发送一份订单邮件提醒.那么我们应用程序如何解决这样的需求场景呢?今天阿笨给大家 ...
- 译:1. RabbitMQ Java Client 之 "Hello World"
这些教程介绍了使用RabbitMQ创建消息传递应用程序的基础知识.您需要安装RabbitMQ服务器才能完成教程 1. 打造第一个Hello World 程序 RabbitMQ是一个消息代理:它接受和转 ...
- 五、RabbitMQ Java Client基本使用详解
Java Client的5.x版本系列需要JDK 8,用于编译和运行.在Android上,仅支持Android 7.0或更高版本.4.x版本系列支持7.0之前的JDK 6和Android版本. 加入R ...
- rabbitmq - java client lib一二事
由于不可抗因素, 需要给对接方撸一个client的demo.基于比较老的jdk. 所幸找到了这里:http://www.rabbitmq.com/releases/rabbitmq-java-clie ...
- 译:2. RabbitMQ Java Client 之 Work Queues (工作队列)
在上篇揭开RabbitMQ的神秘面纱一文中,我们编写了程序来发送和接收来自命名队列的消息. 本篇我们将创建一个工作队列,工作队列背后的假设是每个任务都交付给一个工作者 本篇是译文,英文原文请移步:ht ...
- 译:3.RabbitMQ Java Client 之 Publish/Subscribe(发布和订阅)
在上篇 RabbitMQ 之Work Queues (工作队列)教程中,我们创建了一个工作队列,工作队列背后的假设是每个任务都交付给一个工作者. 在这一部分,我们将做一些完全不同的事情 - 我们将向多 ...
- 译:4.RabbitMQ Java Client 之 Routing(路由)
在上篇博文 译:3.RabbitMQ 之Publish/Subscribe(发布和订阅) 我们构建了一个简单的日志系统 我们能够向许多接收者广播日志消息. 在本篇博文中,我们将为其添加一个功能 - ...
- 译:5.RabbitMQ Java Client 之 Topics (主题)
在 上篇博文 译:4.RabbitMQ 之Routing(路由) 中,我们改进了日志系统. 我们使用的是direct(直接交换),而不是使用只能进行虚拟广播的 fanout(扇出交换) ,并且有可能选 ...
随机推荐
- oracle 错误实例分析(ORA-01126)
问题描述 SQL> shutdown immediate ORA-01109: database not open Database dismounted. ORACLE instance sh ...
- git安装以及webstorm配置git
下载及安装请移步 https://www.cnblogs.com/specter45/p/github.html 用webstorm上传代码时,首先要先下载git,网址一搜就可以搜到,然后开始配置 ...
- journalctl 中文手册
版权声明 本文译者是一位开源理念的坚定支持者,所以本文虽然不是软件,但是遵照开源的精神发布. 无担保:本文译者不保证译文内容准确无误,亦不承担任何由于使用此文档所导致的损失. 自由使用:任何人都可以自 ...
- connection reset by peer, socket write error问题排查
2018-03-15更新:弄明白connection reset产生的原因,见重新分析connection reset by peer, socket write error错误原因 在开发文件上传功 ...
- nyoj 211——Cow Contest——————【floyd传递闭包】
Cow Contest 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 N (1 ≤ N ≤ 100) cows, conveniently numbered 1.. ...
- 从数组去重这个函数来体验es6的高效率
前几天碰到一个题目,要求是这样的. 题目描述 为 Array 对象添加一个去除重复项的方法 示例1 输入 [false, true, undefined, null, NaN, 0, 1, {}, { ...
- c#-FrameWork02泛型
泛型 l 泛型(generic)编程是一种编程范式,它利用”参数化类型”将类型抽象化,从而可以实现更为灵活的复用.把数据类型参数化 sh泛型集合 泛型集合与集合的对比 泛型集合类 非泛型集合类 Li ...
- 关于IQueryable和IEnumerable
园里对这两个已经有很多文章作了深入的介绍,我总结些,当成笔记用. 一.具体判断用哪个上,如果是运行在本地内存中的,用IEnumerable,枚举该对象时,会立即反应查询结果. 如果是远程数据源,比如数 ...
- JavaScript数组常用操作总结
我们在日常开发过程中,使用到原生 JavaScript的时候,有时候会频繁的对数组进行操作,今天我把工作以来,经常用到的有关 JavaScript数组的方法总结一下,方便日后工作的时候查找使用! 一. ...
- python私有成员
在一个模块中,我们可能会定义很多函数和变量,但有的函数和变量我们希望给别人使用,有的函数和变量我们希望仅仅在模块内部使用.在Python中,是通过_前缀来实现的. 正常的函数和变量名是公开的(publ ...