2015-10-23 3 views
4

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

В пунктах повестки дня есть положения. Два пользователя могли бы посмотреть одно и то же назначение в той же повестке дня, в том же приложении. Они запускают это приложение через удаленный сеанс на центральном сервере. Поэтому, если пользователь 1 обновляет состояние назначения, я бы хотел, чтобы пользователь 2 увидел новое состояние «в реальном времени».

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

В классе Программный метод Main Я написал следующий код :

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(); 
} 

в методе EndPointConfig класса Настройка Я добавил:

configuration.UsePersistence<InMemoryPersistence>(); 
configuration.UseSerialization<XmlSerializer>(); 
configuration.UseTransport<MsmqTransport>(); 
ConventionsBuilder conventions = configuration.Conventions(); 
conventions.DefiningEventsAs(t => t.Namespace != null 
    && t.Namespace.Contains("Events")); 

AppointmentStateChanged простой класс в папке События, как так:

public class AppointmentStateChanged: IEvent { 
    public int AppointmentID { get; set; } 
    public string NewState { get; set; } 
} 

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); 
    } 
} 

Если я запустить один консольного приложения все работает отлично. Я вижу, что обработчик обрабатывает событие. Но если я попытаюсь запустить второе консольное приложение, он сработает с: System.Messaging.MessageQueueException (время ожидания для запрошенной операции истекло). Поэтому я должен делать что-то неправильно и заставляю меня предположить, что я не понимаю чего-то на более высоком уровне. Может ли кто-нибудь указать мне в правильном направлении, пожалуйста?

Update Everthing находится в пространстве имен AgendaUpdates, для класса событий, который находится в пространстве имен AgendaUpdates.Events кроме.

Update 2 шаги:

  • Скопировано решение AgendaUpdates (в папку AgendaUpdates2)
  • В копии я изменил MessageEndpointMappings в App.Config атрибут конечной точки "AgendaUpdates2" я получил Исключение MSMQ: «очередь не существует или у вас нет достаточных разрешений для выполнения операции»
  • В копии я добавил эту строку кода в E ndPointConfig: configuration.EndpointName ("AgendaUpdates2"); я получил MSMQ исключения: «очередь не существует или у вас нет достаточных полномочий для выполнения операции»
  • В копии я добавил эту строку коды в Main methodin класса программы: configuration.EndpointName ("AgendaUpdates2"); После повторного нажатия на кнопку снова появилось исключительное исключение.

-> Я проверил его, запустив 2 визуальных студии с оригинальным и скопированным решением. А затем запустите оба консольных приложения в среде IDE.

ответ

1

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

Это ясно объясняется в this article, где решение вашей проблемы полностью находится в конце статьи.

3

Я не совсем уверен, почему вы получаете это исключение , но я могу объяснить, почему то, что вы пытаетесь сделать, не удается. Проблема заключается не в том, что издатель и подписчик в одном приложении (это возможно и может быть полезно); проблема в том, что вы запускаете два экземпляра одного и того же приложения на одном компьютере.

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

Есть несколько вещей, которые вы можете подправлять, чтобы получить свой сценарий, чтобы работать и, чтобы лучше понять, как работает очередями:

  1. Изменение EndPointName вашего второго экземпляра
  2. Запустите второй экземпляр на отдельный машина
  3. отдельные издатель и подписчик на отдельные процессы

Независимо от того, какой путь вы идете, вам нужно будет настроить вас г MessageEndpointMappings (на потребителя/абонента), чтобы отразить, где очередь хозяин/издатель живет («владельца» типа сообщения):

http://docs.particular.net/nservicebus/messaging/message-owner#configuring-endpoint-mapping

Редактировать на основе ваших обновлений

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

Кроме того, убедитесь, что вы используете обе IDE в качестве администратора на вашем компьютере. Я не уверен, что это мешает или нет.

В копии я изменил MessageEndpointMappings в App.Config атрибут конечной точки «AgendaUpdates2» Я получил MSMQ исключение: «очередь не существует или у вас нет достаточных полномочий для выполнения операции»

Поскольку копия является клиентом, вы хотите указать его сопоставление с хостом. Таким образом, это должно быть «AgendaUpdates» (опустить «2»).

В копии я добавил эту строку кода в EndPointConfig: configuration.EndpointName ("AgendaUpdates2"); Я получил MSMQ исключения: «очередь не существует или у вас нет достаточных полномочий для выполнения операции»

В копии я добавил эту строку коды в Main methodin класса программы: configuration.EndpointName ("AgendaUpdates2"); Снова вызвало оригинальное исключение после нажатия клавиши

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

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

+1

В вопросе вы опустили пространство имен, которое используется для указания имени конечной точки. Как говорит Фил, убедитесь, что у обеих есть своя уникальная очередь и укажите имя в коде, согласно документации, которую он предоставляет. Нет ничего плохого в том, что у издателя и подписчика есть тот же процесс. И все должно работать нормально на одной машине, необходимость развертывания на отдельной машине - это решение, принятое операциями и не имеющее никакого отношения к вашему коду. –

+0

@Phil Sandler/@ Dennis van der Stelt Спасибо, что ответили. Я пытался реализовать ваши предложения, но я просто не могу заставить его работать. Я добавил stepts, сделанные в обновлении 2. Что я сделал неправильно? –

+0

Обновлен мой ответ. –

Смежные вопросы