NServiceBus Saga не имеет зарегистрированного компонента IPersistTimeouts

У меня есть хост WCF (IIS), где я получаю это исключение во время настройки NServiceBus:

Возникло исключение: «Autofac.Core.Registration.ComponentNotRegisteredException» в NServiceBus.Core.dll

Дополнительная информация: запрошенная служба «NServiceBus.Timeout.Core.IPersistTimeouts» не зарегистрирована. Чтобы избежать этого исключения, либо зарегистрируйте компонент для предоставления службы, проверьте регистрацию службы с помощью IsRegistered(), либо используйте метод ResolveOptional() для разрешения дополнительной зависимости.

Я использую NSB 5.2.9 с постоянством в памяти и транспортом MSMQ.

Это моя конфигурация для собственного хоста WCF (IIS). Нет App.config! **Это вызывается после регистрации Autofac в global.asax:

    public static void CreateSelfHost( string endpointName, ILifetimeScope container )
    {
        if ( Bus != null )
            return;

        lock ( syncLock )
        {
            var config = new BusConfiguration();

            config.UseContainer<AutofacBuilder>( c => c.ExistingLifetimeScope( container ) );

            var includesBuilder = AllAssemblies.Matching( "Company.App." );
            config.AssembliesToScan( includesBuilder );

            config.UseSerialization<JsonSerializer>();
            config.UseTransport<MsmqTransport>();
            config.UsePersistence<InMemoryPersistence>();
            config.DisableFeature<SecondLevelRetries>();    //turn off for in-mem persistence, otherwise could lose messages
            config.EndpointName( endpointName );


            config.EnableInstallers(); //ensures msmq is created
            config.PurgeOnStartup( true ); //only for self-hosted

            config.Transactions().Disable();
            config.DisableFeature<StorageDrivenPublishing>();

            Bus = NServiceBus.Bus.CreateSendOnly( config ); //create SendOnlyBus here
        }
    }

Конфигурация на всех конечных точках выполняется только через IProvideConfiguration<>.

В свойствах проекта задан профиль NServiceBus.Lite, но это не имеет значения.

Я новичок в NSB и не могу объяснить, почему это происходит. Я искал методы для включения указанного IPersistsTimeouts, но любой метод, который я нашел, помечен как устаревший и не работает.

EDIT #1: Дамп функции по запросу @DavidBoike

------------- FEATURES ----------------
Name: CriticalErrorHandling
Version: 5.2.9
Enabled by Default: Yes
Status: Enabled
Dependencies: None
Startup Tasks: None
Name: CustomIDataBus
Version: 5.2.9
Enabled by Default: No
Status: Disabled
Deactivation reason: Did not meet one of the dependencies: [DataBus]
Name: DataBus
Version: 5.2.9
Enabled by Default: Yes
Status: Disabled
Deactivation reason: Did not fulfill its Prerequisites:
   -No databus properties was found in available messages
Name: Encryptor
Version: 5.2.9
Enabled by Default: Yes
Status: Disabled
Deactivation reason: Did not fulfill its Prerequisites:
   -No encryption properties was found in available messages
Name: ErrorSubscribers
Version: 5.2.9
Enabled by Default: Yes
Status: Enabled
Dependencies: None
Startup Tasks: None
Name: ForwarderFaultManager
Version: 5.2.9
Enabled by Default: Yes
Status: Enabled
Dependencies: None
Startup Tasks: None
Name: InMemoryFaultManager
Version: 5.2.9
Enabled by Default: No
Status: Disabled
Deactivation reason: Did not meet one of the dependencies: 
Name: InstallationSupport
Version: 5.2.9
Enabled by Default: Yes
Status: Enabled
Dependencies: None
Startup Tasks: None
Name: CriticalTimeMonitoring
Version: 5.2.9
Enabled by Default: No
Status: Disabled
Deactivation reason: Did not meet one of the dependencies: 
Name: Audit
Version: 5.2.9
Enabled by Default: Yes
Status: Enabled
Dependencies: None
Startup Tasks: None
Name: AutoSubscribe
Version: 5.2.9
Enabled by Default: Yes
Status: Enabled
Dependencies: None
Startup Tasks: ApplySubscriptions
Name: MsmqSubscriptionPersistence
Version: 5.2.9
Enabled by Default: No
Status: Enabled
Dependencies: None
Startup Tasks: None
Name: Scheduler
Version: 5.2.9
Enabled by Default: Yes
Status: Enabled
Dependencies: None
Startup Tasks: None
Name: CustomSerialization
Version: 5.2.9
Enabled by Default: Yes
Status: Disabled
Deactivation reason: Did not fulfill its Prerequisites:
   -CustomSerialization not enable since serialization definition not detected.
