Я пытаюсь изменить Магазин видео на основе 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, но это работает.