ハンドラに例外がスローされないにもかかわらず、メッセージXを何度もやり直すNServiceBusに厄介な問題があります。 NHibernateセッションとNSB ambiantトランザクションを扱ういくつかの情報があります。何のエラーも投げられないので、私は問題の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がすべてのトランスポート・メッセージの子コンテナを作成し、この子コンテナがメッセージの処理後に破棄されることもわかります。 (_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;
}
}
}
:
public void Dispose()
{
if (!_isDisposed)
{
DiscardSession();
_isDisposed = true;
}
}
private void DiscardSession()
{
if (_transaction != null && _transaction.IsActive)
{
_transaction.Dispose();
}
if (Session != null)
{
Session.Dispose();
}
}
私のハンドラは、このように構成されています。問題は、子コンテナが配置されたときに、作業単位がこのように配置されているということですセッションをフラッシュしてトランザクションをコミットする作業単位をコミットしないと、メッセージが最大再試行回数を超えて再試行されたというエラーが発生したことがわかりました。
SoこれはNHibernateセッションとリンクされているようですそれが作成され処分される方法ですが、作業単位内で作成されているので、セッションファクトリを実際に使用することはできません。 IMessageModuleを使用してセッションを作成して破棄することはできますが、最初にエラーの原因を理解できないため、これが適切な方法かどうかはわかりません。要約するので
:すべてのハンドラは、子コンテナに(THXを同じインスタンスを共有することを使用して依存関係のように、
は私がところで、作業のスコープユニットを使用しています:私はセットアップをしました子コンテナがすべての一時オブジェクトをそのコンテナ内のシングルトンとして扱うが、作業ユニットは共有されていないことがわかったので、これはスコープ設定の理由です)
私は私のハンドラを
using(_unitOfWork) { }
ステートメントにラップして、各処理後に作業ユニットを廃棄します。私は明示的に_unitOfWork
にCommit
を呼び出さない場合は、作業取得者のユニットが配置され、NHibernateのセッションも
が配置され、メッセージは最大再試行回数を超えて再試行と、エラーがスローされます。
この現象の原因は何ですか。 IMessageModuleはこれに対する答えですか?
エラーキュー内のメッセージを見てください。メッセージヘッダーに例外メッセージはありますか? – stephenl
@stephenlいいえ、私が見る唯一の事は ' 'と同じメッセージです。それはNHibernateに関連しているようですが、私はNHibernateとNSBの統合を持っていません。 –