Name: ForwardReceivedMessages
Version: 5.2.9
Enabled by Default: Yes
Status: Disabled
Deactivation reason: Did not fulfill its Prerequisites:
   -No forwarding address was defined in the unicastbus config
Name: RegisterHandlersInOrder
Version: 5.2.9
Enabled by Default: Yes
Status: Enabled
Dependencies: None
Startup Tasks: None
Name: SLAMonitoring
Version: 5.2.9
Enabled by Default: No
Status: Disabled
Deactivation reason: Did not meet one of the dependencies: 
Name: LicenseReminder
Version: 5.2.9
Enabled by Default: Yes
Status: Enabled
Dependencies: None
Startup Tasks: None
Name: Outbox
Version: 5.2.9
Enabled by Default: No
Status: Disabled
Deactivation reason: Did not meet one of the dependencies: 
Name: InMemoryGatewayPersistence
Version: 5.2.9
Enabled by Default: No
Status: Disabled
Deactivation reason: Did not meet one of the dependencies: [Gateway]
Name: InMemoryOutboxPersistence
Version: 5.2.9
Enabled by Default: No
Status: Disabled
Deactivation reason: Did not meet one of the dependencies: [Outbox]
Name: InMemorySagaPersistence
Version: 5.2.9
Enabled by Default: No
Status: Disabled
Deactivation reason: Did not meet one of the dependencies: [Sagas]
Name: InMemorySubscriptionPersistence
Version: 5.2.9
Enabled by Default: No
Status: Disabled
Deactivation reason: Did not meet one of the dependencies: [MessageDrivenSubscriptions]
Name: InMemoryTimeoutPersistence
Version: 5.2.9
Enabled by Default: No
Status: Disabled
Deactivation reason: Did not meet one of the dependencies: [TimeoutManager]
Name: TimeoutManagerBasedDeferral
Version: 5.2.9
Enabled by Default: No
Status: Enabled
Dependencies: None
Startup Tasks: None
Name: UnicastBus
Version: 5.2.9
Enabled by Default: Yes
Status: Enabled
Dependencies: None
Startup Tasks: None
Name: BinarySerialization
Version: 5.2.9
Enabled by Default: Yes
Status: Disabled
Deactivation reason: Did not fulfill its Prerequisites:
   -BinarySerialization not enable since serialization definition not detected.
Name: BsonSerialization
Version: 5.2.9
Enabled by Default: Yes
Status: Disabled
Deactivation reason: Did not fulfill its Prerequisites:
   -BsonSerialization not enable since serialization definition not detected.
Name: JsonSerialization
Version: 5.2.9
Enabled by Default: Yes
Status: Enabled
Dependencies: None
Startup Tasks: None
Name: XmlSerialization
Version: 5.2.9
Enabled by Default: Yes
Status: Disabled
Deactivation reason: Did not fulfill its Prerequisites:
   -XmlSerialization not enable since serialization definition not detected.
Name: MsmqTransportConfigurator
Version: 5.2.9
Enabled by Default: No
Status: Enabled
Dependencies: None
Startup Tasks: None
Name: TimeoutManager
Version: 5.2.9
Enabled by Default: No
Status: Enabled
Dependencies: [TimeoutManagerBasedDeferral]
Startup Tasks: None
Name: Sagas
Version: 5.2.9
Enabled by Default: Yes
Status: Disabled
Deactivation reason: Did not fulfill its Prerequisites:
   -No sagas was found in scanned types
Name: SecondLevelRetries
Version: 5.2.9
Enabled by Default: Yes
Status: Enabled
Dependencies: [ForwarderFaultManager]
Startup Tasks: None
Name: DataBusFileBased
Version: 5.2.9
Enabled by Default: No
Status: Disabled
Deactivation reason: Did not meet one of the dependencies: [DataBus]
Name: StorageDrivenPublishing
Version: 5.2.9
Enabled by Default: No
Status: Enabled
Dependencies: None
Startup Tasks: None
Name: MessageDrivenSubscriptions
Version: 5.2.9
Enabled by Default: No
Status: Enabled
Dependencies: None
Startup Tasks: None

РЕДАКТИРОВАНИЕ № 2:

После применения предложений Дэвида и сведения конфигурации к минимуму я по-прежнему получаю исключение ТОЛЬКО при использовании MsmqPersistence вместо InMemoryPersistence. Я не пробовал другие постоянные хранилища.

