Подписки на события NServiceBus не работают со служебной шиной Azure

Я пытаюсь изменить Магазин видео на основе Azure образец приложения, чтобы интерфейсный сайт электронной торговли мог масштабироваться.

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

Ниже представлена ​​моя текущая конфигурация в Global.asax:

        Feature.Disable<TimeoutManager>();

        Configure.ScaleOut(s => s.UseUniqueBrokerQueuePerMachine());

        startableBus = Configure.With()
            .DefaultBuilder()
            .TraceLogger()
            .UseTransport<AzureServiceBus>()
            .PurgeOnStartup(true)
            .UnicastBus()
            .RunHandlersUnderIncomingPrincipal(false)
            .RijndaelEncryptionService()
            .CreateBus();

        Configure.Instance.ForInstallationOn<Windows>().Install();

        bus = startableBus.Start();

И я также настроил очереди служебной шины Azure, используя:

class AzureServiceBusConfiguration : IProvideConfiguration<NServiceBus.Config.AzureServiceBusQueueConfig>
{
    public AzureServiceBusQueueConfig GetConfiguration()
    {
        return new AzureServiceBusQueueConfig()
        {
            QueuePerInstance = true     
        };
    }
}

Я установил масштабирование веб-роли до двух экземпляров, и, как и ожидалось, создаются две очереди (электронная торговля и электронная торговля-1). Однако я не вижу дополнительных подписок, создаваемых в разделе videostore.sales.events. Вместо этого я вижу:

Отсутствующие подписки

Я думаю, вы увидите подписки VideoStore.ECommerce-1.OrderCancelled и VideoStore.ECommerce-1.OrderPlaced в разделе Videostore.Sales.Events. Или не так хранятся подписки при использовании служебной шины Azure?

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

Мне также кажется странным, что создаются две очереди ошибок и аудита. Почему так могло случиться?

ОБНОВЛЕНИЕ

Ив прав. AzureServiceBusSubscriptionNamingConvention не применял правильное индивидуализированное имя. Мне удалось это исправить, реализовав следующий EndpointConfig:

namespace VideoStore.ECommerce
{
    public class EndpointConfig : IConfigureThisEndpoint, IWantCustomInitialization
    {
        public void Init()
        {
            AzureServiceBusSubscriptionNamingConvention.Apply = BuildSubscriptionName;
            AzureServiceBusSubscriptionNamingConvention.ApplyFullNameConvention = BuildSubscriptionName;
        }

        private static string BuildSubscriptionName(Type eventType)
        {
            var subscriptionName = eventType != null ? Configure.EndpointName + "." + eventType.Name : Configure.EndpointName;

            if (subscriptionName.Length >= 50)
                subscriptionName = new DeterministicGuidBuilder().Build(subscriptionName).ToString();

            if (!SettingsHolder.GetOrDefault<bool>("ScaleOut.UseSingleBrokerQueue"))
                subscriptionName = Individualize(subscriptionName);

            return subscriptionName;
        }

        public static string Individualize(string queueName)
        {
            var parser = new ConnectionStringParser();
            var individualQueueName = queueName;
            if (SafeRoleEnvironment.IsAvailable)
            {
                var index = parser.ParseIndexFrom(SafeRoleEnvironment.CurrentRoleInstanceId);

                var currentQueue = parser.ParseQueueNameFrom(queueName);
                if (!currentQueue.EndsWith("-" + index.ToString(CultureInfo.InvariantCulture))) //individualize can be applied multiple times
                {
                    individualQueueName = currentQueue
                                              + (index > 0 ? "-" : "")
                                              + (index > 0 ? index.ToString(CultureInfo.InvariantCulture) : "");
                }
                if (queueName.Contains("@"))
                    individualQueueName += "@" + parser.ParseNamespaceFrom(queueName);
            }

            return individualQueueName;
        }
    }
}

Однако мне не удалось заставить NServiceBus распознавать мой класс EndpointConfig. Вместо этого мне пришлось вызывать его вручную перед запуском автобуса. Из моего Global.asax.cs:

