Wracamy do serii wpisów o nServiceBus. Koniecznie zapraszam najpierw do przeczytania następujących postów:
http://www.pzielinski.com/?cat=29
Szczególnie pierwszy wpis o teoretycznych zagadnieniach będzie tutaj ważny. Dzisiaj zajmiemy się na przykładzie jak wędruje wiadomość od jednego węzła do drugiego oraz co stanie się, gdy serwer nie będzie dostępny.
Dla przypomnienia, w poprzednim wpisie stworzyliśmy handler:
class AddPersonHandler:IHandleMessages<AddPerson> { public void Handle(AddPerson message) { Console.WriteLine("Dodawanie osoby: {0} {1}",message.FirstName,message.LastName); } }
Komendę AddPerson:
public class AddPerson:IMessage { public string FirstName { get; set; } public string LastName { get; set; } }
A także klienta, który wysyła wiadomości w następujący sposób:
var busConfiguration = new BusConfiguration(); busConfiguration.UsePersistence<RavenDBPersistence>(); ISendOnlyBus bus = Bus.CreateSendOnly(busConfiguration); while (true) { string firstName = Console.ReadLine(); string lastName = Console.ReadLine(); bus.Send(new AddPerson() {FirstName = firstName, LastName = lastName}); }
Jak już wiemy z pierwszego wpisu, z kolejek korzystamy m.in. wtedy, gdy zależy nam na niezawodności dostarczenia wiadomości. System kolejkowy odporny jest na sytuacje, gdy połączenie sieciowe między węzłami jest przerwane tymczasowo. nServiceBus (a raczej kolejki) zadbają, aby wiadomość została dostarczona, jak tylko połączenie zostanie przywrócone.
Zróbmy więc eksperyment. Odpalmy tylko klienta i wyślijmy kilka wiadomości:
Jak widać, wysłanie powiodło się. Nie widać tego na screen’ie, ale fakt, że serwer nie jest uruchomiony, nie przeszkadza w żaden sposób na wysłanie wiadomości za pomocą:
bus.Send(new AddPerson() {FirstName = firstName, LastName = lastName});
Nie było również żadnego blokowania jak to w przypadku synchronicznych wywołań. Oczywiście, jak zostało to napisane w pierwszym poście, wiadomość została umieszczona w kolejce wiadomości wychodzących i potem przychodzących:
Zajrzyjmy zatem do kolejek. W tym celu odpalamy Computer Management i przechodzimy do Services and Applications –> Message Queuing:
Kolejka w której umieszczane są wiadomości do przetworzenia, to w tym przypadku Example.API (taką dałem nazwę projektowi, w którym znajdują się handler’y):
Są tam dokładnie dwie pozycje, ponieważ dane dwóch osób wpisaliśmy w konsoli. Klikając na jedną z nich, dowiemy się o szczegółach:
Widzimy, że reprezentuje to dokładnie naszą wiadomość AddPerson.
Po uruchomieniu serwera, wiadomości zostaną zdjęte z kolejki i przetworzone:
Klient zatem nie interesuje się kiedy serwer otrzyma to wiadomość, co jest przeciwieństwem RPC. Widzimy tam również trzy inne kolejki, którym przyjrzyjmy się kiedyś indziej, ale służą one do obsługi błędów.
Wiadomość może zostać odebrana dopiero np. po kilku dniach. Jeśli z punktu logiki biznesowej, wiemy, że nie ma sensu przetwarzać danej wiadomości po jakimś czasie, to można posłużyć się atrybutem TimeToBeReceived:
[TimeToBeReceived("00:00:10")] public class AddPerson:IMessage { public string FirstName { get; set; } public string LastName { get; set; } }
Jeśli AddPerson nie zostanie dostarczony w ciągu 10 sekund, system usunie wiadomość z kolejki.
Na początku serii wpisów pisałem o kolejkach wiadomości przychodzących i wychodzących. W powyższym wpisie, pokazałem wyłącznie jedną kolejkę Wynika to z faktu, że prezentuje to na jednym, tym samym komputerze. nServiceBus po prostu rozpozna to i kolejka wiadomości wychodzących klienta stanowi tak naprawdę kolejkę wiadomości przychodzących serwera. Jeśli korzystaliśmy z serwera zdalnego, wtedy byśmy mieli jeszcze jedną kolejkę w sekcji Outgoing Queues.