Это исключение вызывается приложением MVC с полной шиной (не SendOnlyBus) и настроено следующим образом:

    public void ConfigureServiceBus( IContainer container, IAppBuilder app )
    {
        var busConfiguration = new BusConfiguration();

        busConfiguration.UseContainer<AutofacBuilder>( c => c.ExistingLifetimeScope( container ) );
        busConfiguration.EnableInstallers();

        var inc = AllAssemblies.Matching( "Company." )
                                            .And( "NServiceBus" )
                                            .And( "ServiceControl" );
        config.AssembliesToScan( inc );

        config.UsePersistence<MsmqPersistence>();
        config.UseSerialization<JsonSerializer>();
        config.UseTransport<MsmqTransport>();

        config.EndpointName( endpointName );

        var startableBus = NServiceBus.Bus.Create( busConfiguration );
        startableBus.Start();
    }

Возникло исключение: «System.NullReferenceException» в NServiceBus.Core.dll. Дополнительная информация: ссылка на объект не указывает на экземпляр объекта.

Стек вызовов:

ServiceBus.Core.dll!NServiceBus.Timeout.Hosting.Windows.TimeoutPersisterReceiver.Poll(object obj) Строка 90 C#

Конфигурация Autofac в MVC:

public static IContainer ConfigureAutofac( IAppBuilder app )
{
    ContainerBuilder builder = new ContainerBuilder();

    // Register your MVC controllers.
    builder.RegisterControllers( typeof( MvcApplication ).Assembly );

    builder.RegisterType<...>().AsImplementedInterfaces();
    //...

    // Set the dependency resolver to be Autofac.
    IContainer container = builder.Build();

    var resolver = new Autofac.Integration.Mvc.AutofacDependencyResolver( container );

    DependencyResolver.SetResolver( resolver );

    return container;
}

Опять же, это происходит в приложении MVC с MsmqPersistence, которое подписывается на события, публикуемые Some_Endpoint. Упомянутый выше хост WCF изначально отправляет команды этой Some_Endpoint.


person John    schedule 02.11.2015    source источник
comment
С NServiceBus 5.0 вам нужно выбрать какую-то форму постоянства. Можете ли вы отредактировать вопрос, указав, как настроен экземпляр BusConfiguration?   -  person David Boike    schedule 03.11.2015
comment
@DavidBoike Я обновил вопрос. Как упоминалось выше, я использую IProvideConfiguration‹›, который, согласно вашей книге, можно использовать для настройки конфигурации (вместо чтения из app.config). Что мне не хватает? Спасибо!   -  person John    schedule 03.11.2015
comment
Было бы полезно включить весь код, который касается экземпляра BusConfiguration, а не только метод расширения. Откуда ты это звонишь? Вы самостоятельно размещаете или используете хост NServiceBus? Также в логе должен быть блок, выводящий состояние всех фич. Вставьте любой из этих блоков, содержащих слово timeout.   -  person David Boike    schedule 04.11.2015
comment
@John обратите внимание, что вы используете InMemoryPersistence, поэтому ваши расписания не переживут перезапуски.   -  person Sean Feldman    schedule 04.11.2015
comment
@DavidBoike да, InMemPersistence предназначен только для разработки. Метод расширения, который я представил в вопросе, - это единственное, что происходит для всех конечных точек. Нет app.config нигде. Все размещены на NServiceBus.Host.   -  person John    schedule 06.11.2015
comment
Как насчет дампа функций?   -  person David Boike    schedule 12.11.2015
comment
@DavidBoike Теперь я получаю ту же ошибку на своем хосте WCF. Я обновил вопрос, чтобы предоставить больше информации о конфигурации. Любопытно, что ни одна другая конечная точка не имеет такой же ошибки.   -  person John    schedule 12.11.2015


Ответы (1)


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

Сканирование сборки

Этот фрагмент кода контролирует, какие сборки сканируются на наличие типов, важных для NServiceBus:

var includesBuilder = AllAssemblies.Matching( "Company.App." );
config.AssembliesToScan( includesBuilder );

Это может привести к странным вещам, если вы случайно исключите важные сборки. Использование AllAssemblies пытается добавить сборки NServiceBus, но вы наверняка исключаете любые плагины ServiceControl.

Если возможно, проще просто опустить этот раздел и разрешить конечной точке сканировать все сборки в каталоге.

Лучше бы:

config.AssembliesToScan(AllAssemblies.Matching("Company.App.")
    .And("NServiceBus")
    .And("ServiceControl"));

