Не удается получить NServiceBus, чтобы не генерировать исключения (MessageQueueException, SqlException, TimeoutPersisterReceiver)

У меня очень разочаровывающая проблема NServiceBus, которую я не могу понять. Я надеюсь, что вы, ребята, сможете пролить свет на ситуацию.

В настоящее время я использую NServiceBus.Core v5.0 и NServiceBus.Host v6.0 и запускаю его в ненавязчивом режиме.

Кажется, что независимо от того, какую конфигурацию я использую, я всегда получаю какую-то ошибку. Я начну с конфигурации, которая производит наименьшее количество проблем:

Случай 1 - Использование пользовательского сканирования сборки:

public void Customize(BusConfiguration configuration)
    {
        var endpointName = typeof(EndpointConfig).Namespace;
        configuration.SetUniqueHostId(endpointName);

        configuration.UseSerialization<JsonSerializer>();
        configuration.UsePersistence<NHibernatePersistence, StorageType.Outbox>();

        configuration.AssembliesToScan(new List<Assembly>
        {
            GetType().Assembly,
            typeof(ICustomCommand).Assembly
        });

        configuration.Conventions()
            .DefiningCommandsAs(type => typeof(ICustomCommand).IsAssignableFrom(type));

        configuration.EnableDurableMessages();
        configuration.EnableInstallers();

        var container = ContainerInitializer.Container;
        configuration.UseContainer<AutofacBuilder>(c => c.ExistingLifetimeScope(container));
    }

Проблемы, которые я заметил здесь, следующие:

  1. При запуске хост-приложения NServiceBus и постоянной базы данных SQL еще не существует, не выдается исключение о том, что база данных не может быть найдена (это происходит в случае 2).

  2. Я продолжаю получать следующее исключение:

NServiceBus.Timeout.Hosting.Windows.TimeoutPersisterReceiver Не удалось извлечь тайм-ауты из хранилища тайм-аутов

В конечном итоге это приводит к сбою приложения, потому что когда эта ошибка возникает слишком много раз, ServiceBus решает, что этого достаточно, и просто выдает фатальное исключение.

  1. Помимо вышеперечисленных проблем, приложение работает отлично, получая и обрабатывая сообщения... пока не произойдет фатальное исключение

Теперь этот немного сложнее:

Случай 2 - Использование сканирования сборки по умолчанию:

public void Customize(BusConfiguration configuration)
    {
        var endpointName = typeof(EndpointConfig).Namespace;
        configuration.SetUniqueHostId(endpointName);

        configuration.UseSerialization<JsonSerializer>();
        configuration.UsePersistence<NHibernatePersistence, StorageType.Outbox>();

        // !! DISABLED !!
        // configuration.AssembliesToScan(new List<Assembly>
        // {
        //    GetType().Assembly,
        //    typeof(ICustomCommand).Assembly
        // });

        configuration.Conventions()
            .DefiningCommandsAs(type => typeof(ICustomCommand).IsAssignableFrom(type));

        configuration.EnableDurableMessages();
        configuration.EnableInstallers();

        var container = ContainerInitializer.Container;
        configuration.UseContainer<AutofacBuilder>(c => c.ExistingLifetimeScope(container));
    }

В этом случае возникают следующие проблемы:

Когда постоянная база данных SQL еще не существует:

  1. При запуске хост-приложения NServiceBus, а база данных SQL не существует, исключение - throw - Ожидаемое поведение (это положительно)

После создания персистентной базы данных SQL:

  1. ServiceControl.Plugin.Nsb5.Heartbeat.Heartbeats | Невозможно отправить пульс в ServiceControl: NServiceBus.Unicast.Queuing.QueueNotFoundException: Не удалось отправить сообщение на адрес: [Particular.ServiceControl@MYPCNAME]

  2. Возникло исключение: System.Messaging.MessageQueueException в System.Messaging.dll Дополнительная информация: Внешний компонент выдал исключение.

  3. 2017-09-15 16: 25: 45.6743 | Warn | NServiceBus.Unicast.Messages.Messages.MessageMetadataRegistry | Заголовок сообщения "SharedTemp.Interfaces.ICustomCommand" сопоставлен с типом "SharedTemp.Interfaces.ICustomCommand", но этот тип не найден в сообщении. реестр [...]

  4. Возникло исключение: "System.Exception" в NServiceBus.Core.dll Дополнительная информация: Не удалось найти метаданные для "Newtonsoft.Json.Linq.JObject".

Теперь исключения 3 и 4 особенно странны (без каламбура), так как документация NServiceBus гласит:

По умолчанию все сборки в каталоге bin конечной точки сканируются, чтобы найти типы, реализующие его интерфейсы, чтобы он мог настроить их автоматически.

