我正在尝试使用NHibernate持久性设置NServiceBus Sagas,但我认为我配置错误,因为我在127.0.0.1:8080连接到服务时出错。我能够让我的传奇处理命令消息,但几秒钟后,控制台窗口中出现以下错误消息,然后再次触发相同的命令,导致再次调用saga中的处理程序。只要我允许应用程序运行,就会重复发生这种情况。我可以告诉NHibernate连接到我的数据库,因为它为saga数据创建了一个表,但该表中没有任何内容。
我认为持续存在saga数据时出现错误,我的猜测是它可能尝试使用默认的RavenDb saga持久性,但我不确定为什么会这样。
我收到的错误消息如下:
WARN NServiceBus.Unicast.Transport.Transactional.TransactionalTransport [(null)]<(null)> - 未能提出“收到的运输消息”事件 对于ID = 3753b476-7501-4fd8-90d0-b10aee95a578 \ 22314的消息 System.Net.WebException:无法连接到远程服务器---> System.Net.Sockets.SocketException:无法建立连接 因为目标机器主动拒绝它127.0.0.1:8080 at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress(socketAddress)at System.Net.Sockets.Socket.InternalConnect(EndPoint remoteEP)at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, 插座s4,插座s6,插座& socket,IPAddress&地址, ConnectSocketState状态,IAsyncResult asyncResult,Exception& 例外)---内部异常堆栈跟踪结束--- at NServiceBus.Unicast.UnicastBus.HandleTransportMessage(IBuilder childBuilder,TransportMessage msg)at NServiceBus.Unicast.UnicastBus.TransportMessageReceived(对象发送者, TransportMessageReceivedEventArgs e)at System.EventHandler`1.Invoke(Object sender,TEventArgs e)at NServiceBus.Unicast.Transport.Transactional.TransactionalTransport.OnTransportMessageReceived(TransportMessage MSG)
我试图使用的传奇样本(这里没什么特别的,无论我是否真的在Handle方法中做某事,都会发生同样的事情):
public class ItemSaga : Saga<ItemData>, IAmStartedByMessages<CreateItemCommand>
{
public void Handle(CreateItemCommand message)
{
}
}
public class ItemData : ISagaEntity
{
public Guid Id { get; set; }
public string Originator { get; set; }
public string OriginalMessageId { get; set; }
}
我的端点配置如下所示:
public class EndpointConfig : IConfigureThisEndpoint, AsA_Publisher, IWantCustomInitialization
{
public void Init()
{
var container = new UnityContainer();
container.AddNewExtension<Domain.UnityExtension>();
Configure.With()
.UnityBuilder(container)
.JsonSerializer()
.Log4Net()
.MsmqSubscriptionStorage()
.MsmqTransport()
.PurgeOnStartup(true)
.UnicastBus()
.ImpersonateSender(false)
.DisableTimeoutManager()
.NHibernateSagaPersister()
.CreateBus()
.Start(() => Configure.Instance.ForInstallationOn<NServiceBus.Installation.Environments.Windows>().Install());
}
}
我的app.config看起来像这样:
<MessageForwardingInCaseOfFaultConfig ErrorQueue="error"/>
<MsmqTransportConfig NumberOfWorkerThreads="1" MaxRetries="5"/>
<NHibernateSagaPersisterConfig UpdateSchema="true">
<NHibernateProperties>
<add Key="connection.provider" Value="NHibernate.Connection.DriverConnectionProvider"/>
<add Key="connection.driver_class" Value="NHibernate.Driver.Sql2008ClientDriver"/>
<add Key="connection.connection_string" Value="Data Source=(localdb)\v11.0;Integrated Security=True;AttachDbFileName=|DataDirectory|\App_Data\EventStore.mdf"/>
<add Key="dialect" Value="NHibernate.Dialect.MsSql2012Dialect"/>
</NHibernateProperties>
</NHibernateSagaPersisterConfig>
<connectionStrings>
<add name="EventStore" connectionString="Data Source=(localdb)\v11.0;Integrated Security=True;AttachDbFileName=|DataDirectory|\App_Data\EventStore.mdf"
providerName="System.Data.SqlClient" />
</connectionStrings>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="NHibernate" publicKeyToken="aa95f207798dfdb4" />
<bindingRedirect oldVersion="0.0.0.0-3.3.0.4000" newVersion="3.3.1.4000" />
</dependentAssembly>
</assemblyBinding>
</runtime>
只是几个笔记:
这是来自我用来测试此功能的示例应用。它使用附加到localdb的本地数据库文件,但是我使用SQL Server 2012的完整应用程序表现出相同的行为。我还必须为NHibernate添加一个dependdenteAssembly条目,因为NServiceBus.NHibernate NuGet包当前绑定到较旧的程序集版本(截至本文)。
正如您所看到的,我也使用Unity作为我的IOC,但我也使用Ninject复制了一个项目。我使用EventStore进行域名存储,效果很好。我有命令处理程序处理命令并通过EventStore发布事件以由其他进程处理。但是,我已经尝试禁用所有那些只留下我的Saga作为命令处理程序的人,我仍然得到同样的错误。
有没有人对我可能做错了什么有任何想法?
答案 0 :(得分:0)
我找到了解决问题的方法。使用内置的NServiceBus配置文件似乎是一个问题。我没有在主机的命令行参数中指定配置文件,因此默认情况下它正在加载NServiceBus.Production配置文件。默认情况下,Production配置文件使用RavenDB进行所有持久性。
查看GitHub上的NServiceBus源,生产配置文件处理程序在ProfileActivated方法中包含以下内容:
Configure.Instance.RavenPersistence();
if (!Configure.Instance.Configurer.HasComponent<ISagaPersister>())
Configure.Instance.RavenSagaPersister();
if (!Configure.Instance.Configurer.HasComponent<IManageMessageFailures>())
Configure.Instance.MessageForwardingInCaseOfFault();
if (Config is AsA_Publisher && !Configure.Instance.Configurer.HasComponent<ISubscriptionStorage>())
Configure.Instance.RavenSubscriptionStorage();
这里需要注意几点:
我不确定这种行为是否是设计,错误或我的错误配置。但是我的解决方法是创建自己的个人资料。我不得不将NHibernate配置调用从我的端点配置移动到我的新配置文件,但是一旦我这样做,我就能够使用NHibernate持久性而没有错误。
我的自定义配置文件如下所示(我从Production配置文件的日志处理程序中借用了日志记录处理程序):
public class MyProfile : IProfile
{
}
internal class MyProfileProfileHandler : IHandleProfile<MyProfile>, IWantTheEndpointConfig
{
void IHandleProfile.ProfileActivated()
{
Configure.Instance.NHibernateUnitOfWork();
Configure.Instance.NHibernateSagaPersister();
Configure.Instance.DBSubcriptionStorage();
Configure.Instance.UseNHibernateTimeoutPersister();
}
public IConfigureThisEndpoint Config { get; set; }
}
public class MyProfileLoggingHandler : IConfigureLoggingForProfile<MyProfile>
{
void IConfigureLogging.Configure(IConfigureThisEndpoint specifier)
{
SetLoggingLibrary.Log4Net<RollingFileAppender>(null,
a =>
{
a.CountDirection = 1;
a.DatePattern = "yyyy-MM-dd";
a.RollingStyle = RollingFileAppender.RollingMode.Composite;
a.MaxFileSize = 1024 * 1024;
a.MaxSizeRollBackups = 10;
a.LockingModel = new FileAppender.MinimalLock();
a.StaticLogFileName = true;
a.File = "logfile";
a.AppendToFile = true;
});
if (GetStdHandle(STD_OUTPUT_HANDLE) == IntPtr.Zero)
return;
SetLoggingLibrary.Log4Net<ColoredConsoleAppender>(null,
a =>
{
LiteLoggingHandler.PrepareColors(a);
a.Threshold = Level.Info;
}
);
}
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);
const int STD_OUTPUT_HANDLE = -11;
}
最后一点,我还必须根据标准的NHibernate实践将我的saga数据对象的所有属性设置为虚拟。一旦系统实际使用NHibernate,这就变得非常明显了。
public class ItemData : ISagaEntity
{
public virtual Guid Id { get; set; }
public virtual string Originator { get; set; }
public virtual string OriginalMessageId { get; set; }
}
这是一个很长的解释,但希望它能帮助其他人走出困境。如果有人对更好的方法有所建议,或者使用配置文件的正确方法,请告诉我们!