C# 同一应用程序是否可以同时作为发布服务器/订阅服务器和NServiceBus?
我不熟悉消息传递体系结构,所以我可能走错了方向。但我想通过解决一个小问题,在我的团队中慢慢引入NServiceBus 议程中的任命有国家。两个用户可以在同一个应用程序中查看同一议程中的同一约会。他们通过中央服务器上的远程会话启动此应用程序。因此,如果用户1更新约会的状态,我希望用户2看到新状态“实时” 为了模拟这一点或进行概念验证(如果您愿意),我制作了一个新的控制台应用程序。通过NuGet,我同时获得了NServiceBus和NServiceBus.Host,因为从文档中我了解到,我需要这两个。我知道,在生产代码中,不建议将所有内容都放在同一个程序集中,但是发布者和订阅者很可能最终都放在同一个程序集中 在类程序方法Main中,我编写了以下代码:C# 同一应用程序是否可以同时作为发布服务器/订阅服务器和NServiceBus?,c#,msmq,nservicebus,C#,Msmq,Nservicebus,我不熟悉消息传递体系结构,所以我可能走错了方向。但我想通过解决一个小问题,在我的团队中慢慢引入NServiceBus 议程中的任命有国家。两个用户可以在同一个应用程序中查看同一议程中的同一约会。他们通过中央服务器上的远程会话启动此应用程序。因此,如果用户1更新约会的状态,我希望用户2看到新状态“实时” 为了模拟这一点或进行概念验证(如果您愿意),我制作了一个新的控制台应用程序。通过NuGet,我同时获得了NServiceBus和NServiceBus.Host,因为从文档中我了解到,我需要这两个
BusConfiguration configuration = new BusConfiguration();
configuration.UsePersistence<InMemoryPersistence>();
configuration.UseSerialization<XmlSerializer>();
configuration.UseTransport<MsmqTransport>();
configuration.TimeToWaitBeforeTriggeringCriticalErrorOnTimeoutOutages(new TimeSpan(1, 0, 0));
ConventionsBuilder conventions = configuration.Conventions();
conventions.DefiningEventsAs(t => t.Namespace != null
&& t.Namespace.Contains("Events"));
using (IStartableBus bus = Bus.Create(configuration))
{
bus.Start();
Console.WriteLine("Press key");
Console.ReadKey();
bus.Publish<Events.AppointmentStateChanged>(a =>
{
a.AppointmentID = 1;
a.NewState = "New state";
});
Console.WriteLine("Event published.");
Console.ReadKey();
}
AppointmentStateChangedHandler是事件处理程序:
public class AppointmentStateChangedHandler : IHandleMessages<Events.AppointmentStateChanged> {
public void Handle(Events.AppointmentStateChanged message) {
Console.WriteLine("AppointmentID: {0}, changed to state: {1}",
message.AppointmentID,
message.NewState);
}
}
public class AppointmentStateChangedHandler:IHandleMessages{
公共无效句柄(Events.AppointmentStateChanged消息){
WriteLine(“AppointmentID:{0},更改为状态:{1}”,
message.AppointmentID,
message.NewState);
}
}
如果我启动一个控制台应用程序,一切正常。我看到处理程序处理该事件。但如果我尝试启动第二个控制台应用程序,它会崩溃:System.Messaging.MessageQueueException(请求的操作超时已过期)。所以我一定是做错了什么,让我再次猜测我不理解更高层次的东西。谁能给我指一下正确的方向吗
更新
除AgendaUpdate.Events命名空间中的事件类外,所有内容都位于AgendaUpdate命名空间中
更新2
采取的步骤:
- 复制的AgendaUpdate解决方案(到AgendaUpdate文件夹)
- 在副本中,我将App.Config中的MessageEndpointMappings端点属性更改为“AgendaUpdates2” 我收到MSMQ异常:“队列不存在或您没有足够的权限执行该操作”
- 在副本中,我将这行代码添加到EndPointConfig:configuration.EndpointName(“AgendaUpdates2”); 我收到MSMQ异常:“队列不存在或您没有足够的权限执行该操作”
- 在副本中,我将这行代码添加到Program类的Main方法中: configuration.EndpointName(“AgendaUpdates2”); 按此键后再次获取原始异常
-->我用原始和复制的解决方案启动了2个VisualStudio来测试它。然后在IDE中启动两个控制台应用程序 我不太清楚为什么会出现这种特殊的异常,但我可以解释为什么您尝试的操作失败了。问题在于发布服务器和订阅服务器不在同一个应用程序中(这是可能的,并且可能很有用);问题是您在同一台计算机上运行同一应用程序的两个实例 NServiceBus依赖于队列技术(在您的例子中是MSMQ),要使一切正常工作,每个应用程序都需要有自己独特的队列。当您启动两个相同的实例时,两个实例都试图共享同一队列 为了让场景正常工作,更好地理解排队是如何工作的,您可以修改以下几点:
这听起来很合理,但请记住,如果您的副本是订阅者,则不应发布副本,因此在副本启动后不要按任何键(仅按原件中的键)。如果您希望发布者同时也是消息的接收者,请在配置中指定此项
这一点在中有清楚的解释,其中问题的解决方案完全在文章的末尾。在问题中,您省略了用于指定端点名称的名称空间。正如Phil所说,确保两者都有自己独特的队列和spe
public class AppointmentStateChanged: IEvent {
public int AppointmentID { get; set; }
public string NewState { get; set; }
}
public class AppointmentStateChangedHandler : IHandleMessages<Events.AppointmentStateChanged> {
public void Handle(Events.AppointmentStateChanged message) {
Console.WriteLine("AppointmentID: {0}, changed to state: {1}",
message.AppointmentID,
message.NewState);
}
}