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(扇出交换) ,并且有可能选 ...
随机推荐
- TOJ 3488 Game Dice
描述 In the game of Dungeons & Dragons, players often roll multi-sided dice to generate random num ...
- Notepad++的ftp远程编辑功能
我们主要来说说NppFTP的使用方法: 1.启动notepad++后,点击插件-->NppFTP-->Show NppFTP Window,就可以显示NppFTP的管理窗口了. 2.在Np ...
- 自己用 python 实现 base64 编码
自己用 python 实现 base64 编码 base64 编码原理 二进制文件中包含有很多无法显示和打印的字符,二进制的数据一般以 ASCII 码形式(8 bit,即一个字节)存储,8 bit 可 ...
- bzoj 3716: [PA2014]Muzeum
Description 吉丽的漫展有n件手办和m名警卫.建立平面直角坐标系,每个手办和警卫都可以看做一个点.警卫们的目光都朝着y轴负方向,且都有相同大小的视角.警卫可以看见自己视角内(包括边界上的点) ...
- js获取当前日期,格式为YYYY-MM-DD
//获取当前时间,格式YYYY-MM-DD function getNowFormatDate() { var date = new Date(); var seperator1 = "-& ...
- Java网络编程二--基于UDP的编程
DatagramSocket对象为基于UDP协议的Socket 构造器提供可以选择性绑定到指定端口和ip 创建完对象后调用:receive(DatagramPacket p) send(Dategra ...
- 什么是图像 -- opencv基础
opencv基础篇--到底什么是图像 什么是图像?英语中有两个单词来形容图像,一个是picture,一个是image.这两者虽然是形容同一个东西,但却又有着区别.picture代表实而有物的真实图像: ...
- ES6 克隆对象
浅克隆:只能克隆原始对象自身的值,不能克隆它继承的值 方法一: function clone(origin) { return Object.assign({}, origin); } 方法二: fu ...
- Windows无法启动MySQL服务,错误1067
问题:mysql服务启动异常 找出原因 检查D:\mysql-5.6.20-winx64\data目录下client-02.err文件的错误信息(以err为后缀名的文件是mysql的日志文件) 修改配 ...
- WPF - MVVM 之TreeView
在项目中使用OnPropertyChanged方法,最简单的实例: private event PropertyChangedEventHandler PropertyChanged; protect ...