0

NHibernate永続性を使用してNServiceBusSagasをセットアップしようとしていますが、127.0.0.1:8080でサービスへの接続中にエラーが発生したため、何かが正しく構成されていないと思います。sagaにコマンドメッセージを処理させることはできますが、数秒後に以下のエラーメッセージがコンソールウィンドウに表示され、同じコマンドが再度実行されて、sagaのハンドラーが再度呼び出されます。これは、アプリケーションの実行を許可している限り、繰り返し発生します。NHibernateがsagaデータのテーブルを作成するため、データベースに接続していることがわかりますが、そのテーブルには何も保持されていません。

sagaデータの永続化にエラーがあると思います。デフォルトのRavenDbsaga永続性を使用しようとしている可能性があると思いますが、なぜそうなるのかわかりません。

私が受け取るエラーメッセージは次のとおりです。

警告NServiceBus.Unicast.Transport.Transactional.TransactionalTransport[(null)] <(null)>-ID =3753b476-7501-4fd8-90d0-b10aee95a578 \22314System.Net.WebExceptionのメッセージの「transportmessagereceived」イベントの発生に失敗しました。リモートサーバーに接続できません--->System.Net.Sockets.SocketException:ターゲットマシンがSystem.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot、 SocketAddress socketAddress)at System.Net.Sockets.Socket.InternalConnect(EndPoint remoteEP)at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure、Socket s4、Socket s6、Socket&socket、IPAddress&address、ConnectSocketState state、IAsyncResult asyncResult、Exception&例外)---内部例外スタックトレースの終了--- NServiceBus.Unicast.UnicastBus.HandleTransportMessage(IBuilder childBuilder、TransportMessage msg)at NServiceBus.Unicast.UnicastBus.TransportMessageReceived(Object sender、TransportMessageReceivedEventArgs e)at System.EventHandler`1 .Invoke(Object sender、TEventArgs e)at NServiceBus.Unicast.Transport.Transactional.TransactionalTransport.OnTransportMessageReceived(TransportMessage msg)OnTransportMessageReceived(TransportMessage msg)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>

ほんの2、3のメモ:

これは、この機能をテストするために使用しているサンプルアプリからのものです。localdbに添付されたローカルデータベースファイルを使用しますが、SQLServer2012を使用する私の完全なアプリケーションは同じ動作を示しています。NServiceBus.NHibernate NuGetパッケージは現在(この投稿の時点で)古いアセンブリバージョンにバインドされているため、NHibernateのdependenteAssemblyエントリも追加する必要がありました。

ご覧のとおり、私はIOCとしてUnityも使用していますが、Ninjectを使用したプロジェクトでもこれを複製しました。私はドメインストレージにEventStoreを使用していますが、これはうまく機能しています。コマンドを処理し、他のプロセスで処理されるようにEventStoreを介してイベントを公開するコマンドハンドラーがあります。ただし、コマンドハンドラーとして佐賀だけを残して、それらすべてを無効にしようとしましたが、それでも同じエラーが発生します。

誰かが私が間違っているかもしれないことについて何か考えを持っていますか?

4

1 に答える 1

0

問題の回避策を見つけました。組み込みの NServiceBus プロファイルの使用に問題があるようです。ホストのコマンド ライン引数でプロファイルを指定しなかったため、デフォルトで NServiceBus.Production プロファイルをロードしていました。Production プロファイルは、デフォルトで、すべての永続性に RavenDB を使用します。

GitHub の NServiceBus ソースを見ると、Production Profile Handler の 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();

ここで注意すべき点がいくつかあります。

  • プロファイルは常に、Configure インスタンスで RavenPersistence() を呼び出します。他の永続性が既に定義されている場合、実際に Raven の構成をバイパスするかどうかを確認するために、そのメソッドの内部の仕組みを掘り下げていませんが、常にこのメソッドを実行します。
  • NServiceBus ソースにアタッチしてこのコードを使用してデバッグすると、2 行目で HasComponent が false を返し、RavenSagaPersister 構成が実行されます。これは、エンドポイント構成で NHibernateSagaPerister が定義されている場合でも発生します。

この動作が設計によるものなのか、バグなのか、それとも私の設定ミスによるものなのかはわかりません。ただし、私の回避策は、独自のプロファイルを作成することでした。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; }
}

これは長い説明ですが、うまくいけば、他の誰かが道を進むのに役立ちます. これを達成するためのより良い方法、またはプロファイルを使用する正しい方法について誰か提案があれば、私に知らせてください!

于 2012-10-18T19:55:54.183 に答える