虽然在处理程序中没有引发异常,但我得到了NServiceBus重试消息X次的奇怪问题。有一些信息处理NHibernate会话和NSB环境事务。由于没有错误发生,我不是100%确定的问题,因此不能真正决定做什么。即使没有异常,NServiceBus重试消息
我被配置NSB与城堡温莎像这样:
IWindsorContainer container = new WindsorContainer(new XmlInterpreter());
container.Install(new ContainerInstaller());
container.Install(new UnitOfWorkInstaller(AppDomain.CurrentDomain.BaseDirectory, Castle.Core.LifestyleType.Scoped));
container.Install(new FactoryInstaller(AppDomain.CurrentDomain.BaseDirectory));
container.Install(new RepositoryInstaller(AppDomain.CurrentDomain.BaseDirectory));
Configure.With()
.CastleWindsorBuilder(container)
.FileShareDataBus(Properties.Settings.Default.DataBusFileSharePath)
.MsmqTransport()
.IsTransactional(true)
.PurgeOnStartup(false)
.UnicastBus()
.LoadMessageHandlers()
.ImpersonateSender(false)
.JsonSerializer();
的UnitOfWorkInstaller
寄存器工作(NHibernate会话)的单位像这样:
public void Install(IWindsorContainer container, IConfigurationStore store)
{
var fromAssemblyDescriptor = AllTypes.FromAssemblyInDirectory(new AssemblyFilter(_installationPath));
container.Register(fromAssemblyDescriptor
.IncludeNonPublicTypes()
.Pick()
.If(t => t.GetInterfaces().Any(i => i == typeof(IUnitOfWork)) && t.Namespace.StartsWith("Magma"))
.WithService.AllInterfaces()
.Configure(con => con.LifeStyle.Is(_lifeStyleType).UsingFactoryMethod(k => k.Resolve<IUnitOfWorkFactory>().Create())));
}
因此,每个时间的消息到达时所有存储库都使用相同的工作单元。我读过手动回滚当前事务结果的错误(我真的不知道为什么),我也知道NSB为每个传输消息创建一个子容器,并且此子容器在处理消息后处理。问题是,当孩子容器布置工作单元配置是这样的:
public void Dispose()
{
if (!_isDisposed)
{
DiscardSession();
_isDisposed = true;
}
}
private void DiscardSession()
{
if (_transaction != null && _transaction.IsActive)
{
_transaction.Dispose();
}
if (Session != null)
{
Session.Dispose();
}
}
我的处理程序结构是这样的:(该_unitOfWork作为一个构造函数依赖通过)
public void Handle(<MessageType> message)
{
using (_unitOfWork)
{
try
{
// do stuff
_unitOfWork.Commit();
}
catch (Exception ex)
{
_unitOfWork.Rollback();
// rethrow so the message stays in the queue
throw;
}
}
}
我发现,如果我没有提交工作单元(刷新会话并提交交易),我得到一个错误,表示邮件已重试超过最大重试次数bla bla bla ...
因此,它似乎与NHibernate会话和它的创建和处理方式,但是由于它是在工作单元内创建的,所以我无法真正使用会话工厂。我读过我可以使用IMessageModule来创建和处理会话,但我不知道这是否正确,因为我不明白是什么导致了错误。
因此,要回顾:
我使用的工作范围的单位,使所有的处理程序相依性将共享相同的实例(THX到子容器,BTW:我设置作为临时思考的工作单元,子容器将所有瞬态对象视为该容器内的单例,但我看到工作单元未被共享,因此这就是为什么它的设置范围)
我是将我的处理程序包装在
using(_unitOfWork) { }
声明中,以便在每次处理后处理工作单元。当下班的单位设置,NHibernate会话也设置
如果我不显式调用
Commit
在_unitOfWork
,消息重试超出最大重试次数,然后抛出一个错误。
是什么导致了这种行为?而IMessageModule就是这个答案吗?
查看错误队列中的消息。消息头中是否有异常消息? – stephenl 2012-04-12 00:30:01
@stephenl Nope,我看到的唯一信息是与' '相同的信息。它似乎与NHibernate有关,但我没有任何与NHibernate的NSB集成。 –
2012-04-12 12:19:44