И "Newtonsoft.Json" и мои "SharedTemp dll's" действительно находятся в папке BIN, но NServiceBus, похоже, их не находит. Что касается пункта 1: NServiceBus не создает эту очередь для меня, но создает все остальные очереди, которые мне нужны.

Наконец, всегда запрашиваемый файл app.config:

    <?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="MasterNodeConfig" type="NServiceBus.Config.MasterNodeConfig, NServiceBus.Core"/>
    <section name="MessageForwardingInCaseOfFaultConfig" type="NServiceBus.Config.MessageForwardingInCaseOfFaultConfig, NServiceBus.Core"/>
    <section name="UnicastBusConfig" type="NServiceBus.Config.UnicastBusConfig, NServiceBus.Core"/>
    <section name="AuditConfig" type="NServiceBus.Config.AuditConfig, NServiceBus.Core"/>
  </configSections>
  <appSettings>
    <add key="NServiceBus/Persistence/NHibernate/dialect" value="NHibernate.Dialect.MsSql2012Dialect"/>
    <add key="NServiceBus/Outbox" value="true"/>
  </appSettings>
  <MessageForwardingInCaseOfFaultConfig ErrorQueue="error"/>
  <UnicastBusConfig>
    <MessageEndpointMappings />
  </UnicastBusConfig>
  <AuditConfig QueueName="audit"/>
  <connectionStrings>
    <add name="NServiceBus/Persistence" connectionString="Server=(LocalDB)\v11.0;Initial Catalog=NServiceBus;Integrated Security=true"/>
  </connectionStrings>
  <system.web>
    <membership defaultProvider="ClientAuthenticationMembershipProvider">
      <providers>
        <add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri=""/>
      </providers>
    </membership>
    <roleManager defaultProvider="ClientRoleProvider" enabled="true">
      <providers>
        <add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400"/>
      </providers>
    </roleManager>
  </system.web>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/>
  </startup>
  <MasterNodeConfig Node="localhost"/>
</configuration>

У кого-нибудь есть идеи по этому поводу?

1 ответ

Решение

После долгих поисков я наконец нашел проблему!

Прежде всего, я использовал собственный пакет NuGet, который должен был помочь мне с настройкой NServiceBus. Пакет отлично работал для других проектов, но для моего не очень хорошо, так как я использовал JsonSerialization вместо стандартной XML-сериализации.

Первая проблема с пакетом состоит в том, что он использовал интерфейс "INeedInitialization" для настройки NServiceBus. В моем коде я бы затем вызвал "IConfigureThisEndpoint", чтобы включить JsonSerialization. Проблема заключалась в том, что при запуске хоста NServiceBus он не смог найти библиотеку NewtonSoft.Json. Если затем я добавлю сканирование собственной сборки в свой собственный код конфигурации, это не вызовет "INeedInitialization", что приведет к неполной / неправильной конфигурации.

Я предполагаю, что он не мог загрузить библиотеку NewtonSoft.Json, потому что сканирование было запущено в коде / пространстве имен пакета? Может быть @Sean Farmer может ответить на это?

Вторая проблема с пакетом состоит в том, что он добавил бы строки подключения к app.config, одну для "NServiceBus/Persistence" и одну для "NServiceBus/Persistence/NHibernate/Saga". Я не использую Saga, поэтому строка подключения для этого не нужна. Первоначально это не было проблемой, так как я поймал это в первый раз, но я полностью забыл об этом после переустановки пакета. Удаление этого снова также, казалось, сделало NServiceBus счастливее.

Итак, что же получилось? Я удалил пакет и сделал конфигурацию самостоятельно со следующим результатом:

public void Customize(BusConfiguration configuration)
    {
        var endpointName = typeof(EndpointConfig).Namespace;
        configuration.UniquelyIdentifyRunningInstance().UsingCustomIdentifier(endpointName);

        configuration.EnableOutbox();
        configuration.UsePersistence<NHibernatePersistence>();
        configuration.Transactions().DefaultTimeout(TimeSpan.FromMinutes(5.0));

        configuration.UseSerialization<JsonSerializer>();

        configuration.Conventions()
            .DefiningCommandsAs(type => typeof(ICustomCommand).IsAssignableFrom(type));

        configuration.EnableDurableMessages();
        configuration.EnableInstallers();

        var container = ContainerInitializer.Container;
        configuration.UseContainer<AutofacBuilder>(c => c.ExistingLifetimeScope(container));
    }

@Sean: Спасибо, что позволили мне связаться с вами. К счастью, это было не нужно

@ Майк: Спасибо за вклад

Другие вопросы по тегам