Или, что еще лучше, не добавляйте в белый список, а используйте черный список, если вам это абсолютно необходимо, потому что у вас есть какая-то сумасшедшая сборка с тысячами несвязанных типов, которые вы не хотите сканировать:

config.AssembliesToScan(AllAssemblies.Except("CrazyAssemblies"));

ОтправитьТолько

В вашем фрагменте кода WCF вы создаете шину только для отправки, но у вас есть несколько странных вариантов конфигурации над ней:

config.EnableInstallers(); //ensures msmq is created
config.PurgeOnStartup( true ); //only for self-hosted

config.Transactions().Disable();
config.DisableFeature<StorageDrivenPublishing>();

Bus = NServiceBus.Bus.CreateSendOnly( config ); //create SendOnlyBus here

Конечная точка только для отправки по определению не получает сообщения, поэтому не создает очереди. EnableInstallers() не понадобится, т.к. не нужно настраивать очереди. PurgeOnStartup(true) не имеет особого смысла, так как нет очереди на очистку.

Кроме того, вы говорите о сагах и очередях с тайм-аутом, но конечная точка только для отправки не может обрабатывать сообщения, что означает отсутствие саг. Эти комбинации вещей могут вызывать странные пограничные случаи.

Включение/отключение функций

Я вижу несколько вызовов, отключающих определенные функции:

config.DisableFeature<SecondLevelRetries>();    //turn off for in-mem persistence, otherwise could lose messages

config.DisableFeature<StorageDrivenPublishing>();

SecondLevelRetries — это одна из вещей, для которой требуются тайм-ауты, поэтому, если вы отключите это и у вас не будет саг, я могу увидеть, где может быть уникальная комбинация настроек, которая приведет к тому, что сохранятель тайм-аута InMemory не будет зарегистрирован, что было бы ошибкой.

Обратите внимание, что в выводе вашей функции:

  • InMemoryTimeoutPersistence отключен из-за TimeoutManager
  • Тем не менее, TiemoutManager включен. Это может возможно быть ошибкой.

Вы всегда можете попытаться форсировать проблему:

config.EnableFeature<InMemoryTimeoutPersistence>();

Но обычно лучше позволить функциям разобраться во всем самим, а не включать/отключать их по отдельности.

Заметки, связанные с парой:

  1. Отключение SecondLevelRetries для того, чтобы не терять сообщения, является своего рода обратным. С сохранением в памяти вы будете терять сообщения. Подходит только для разработки. Для производства вы должны использовать один из других вариантов сохранения. Однако я вижу, как было бы полезно пропустить SLR в разработке, чтобы не повторять трассировки исключений при отладке.
  2. Почему вы отключаете StorageDrivenPublishing? MSMQ не имеет встроенного Pub/Sub (как в RabbitMQ или служебной шине Azure), поэтому без этой функции вы вообще не сможете публиковать события.

Разнообразный

Это может быть связано с тем, как настроен ваш контейнер Autofac, прежде чем вы передадите его в NServiceBus. Трудно предположить, так как я не вижу этот код.

Я попытался воспроизвести код с предоставленным вами кодом, и мне не удалось заставить его потерпеть неудачу. Если ничего из вышеперечисленного не работает и можно сделать простую реплику (например, шину, созданную в рамках простого проекта консольного приложения Windows), то это должно быть довольно легко исправить или, по крайней мере, сделать убедитесь, что предоставлено лучшее сообщение об ошибке.

РЕДАКТИРОВАТЬ: MsmqPersistence

Имеет смысл получить исключение NullReferenceException при использовании MsmqPersistence. MsmqPersistence включает ТОЛЬКО хранилище по подписке. Он не предоставляет реализации других типов сохраняемости, включая тайм-ауты, саги, шлюз и исходящие. (может я что-то пропустил?)

В любом случае, MsmqPersistence — это пережиток. Не используйте его!

Для разработки можно использовать in-memory. Для других сред вы должны использовать NHibernate или RavenDB.

person David Boike    schedule 12.11.2015
comment
спасибо Дэвид за этот исчерпывающий ответ. Единственное наблюдение, которое мне удалось сделать в дебрях конфигурации, заключается в следующем: как только я заменил сохраняемость msmq на сохраняемость в памяти, исключение IPersistTimeouts исчезло. Я попробую ваши предложения. - person John; 12.11.2015
comment
Я снова обновил вопрос. Исключение немного отличается после применения всех ваших предложений, но только при использовании msmq-persistence. - person John; 12.11.2015