EasyNetQ自定义异常消息处理
20140310补充:
rabbitmq有requeue属性,可以选择消息是否返回队列,另,本文的解决方式非常之山寨,只能应用于发送和接收方式。
这几天在折腾消息队列,在.Net环境下有基于RabbitMQ有很多有API的选择,最后选择了比较简单的EasyNetQ(http://easynetq.com/)
在测试使用的时候发现一个问题,对于处理错误的消息,EasyNetQ默认会放到一个错误队列中并提供了一个工具可以对错误队列的消息进行重新分发。RabiitMQ是有一个事务功能的,但是貌似在EasyNetQ的实现中,没有发现相关的操作方式
现在的需求是,在某种特定的情况下,需要将处理不成功的消息,保留在消息原队列
做了一个变通处理,出现错误消息的时候,将其再送回原队列。从客户端上可以直接send回队列,但这样不是一个很好的方式
研究了一下EasyNetQ的相关代码,发现其定义了一个IConsumerErrorStrategy接口,我们只要自己自行实现,并注册一个自定义方法就可以
ComponentRegistration.cs原注册方法相关,默认错误消息处理方式在DefaultConsumerErrorStrategy.cs中
public class ComponentRegistration
{
public static void RegisterServices(IContainer container)
{
Preconditions.CheckNotNull(container, "container"); // Note: IConnectionConfiguration gets registered when MQContext.CreateBus(..) is run.
#region DefaultConsumerErrorStrategy
container
.Register(_ => container)
.Register<IMessageQueueQLogger, ConsoleLogger>()
.Register<ISerializer, JsonSerializerN>()
.Register<IConventions, Conventions>()
.Register<IEventBus, EventBus>()
.Register<ITypeNameSerializer, TypeNameSerializer>()
.Register<Func<string>>(x => CorrelationIdGenerator.GetCorrelationId)
.Register<IClusterHostSelectionStrategy<ConnectionFactoryInfo>, DefaultClusterHostSelectionStrategy<ConnectionFactoryInfo>>()
.Register<IConsumerDispatcherFactory, ConsumerDispatcherFactory>()
.Register<IPublishExchangeDeclareStrategy, PublishExchangeDeclareStrategy>()
.Register<IPublisherConfirms, PublisherConfirms>()
.Register<IConsumerErrorStrategy, DefaultConsumerErrorStrategy>()
.Register<IHandlerRunner, HandlerRunner>()
.Register<IInternalConsumerFactory, InternalConsumerFactory>()
.Register<IConsumerFactory, ConsumerFactory>()
.Register<IConnectionFactory, ConnectionFactoryWrapper>()
.Register<IPersistentChannelFactory, PersistentChannelFactory>()
.Register<IClientCommandDispatcherFactory, ClientCommandDispatcherFactory>()
.Register<IHandlerCollectionFactory, HandlerCollectionFactory>()
.Register<IAdvancedBus, RabbitAdvancedBus>()
.Register<IRpc, Rpc>()
.Register<ISendReceive, SendReceive>()
.Register<IBus, RabbitBus>();
#endregion
}
}
对DefaultConsumerErrorStrategy的代码进行研究后发现,EasyNetQ是产生一个处理错误消息队列的Exchanges,将消息二次封装后推送到默认的错误队列
只要将消息队列改为源消息队列,取消消息二次封装,直接推送到队列
队列绑定
private string DeclareErrorExchangeAndBindToDefaultErrorQueue(IModel model, ConsumerExecutionContext context)
{
var originalRoutingKey = context.Info.RoutingKey; return errorExchanges.GetOrAdd(originalRoutingKey, _ =>
{
var exchangeName = conventions.ErrorExchangeNamingConvention(context.Info);
model.ExchangeDeclare(exchangeName, ExchangeType.Direct, durable: true);
//更改第一个参数
model.QueueBind(originalRoutingKey, exchangeName, originalRoutingKey);
return exchangeName;
});
}
消息处理
public virtual PostExceptionAckStrategy HandleConsumerError(ConsumerExecutionContext context, Exception exception)
{
Preconditions.CheckNotNull(context, "context");
Preconditions.CheckNotNull(exception, "exception"); try
{
Connect(); using (var model = connection.CreateModel())
{
var errorExchange = DeclareErrorExchangeQueueStructure(model, context);
var messageBody = context.Body;
var properties = model.CreateBasicProperties();
context.Properties.CopyTo(properties);
properties.Type = context.Properties.Type;
//消息持久化
properties.SetPersistent(true); model.BasicPublish(errorExchange, context.Info.RoutingKey, properties, messageBody); }
}
catch (Exception unexpectedException)
{
// Something else unexpected has gone wrong :(
logger.ErrorWrite("EasyNetQMessageQueue Consumer Error Handler: Failed to publish error message\nException is:\n"
+ unexpectedException);
}
return Consumer.PostExceptionAckStrategy.ShouldAck;
}
因为EasyNetQ在CreateBus的时候就会将相关事件注册,所以我们只需最后自行在config中加入有关配置,在注册事件的位置加入判断即可让异常抛回
由于刚接触RabbitMQ,对于一些概念的理解可能还不是非常到位,这是我目前所能找到的解决方案
当然可能以后的版本中,EasyNetQ会加入对事务的操作,现在EasyNetQ支持了一种叫Publisher Confirms的方法,貌似还是不是我想要的
EasyNetQ自定义异常消息处理的更多相关文章
- Web API应用架构在Winform混合框架中的应用(2)--自定义异常结果的处理
在上篇随笔<Web API应用架构在Winform混合框架中的应用(1)>中我介绍了关于如何在Winfrom里面整合WebAPI,作为一个新型数据源的接入方式,从而形成了三种不同的数据提供 ...
- .NET操作RabbitMQ组件EasyNetQ使用中文简版文档。
本文出自EasyNetQ官方文档,内容为自己理解加翻译.文档地址:https://github.com/EasyNetQ/EasyNetQ/wiki/Quick-Start EasyNetQ简介 Ea ...
- 【框架学习与探究之消息队列--EasyNetQ(1)】
前言 本文欢迎转载,实属原创,本文原始链接地址:http://www.cnblogs.com/DjlNet/p/7603554.html 废话 既然都是废话了,所以大家就可以跳过了,这里是博主有事没事 ...
- 使用EasyNetQ组件操作RabbitMQ消息队列服务
RabbitMQ是一个由erlang开发的AMQP(Advanved Message Queue)的开源实现,是实现消息队列应用的一个中间件,消息队列中间件是分布式系统中重要的组件,主要解决应用耦合, ...
- NET操作RabbitMQ组件EasyNetQ
NET操作RabbitMQ组件EasyNetQ使用中文简版文档. 本文出自EasyNetQ官方文档,内容为自己理解加翻译.文档地址:https://github.com/EasyNetQ/EasyNe ...
- RabbitMQ学习系列四-EasyNetQ文档跟进式学习与实践
EasyNetQ文档跟进式学习与实践 https://www.cnblogs.com/DjlNet/p/7603554.html 这里可能有人要问了,为什么不使用官方的nuget包呐:RabbitMQ ...
- NetCore基于EasyNetQ的高级API使用RabbitMq
一.消息队列 消息队列作为分布式系统中的重要组件,常用的有MSMQ,RabbitMq,Kafa,ActiveMQ,RocketMQ.至于各种消息队列的优缺点比较,在这里就不做扩展了,网上资源很多. 更 ...
- EasyNetQ使用(九)【非泛型的发布&订阅扩展方法,发生错误的情况 】
自从EasyNetQ第一个版本开始,它就可以发布/订阅特定类型的消息. bus.Subscribe<MyMessage>("subscriptionId", x =&g ...
- EasyNetQ异常处理
代码下载 https://download.csdn.net/download/u010312811/11252093 官方Demo https://github.com/EasyNetQ/EasyN ...
随机推荐
- .NET基础 (02).NET运行机制
.NET运行机制1 .NET程序被编译成什么形式的代码2 JIT是如何工作的3 简述程序集的加载机制4 如何配置程序集的版本策略 1 .NET程序被编译成什么形式的代码 .NET程序在编写完成后,会经 ...
- Javascript 的addEventListener()及attachEvent()对比
Mozilla中: addEventListener的使用方式: target.addEventListener(type, listener, useCapture); target: 文档节点.d ...
- [LintCode笔记了解一下]80.Median
Given a unsorted array with integers, find the median of it. A median is the middle number of the ar ...
- Hadoop各个启动流
(0)如果集群是第一次启动,需要格式化namenodehadoop@node1:~$ hdfs namenode –format (1)启动HDFS:hadoop@master:~$ start-df ...
- 安装Python-Windows
安装Python-Windows 在开始Python编程前,需要先安装Python环境.Python安装包可以到Python的官网下载,官网地址是https://www.python.org/,如果想 ...
- spring boot 错误:Check your ViewResolver setup
Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as ...
- python学习之路 七 :生成器、迭代器
本节重点: 掌握列表生成式.生成器.迭代器 一.生成式 现在有个需求,把[1,2,3,4,5,6,7,8,9,10]中的每个值加1. # 二逼青年版 a = [0,1,2,3,4,5,6,7,8,9 ...
- 如何防止Unity3D代码被反编译?
欢迎访问网易云社区,了解更多网易技术产品运营经验. 网易云易盾移动游戏安全技术专家陈士留在2018年Unity技术路演演讲内容中对这个问题有过比较详细的介绍,摘录如下: 防止Unity3D代码被反编译 ...
- RabbitMq初探——安装
rabbitmq Server安装 rabbitmq server安装很简单. 安装erlang环境 rpm -ihv erlang-18.1-1.el6.x86_64.rpm rpm -ihv ra ...
- Mysql内置功能《六》流程控制
一 流程控制 delimiter // CREATE PROCEDURE proc_if () BEGIN declare i int default 0; if i = 1 THEN SELECT ...