new EndpointConfig().Init();
bus = startableBus.Start();

Как только я это сделал, названия подписок появились, как и ожидалось:

Правильные подписки

Не уверен, почему он игнорирует мой IConfigureThisEndpoint, но это работает.


person RMD    schedule 04.06.2014    source источник


Ответы (1)


Это похоже на ошибку, можете ли вы поднять проблему с github по этому поводу на https://github.com/Particular/NServiceBus.Azure

Тем не менее, я думаю, что лучше использовать функцию масштабирования signalr вместо использования QueuePerInstance, поскольку signalr необходимо реплицировать другую информацию, такую ​​как (сопоставления соединений / групп), внутренне, при работе в режиме масштабирования.

Обновлять:

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

.com / Particular / NServiceBus.Azure / blob / master / src / NServiceBus.Azure.Transports.WindowsAzureServiceBus / NamingConventions / AzureServiceBusSubscriptionNamingConvention.cs

пока он в очереди

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

https://github.com/Particular/NServiceBus.Azure/blob/master/src/NServiceBus.Azure.Transports.WindowsAzureServiceBus/Config/QueueIndividualizer.cs

person Yves Goeleven    schedule 05.06.2014
comment
Я добавлю ошибку, но как насчет сценариев, в которых я делаю что-то вроде аннулирования кеша? В таком случае QueuePerInstance - это именно то, что мне нужно, верно? Эта проблема характерна для работы в Azure? - person RMD; 05.06.2014
comment
YVes - оказывается, проблема не в именовании очереди. Вместо этого, я думаю, может быть проблема с подписками на мероприятия. Я пересматриваю свой пост и закрываю проблему с github. - person RMD; 18.06.2014
comment
Я отредактировал сообщение выше. Есть предположения? - person RMD; 18.06.2014
comment
Обновил мой исходный ответ (здесь недостаточно места) - person Yves Goeleven; 18.06.2014
comment
Это имеет смысл. Я действительно пошел по этому пути. В каких проектах следует применять это соглашение? Из того, что я прочитал, обычно сообщение отправляется от подписчика издателю, а затем издатель регистрирует подписчика. В этом случае подписчик сам создает подписку на тему, поскольку обмен сообщениями осуществляется через посредника? - person RMD; 18.06.2014
comment
Да, это сам подписчик создает. Таким образом, вы должны установить измененное соглашение в конечных точках подписки. - person Yves Goeleven; 18.06.2014
comment
Спасибо - проблема решена, но если вы видите мое обновление выше, у меня все еще есть 2 нерешенных проблемы. Во-первых, EndpointConfig в веб-роли не вызывается. Пришлось вручную вызывать. Во-вторых, он все еще создает очередь ошибок и аудита с суффиксом, чего, как я подозреваю, не должно происходить. - person RMD; 18.06.2014
comment
То, что конфигурация конечной точки не вызывается, нормально, это часть хост-процесса, но вы запускаете все вручную в веб-роли - person Yves Goeleven; 18.06.2014
comment
Мне нужно заглянуть в очередь аудита, это ожидаемое поведение, как вы сказали, для создания очередей для каждого экземпляра, но, возможно, это нежелательное поведение ... - person Yves Goeleven; 18.06.2014
comment
Я подозреваю, что это нежелательное поведение, особенно если ServiceControl полагается на эти очереди. Имеет ли это? - person RMD; 19.06.2014
comment
В целом, недействительность кеша - не используйте NServiceBus вместе с внутрипроцессным кешированием для реализации вашего собственного распределенного кеша. Если вам нужен распределенный кеш, выберите тот, который уже существует. - person Udi Dahan; 21.12.2014
comment
@UdiDahan - Я знаю, откуда вы, но в данном случае у нас все работает хорошо. Простая оболочка вокруг MemoryCache, которая делает недействительными кэшированные группы элементов, когда они получают события от NSB. У нас есть некоторые требования, связанные с HIPAA, которые не позволяют нам использовать много сторонних распределенных кешей. - person RMD; 10.01.2015