我正在尝试修改Azure-based Video Store sample app,以便前端电子商务网站可以扩展。
具体来说,我希望通过OrderPlaced等事件通知网站的所有实例,这样无论客户端Web应用程序通过SignalR连接到哪个Web服务器,它都会正确接收通知并更新UI。
以下是我在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 Service Bus队列:
class AzureServiceBusConfiguration : IProvideConfiguration<NServiceBus.Config.AzureServiceBusQueueConfig>
{
public AzureServiceBusQueueConfig GetConfiguration()
{
return new AzureServiceBusQueueConfig()
{
QueuePerInstance = true
};
}
}
我已将网络角色设置为扩展为两个实例,并且正如预期的那样,会创建两个队列(电子商务和电子商务-1)。但是,我没有看到在videostore.sales.events主题下创建的其他主题订阅。相反,我看到了:
我认为您会在Videostore.Sales.Events主题下看到VideoStore.ECommerce-1.OrderCancelled和VideoStore.ECommerce-1.OrderPlaced订阅。或者,这不是使用Azure Service Bus时存储订阅的方式吗?
我在这里缺少什么?我在电子商务实例的一个上获得了这个活动,但两者都没有。即使这不是扩展SignalR的正确方法,我的用例也扩展到缓存失效之类的东西。
我也觉得很奇怪,正在创建两个错误和审计队列。为什么会这样?
更新
Yves是对的。 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,但这样可行。
答案 0 :(得分:3)
这听起来像个bug,你能在https://github.com/Particular/NServiceBus.Azure
上提出一个github问题尽管如此,我认为使用信号器的横向扩展功能而不是使用QueuePerInstance更好,因为信号器需要在内部以及在横向扩展模式下运行时复制其他信息(如连接/组映射)。
更新
我认为我看到了这个问题,订阅也应该个性化,在当前的命名惯例中并非如此
虽然它在queuenamingconventions
由于这些约定是公开的,您可以通过更改IWantCustomInitialization中的func来覆盖它们以解决问题,直到我可以获得修复,只需复制当前方法并添加个性化逻辑。队列个性化器虽然是内部的,但您必须从
复制该类