asp.net 使用rabbitmq事例
本例asp.net 使用rabbitmq需求背景:为了提升用户体验,用户点击下单按钮,后台先做一些简单必要的操作,返回给用户一个友好提示(比如提示处理中,或者订单状态为处理中),然后发通过发消息给队列,把耗时久的操作留给rabbitmq队列处理。
1、生产者封装类:
public class Publisher
{
private readonly string _exchange;
private readonly string _hostName;
private readonly string _password;
private readonly Uri _uri;
private readonly string _userName;
private readonly string _virtualHost; /// <param name="exchange"></param>
/// <param name="hostName"></param>
/// <param name="userName"></param>
/// <param name="password"></param>
/// <param name="virtualHost"></param>
/// <param name="uri">AMQP Address</param>
public Publisher(string exchange, string hostName, string userName, string password, string virtualHost, Uri uri)
{
_hostName = hostName;
_exchange = exchange;
_userName = userName;
_password = password;
_virtualHost = virtualHost;
_uri = uri; Factory = new ConnectionFactory
{
HostName = _hostName,
UserName = _userName,
Password = _password,
VirtualHost = _virtualHost,
Endpoint = new AmqpTcpEndpoint(_uri),
RequestedHeartbeat =
};
Factory.RequestedHeartbeat = ;
} public string HostName
{
get { return _hostName; }
} public string Exchange
{
get { return _exchange; }
} public string UserName
{
get { return _userName; }
} public string Password
{
get { return _password; }
} public string VirtualHost
{
get { return _virtualHost; }
} public Uri Uri
{
get { return _uri; }
} public ConnectionFactory Factory { get; private set; } /// <summary>
/// 直连式交换机,发消息
/// </summary>
/// <param name="queueName">队列名</param>
/// <param name="message">消息</param>
/// <param name="durable">消息是否持久化</param>
public void PublishDirectMessage(string queueName, string message, bool durable=false)
{
if (null == Factory)
{
throw new ArgumentException("connection factory initialization error");
} if (string.IsNullOrWhiteSpace(message))
{
throw new ArgumentNullException("message can not be null.");
} if (string.IsNullOrWhiteSpace(Exchange))
{
throw new ArgumentNullException("exchange can not be null.");
} try
{
using (var connection = Factory.CreateConnection())
{
//通道 (Channel),在C#客户端里叫Model(不明白为什么这么取名字),其他客户端基本都叫Channel
using (var channel = connection.CreateModel())
{
//定义交换机
channel.ExchangeDeclare(Exchange, ExchangeType.Direct, durable: durable,
autoDelete: false, arguments: null); //定义队列,如果名称相同不会重复创建
channel.QueueDeclare(queueName, durable: durable, exclusive: false,
autoDelete: false, arguments: null); //绑定
channel.QueueBind(queueName, Exchange, routingKey: queueName); //消息可持久化
IBasicProperties props = null;
if (durable) {
props = channel.CreateBasicProperties();
props.SetPersistent(true);
} //发送消息到队列
var msgBody = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(Exchange, routingKey: queueName, basicProperties: props,
body: msgBody);
}
}
}
catch (Exception ex)
{
LogHelper.Log(LogCategory.Error, ex.Message, ex);
}
} /// <summary>
/// Fanout(广播)式交换机
/// </summary>
/// <param name="message"></param>
public void PublishFanoutMessage(string message)
{
if (null == Factory)
{
throw new ArgumentException("connection factory initialization error");
} if (string.IsNullOrWhiteSpace(message))
{
throw new ArgumentNullException("message can not be null.");
} if (string.IsNullOrWhiteSpace(Exchange))
{
throw new ArgumentNullException("exchange can not be null.");
} try
{
using (var connection = Factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
channel.ExchangeDeclare(Exchange, ExchangeType.Fanout);
byte[] body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(Exchange, "", null, body);
}
}
}
catch (Exception ex)
{
LogHelper.Log(LogCategory.Error, ex.Message, ex);
}
}
}
生产者
2、消费者封装类:
public delegate void ReceiveMessageHandle(string inputStr);
public delegate bool ReceiveAnswerMessageHandle(string inputStr); /// <typeparam name="T">要接收的数据类型</typeparam>
public class Subscriber<T> : IDisposable
{
private readonly string _exchange;
private readonly string _hostName;
private readonly string _password;
private readonly Uri _uri;
private readonly string _userName;
private readonly string _virtualHost; /// <param name="exchange"></param>
/// <param name="hostName"></param>
/// <param name="userName"></param>
/// <param name="password"></param>
/// <param name="virtualHost"></param>
/// <param name="uri">AMQP Address</param>
public Subscriber(string exchange, string hostName, string userName, string password, string virtualHost,
Uri uri)
{
_hostName = hostName;
_exchange = exchange;
_userName = userName;
_password = password;
_virtualHost = virtualHost;
_uri = uri; Factory = new ConnectionFactory
{
HostName = _hostName,
UserName = _userName,
Password = _password,
VirtualHost = _virtualHost,
Endpoint = new AmqpTcpEndpoint(_uri),
RequestedHeartbeat =
}; Connection = Factory.CreateConnection();
Channel = Connection.CreateModel();
} public string HostName
{
get { return _hostName; }
} public string Exchange
{
get { return _exchange; }
} public string UserName
{
get { return _userName; }
} public string Password
{
get { return _password; }
} public string VirtualHost
{
get { return _virtualHost; }
} public Uri Uri
{
get { return _uri; }
} public ConnectionFactory Factory { get; private set; } public IModel Channel { get; private set; }
public IConnection Connection { get; private set; }
public EventingBasicConsumer Consumer { get; private set; } private string QueueName { get; set; } public string Message { get; set; } //public delegate string MessageHandle(); /// <summary>
/// 手动释放
/// </summary>
void IDisposable.Dispose()
{
if (Channel != null)
{
Consumer = null;
Channel.Close();
Channel.Dispose();
} if (Connection != null)
{
Consumer = null;
Connection.Close();
Connection.Dispose();
} GC.SuppressFinalize(this);
} /// <summary>
/// 托管释放
/// </summary>
~Subscriber()
{
if (Channel != null)
{
Consumer = null;
Channel.Close();
Channel.Dispose();
} if (Connection != null)
{
Consumer = null;
Connection.Close();
Connection.Dispose();
}
} public ReceiveMessageHandle ReceiveMessageHandler { get; set; }
public ReceiveAnswerMessageHandle ReceiveAnswerMessageHandle { get; set; } /// <summary>
/// 接受广播消息
/// <param name="tryTimes">消费失败后,继续尝试消费的次数</param>
/// </summary>
public void ReceiveFanoutMessage(int tryTimes = )
{
try
{
//Channel.ExchangeDeclare(Exchange, ExchangeType.Fanout);
//QueueName = Channel.QueueDeclare().QueueName;
//Channel.QueueBind(QueueName, Exchange, "");
//Consumer = new EventingBasicConsumer(Channel);
//Consumer.Received += (model, dlvrArgs) =>
//{
// byte[] body = dlvrArgs.Body;
// Message = Encoding.UTF8.GetString(body);
// ReceiveMessageHandler(Message);
//};
//Channel.BasicConsume(QueueName, true, Consumer); Channel.ExchangeDeclare(Exchange, ExchangeType.Fanout);
QueueName = Channel.QueueDeclare().QueueName;
Channel.QueueBind(QueueName, Exchange, "");
Consumer = new EventingBasicConsumer(Channel);
Consumer.Received += (model, dlvrArgs) =>
{
byte[] body = dlvrArgs.Body;
if (body != null && body.Length > )
{
Message = Encoding.UTF8.GetString(body);
if (!string.IsNullOrWhiteSpace(Message))
{
bool isConsumeSuccess = false;// 是否消费成功
int consumeCount = ;//尝试消费次数
while (!isConsumeSuccess)
{
consumeCount++;
isConsumeSuccess = ReceiveAnswerMessageHandle(Message);
if (isConsumeSuccess || consumeCount >= tryTimes)
{
Channel.BasicAck(dlvrArgs.DeliveryTag, false);//将队列里面的消息进行释放
isConsumeSuccess = true;
}
else
{
//重新放入队列,等待再次消费
Channel.BasicAck(dlvrArgs.DeliveryTag, true);
}
}
}
}
};
Channel.BasicConsume(QueueName, false, Consumer);
}
catch (Exception ex)
{
LogHelper.Log(LogCategory.Error, ex.Message, ex);
}
} /// <summary>
/// 接受直连交换机消息
/// </summary>
/// <param name="queueName">队列名</param>
/// <param name="durable">消息是否持久化</param>
/// <param name="tryTimes">消费失败后,继续尝试消费的次数</param>
/// <returns></returns>
public void ReceiveDirectMessage(string queueName, bool durable = false, int tryTimes = )
{
try
{
Channel.ExchangeDeclare(Exchange, ExchangeType.Direct, durable: durable, autoDelete: false, arguments: null);
Channel.QueueDeclare(queueName, durable: durable, exclusive: false, autoDelete: false, arguments: null);
Channel.QueueBind(queueName, Exchange, routingKey: queueName);
//订阅模式 (有消息到达将被自动接收) 消费者
Consumer = new EventingBasicConsumer(Channel);
//绑定消息接收后的事件委托
Consumer.Received += (model, dlvrArgs) =>
{
byte[] body = dlvrArgs.Body;
if (body != null && body.Length > )
{
Message = Encoding.UTF8.GetString(body);
if (!string.IsNullOrWhiteSpace(Message))
{
bool isConsumeSuccess = false;// 是否消费成功
int consumeCount = ;//尝试消费次数
while (!isConsumeSuccess)
{
consumeCount++;
isConsumeSuccess = ReceiveAnswerMessageHandle(Message);
if (isConsumeSuccess || consumeCount >= tryTimes)
{
Channel.BasicAck(dlvrArgs.DeliveryTag, false);//将队列里面的消息进行释放
isConsumeSuccess = true;
}
else
{
//重新放入队列,等待再次消费
Channel.BasicAck(dlvrArgs.DeliveryTag, true);
}
}
}
}
};
Channel.BasicConsume(queueName, false, Consumer);
} catch (Exception ex)
{
LogHelper.Log(LogCategory.Error, ex.Message, ex);
}
} public T ToJson()
{
return JsonConvert.DeserializeObject<T>(Message);
}
}
消费者
3、新建控制台程序,发送消息:
class Program
{
public static string MqUri = ConfigHelper.GetConfig("RabbitMQ", "MqUri");
public static string MqExchange = ConfigHelper.GetConfig("RabbitMQ", "MqExchange");
public static string MqHostName = ConfigHelper.GetConfig("RabbitMQ", "MqHostName");
public static string MqUserName = ConfigHelper.GetConfig("RabbitMQ", "MqUserName");
public static string MqPassword = ConfigHelper.GetConfig("RabbitMQ", "MqPassword"); static void Main(string[] args)
{
string userCommand = "";
while (userCommand != "exit")
{
Console.WriteLine("请输入:");
userCommand = Console.ReadLine(); //发送消息
var publisher = new Publisher(MqExchange, MqHostName,
MqUserName, MqPassword, "/", new Uri(MqUri)); publisher.PublishFanoutMessage(userCommand);
}
}
}
发送消息控制台应用
4、新建控制台程序,接受消息:
internal class Program
{
public static string MqUri = ConfigHelper.GetConfig("RabbitMQ", "MqUri");
public static string MqExchange = ConfigHelper.GetConfig("RabbitMQ", "MqExchange");
public static string MqHostName = ConfigHelper.GetConfig("RabbitMQ", "MqHostName");
public static string MqUserName = ConfigHelper.GetConfig("RabbitMQ", "MqUserName");
public static string MqPassword = ConfigHelper.GetConfig("RabbitMQ", "MqPassword"); static void Main(string[] args)
{
Console.WriteLine("Start process data {0}", DateTime.Now);
try
{
var subscriber = new Subscriber<string>(
MqExchange, MqHostName, MqUserName, MqPassword, "/",
new Uri(MqUri))
{
ReceiveAnswerMessageHandle = SubscriberHandler1
}; subscriber.ReceiveFanoutMessage(); }
catch (Exception ex)
{
Console.WriteLine(ex);
}
} private static bool SubscriberHandler1(string msg)
{
Console.WriteLine(msg);
return true;
}
}
接受消息控制台应用
5、配置文件:
上面两个控制台的配置文件一样,如下:
<RabbitMQ>
<add key="MqUri" value="amqp://localhost/" />
<add key="MqExchange" value="MyExchange" />
<add key="MqHostName" value="localhost" />
<add key="MqUserName" value="root" />
<add key="MqPassword" value="root" />
</RabbitMQ>
6、结果图:
asp.net 使用rabbitmq事例的更多相关文章
- DotNet 资源大全中文版(Awesome最新版)
Awesome系列的.Net资源整理.awesome-dotnet是由quozd发起和维护.内容包括:编译器.压缩.应用框架.应用模板.加密.数据库.反编译.IDE.日志.风格指南等. 算法与数据结构 ...
- 【资源大全】.NET资源大全中文版(Awesome最新版)
算法与数据结构(Algorithms and Data structures) 应用程序接口(API) 应用程序框架(Application Frameworks) 模板引擎(Application ...
- ASP.NET Core Web API下事件驱动型架构的实现(三):基于RabbitMQ的事件总线
在上文中,我们讨论了事件处理器中对象生命周期的问题,在进入新的讨论之前,首先让我们总结一下,我们已经实现了哪些内容.下面的类图描述了我们已经实现的组件及其之间的关系,貌似系统已经变得越来越复杂了. 其 ...
- ASP.NET Core2利用MassTransit集成RabbitMQ
在ASP.NET Core上利用MassTransit来集成使用RabbitMQ真的很简单,代码也很简洁.近期因为项目需要,我便在这基础上再次进行了封装,抽成了公共方法,使得使用RabbitMQ的调用 ...
- 如何从40亿整数中找到不存在的一个 webservice Asp.Net Core 轻松学-10分钟使用EFCore连接MSSQL数据库 WPF实战案例-打印 RabbitMQ与.net core(五) topic类型 与 headers类型 的Exchange
如何从40亿整数中找到不存在的一个 前言 给定一个最多包含40亿个随机排列的32位的顺序整数的顺序文件,找出一个不在文件中的32位整数.(在文件中至少确实一个这样的数-为什么?).在具有足够内存的情况 ...
- ExpandoObject与DynamicObject的使用 RabbitMQ与.net core(一)安装 RabbitMQ与.net core(二)Producer与Exchange ASP.NET Core 2.1 : 十五.图解路由(2.1 or earler) .NET Core中的一个接口多种实现的依赖注入与动态选择看这篇就够了
ExpandoObject与DynamicObject的使用 using ImpromptuInterface; using System; using System.Dynamic; names ...
- 简述C#中IO的应用 RabbitMQ安装笔记 一次线上问题引发的对于C#中相等判断的思考 ef和mysql使用(一) ASP.NET/MVC/Core的HTTP请求流程
简述C#中IO的应用 在.NET Framework 中. System.IO 命名空间主要包含基于文件(和基于内存)的输入输出(I/O)服务的相关基础类库.和其他命名空间一样. System.I ...
- ASP.NET Core2基于RabbitMQ对Web前端实现推送功能
在我们很多的Web应用中会遇到需要从后端将指定的数据或消息实时推送到前端,通常的做法是前端写个脚本定时到后端获取,或者借助WebSocket技术实现前后端实时通讯.因定时刷新的方法弊端很多(已不再采用 ...
- 重温.NET下Assembly的加载过程 ASP.NET Core Web API下事件驱动型架构的实现(三):基于RabbitMQ的事件总线
重温.NET下Assembly的加载过程 最近在工作中牵涉到了.NET下的一个古老的问题:Assembly的加载过程.虽然网上有很多文章介绍这部分内容,很多文章也是很久以前就已经出现了,但阅读之后 ...
随机推荐
- python使用stomp连接activemq
一.安装ActiveMQ服务 1. 当使用windows时,安装参考:https://blog.csdn.net/WuLex/article/details/78323811 启动:运行activem ...
- noj算法 8皇后打印 回溯法
描述: 输出8皇后问题所有结果. 输入: 没有输入. 输出: 每个结果第一行是No n:的形式,n表示输出的是第几个结果:下面8行,每行8个字符,‘A’表示皇后,‘.’表示空格.不同的结果中,先输出第 ...
- eclipse格式化代码快捷键失效
原因是与搜狗输入法的“简繁切换”快捷键冲突(取消搜狗输入法的简繁切换快捷键,即可解决)
- Source Code Review
1.berfore we talking abnout the Source Code review,here's what we want to know about the most popula ...
- python实现简单的登录管理
import json,timeusername=[]userpasswd=[]def login_success_file(name): try: f=open(r"F:/login_su ...
- Hive SemanticException
hive, sex='boy'); FAILED: SemanticException Line : Invalid path ''/root/data/hdata.txt'': No files m ...
- 利用fastjson解析json并通过js&ajax实现页面的无跳转刷新
1.json是一种优秀的数据格式,在移动开发和web开发中经常用到,本例中通过一个小案例讲解如何通过alibaba的开源框架fastjson来解析jason数据格式并通过js实现无跳转刷新 2,新建一 ...
- H5测试与PC端测试不同的点
1.通过H5网页(非手机的返回功能)的返回功能可以返回,不会出现无法返回的情况. 2.横屏竖屏相互切换,能自适应,并且布局不会乱掉: 3.为能在不同分辨率的手机上能更好的展示,建议采用响应式设计(如: ...
- DWM1000 测距原理简单分析 之 SS-TWR代码分析2 -- [蓝点无限]
蓝点DWM1000 模块已经打样测试完毕,有兴趣的可以申请购买了,更多信息参见 蓝点论坛 正文: 首先将SS 原理介绍中的图片拿过来,将图片印在脑海里. 对于DeviceA 和 DeviceB来说,初 ...
- Selenium 2自动化测试实战
Selenium 2自动化测试实战 百度网盘 链接:https://pan.baidu.com/s/1aiP3d8Y1QlcHD3fAlEj4sg 提取码:jp8e 复制这段内容后打开百度网盘手机Ap ...