Kolejkowanie wiadomości (MSMQ)
Transkrypt
Kolejkowanie wiadomości (MSMQ)
Kolejkowanie wiadomości (MSMQ)
laboratorium
2013
T. Goluch , K.M. Ocetkiewicz
1. Wstęp
Usługa kolejkowania wiadomości (znana także pod nazwą MSMQ) jest infrastrukturą obsługi wiadomości i narzędziem
programistycznym umożliwiającym tworzenie rozproszonych aplikacji do obsługi wiadomości dla systemu Microsoft
Windows. Pierwsza wersja MSMQ 1.0 powstała w 97 roku i doczekała się już wersji 5.0.
Aplikacje opracowane dla usługi kolejkowania wiadomości wysyłają wiadomości do kolejek będących
tymczasowymi lokalizacjami magazynowymi, z których wiadomości mogą docierać do swoich miejsc docelowych,
jeśli warunki na to pozwalają. Takie aplikacje mogą komunikować się ze sobą przez sieci heterogeniczne i wysyłać
wiadomości między komputerami, które tymczasowo mogą nie być w stanie połączyć się ze sobą. Usługa kolejkowania
wiadomości zapewnia następujące korzyści:
gwarantowane dostarczanie wiadomości,
wydajny routing,
zwiększone bezpieczeństwo,
obsługa wysyłania wiadomości w transakcjach,
obsługa wiadomości na podstawie priorytetów.
Dzięki usłudze kolejkowania wiadomości użytkownicy mogą komunikować się przez sieci i komputery, które mogą być
w trybie offline, niezależnie od bieżącego stanu sieci i komputerów. Administratorzy systemów mogą korzystać z
Usługi kolejkowania wiadomości do wydajnego zarządzania dużymi, złożonymi sieciami komputerów i kolejek
wiadomości.
Podstawowym zarzutem wobec MSMQ może być, brak buforowania komunikatów po stronie nadawcy.
Innymi słowy węzeł docelowy (kolejka komunikatów) musi być dostępna cały czas. Wiadomości mogą mieć nie więcej
niż 4 MB danych.
Usługa kolejkowania wiadomości może być domyślnie nie zainstalowana w systemie Windows. W celu
zainstalowania podstawowej funkcjonalności MSMQ należy odszukać w panelu sterowania opcję: włącz lub wyłącz
funkcje systemu → Serwer usługi MSMQ i zaznaczyć oraz zainstalować: Podstawowe funkcje serwera usługi MSMQ
(gotowe na wirtualnych systemach laboratoryjnych).
2. Rodzaje kolejek
Kolejki możemy podzielić na publiczne i prywatne. Kolejki publiczne wymagają aby komputer działał w
trybie domeny. Komputery pracujące w trybie grupy roboczej mogą korzystać jedynie z kolejek prywatnych. Kolejka
może być identyfikowana za pomocą ścieżki. Ścieżka składa się z dwóch części:
NazwaKomputera\NazwaKolejki.
Dodatkowo nazwy kolejek prywatnych są poprzedzone prefiksem private$. Nazwa komputera lokalnego może zostać
zastąpiona kropką. Przykładowe nazwy ścieżek:
Kaims.pl\gameQueue – kolejka publiczna gameQueue na komputerze kaims.pl.
.\gameQueue – kolejka publiczna gameQueue na komputerze lokalnym.
.\private$\gameQueue – kolejka prywatna gameQueue na komputerze lokalnym.
Dla lokalnych kolejek prywatnych można używać formatu bezpośredniego:
DIRECT=OS:.\private\NazwaKolejki.
Należy pamiętać o prawidłowym formatowaniu stringów – podwójny backslash. W .NET dodając znak @ przed
rozpoczynjącym cudzysłowem można stosować pojedynczy backslash.
T. Goluch , K.M. Ocetkiewicz
Kolejkowanie wiadomości (MSMQ)
{C91E19C4-8B08-4D63-9B7C-0913AAB2A7CE}
{C91E19C4-8B08-4D63-9B7C-0913AAB2A7CE}
1
3. MSMQ w C++
Aby korzystać z kolejek w C++ należy dołączyć plik nagłówkowy "mq.h" oraz dołączyć dla linkera bibliotekę:
mqrt.lib. Można w tym celu skorzystać z dyrektywy: #pragma comment(lib,"mqrt.lib").
Utworzenie kolejki:
HRESULT APIENTRY MQCreateQueue(
PSECURITY_DESCRIPTOR pSecurityDescriptor,
MQQUEUEPROPS * pQueueProps,
LPWSTR lpwcsFormatName,
LPDWORD lpdwFormatNameLength
);
opis parametrów:
PSECURITY_DESCRIPTOR pSecurityDescriptor – deskryptor zabezpieczeń, NULL – domyślny
poziom zabezpieczeń,
MQQUEUEPROPS * pQueueProps – wskaźnik do struktury opisującej właściwości kolejki1. Wymagane pola:
o DWORD cProp – liczba właściwości struktury MQQUEUEPROPS,
o QMPROPID aPropID[] – identyfikator właściwości:
PROPID_Q_PATHNAME – nazwa ścieżki tworzonej kolejki (wymagany) ,
PROPID_Q_LABEL – opis kolejki (opcjonalny),
PROPID_Q_JOURNAL – określa czy usunięte wiadomości trafią do kolejki dziennika.
Domyślnie nie trafią (opcjonalny),
PROPID_Q_JOURNAL_QUOTA – określa maksymalny rozmiar kolejki dziennika
(opcjonalny).
PROPID_Q_TRANSACTION – określa jest transakcyjna czy nie. Domyślnie transakcje nie są
wspierane (opcjonalny).
o PROPVARIANT aPropVar[] – struktura MQPROPVARIANT2 określająca wartość właściwości. Dla
wymaganej właściwości: PROPID_Q_PATHNAME wymagane są pola:
VARTYPE vt – indykator typu właściwości (unii). Dla PROPID_Q_PATHNAME jest to typ:
VT_LPWSTR,
LPWSTR pwszVal – ciąg znaków Unicode nazwy ścieżki kolejki,
o HRESULT aStatus[] – błąd wskazujący status właściwości (opcjonalny).
LPWSTR lpwcsFormatName – wskaźnik do nazwy ścieżki utworzonej kolejki. Dla lokalnej kolejki prywatnej
zostanie zwrócony bezpośredni format nazwy, który być wykorzystany podczas otwierania i usuwania kolejki.
LPDWORD lpdwFormatNameLengt – wskaźnik, pod który zapisana zostanie długość nazwy ścieżki (liczba
znaków Unicode).
Skasowanie kolejki:
HRESULT APIENTRY MQDeleteQueue(LPCWSTR lpwcsFormatName);
opis parametrów:
LPCWSTR lpwcsFormatName – nazwa ścieżki kolejki. Dla lokalnej kolejki prywatnej można używać formatu
bezpośredniego.
Otwarcie istniejącej kolejki:
HRESULT APIENTRY MQOpenQueue(
LPCWSTR lpwcsFormatName,
DWORD dwAccess,
DWORD dwShareMode,
QUEUEHANDLE * phQueue
1
2
http://msdn.microsoft.com/pl-pl/library/aa925380.aspx
http://msdn.microsoft.com/pl-pl/library/aa925608.aspx
T. Goluch , K.M. Ocetkiewicz
Kolejkowanie wiadomości (MSMQ)
{C91E19C4-8B08-4D63-9B7C-0913AAB2A7CE}
{C91E19C4-8B08-4D63-9B7C-0913AAB2A7CE}
2
);
opis parametrów:
LPCWSTR lpwcsFormatName – nazwa ścieżki kolejki. Dla kolejki prywatnej można używać formatu
bezpośredniego.
DWORD dwAccess – tryb dostępu (dozwolone jest stosowanie sumy binarnej w celu łączenia trybów):
o MQ_SEND_ACCESS – wstawianie nowych wiadomości (tryb domyślny),
o MQ_RECEIVE_ACCESS – czytanie i usuwanie wiadomości,
o MQ_PEEK_ACCESS – czytanie wiadomości (bez usuwania),
DWORD dwShareMode – tryb współdzielenia:
o MQ_DENY_NONE – kolejka otwarta do współdzielonego dostępu (tryb domyślny),
o MQ_DENY_RECEIVE_SHARE – kolejka otwarta do wyłącznego dostępu (przydatny aby zablokować
możliwość kasowania wiadomości innym),
QUEUEHANDLE * phQueue – uchwyt to kolejki.
Zamknięcie istniejącej kolejki:
HRESULT APIENTRY MQCloseQueue(QUEUEHANDLE hQueu);
opis parametrów:
QUEUEHANDLE hQueu – uchwyt do kolejki.
Wysłanie wiadomości:
HRESULT APIENTRY MQSendMessage(
QUEUEHANDLE hDestinationQueue,
MQMSGPROPS * pMessageProps,
ITransaction * pTransaction
);
opis parametrów:
3
4
QUEUEHANDLE hDestinationQueue – uchwyt to kolejki,
MQMSGPROPS * pMessageProps – wskaźnik do struktury wiadomości 3. Wymagane pola:
o DWORD cProp – liczba właściwości struktury MQMSGPROPS,
o QMPROPID aPropID[] – identyfikator właściwości:
PROPID_M_LABEL – opis wiadomości (wymagany),
PROPID_M_LABEL_LEN – długość bufora opisu wiadomości w liczbie znaków Unicode
(wymagany w trybie odczytu),
PROPID_M_BODY – zawartość wiadomości (opcjonalny) ,
o PROPVARIANT aPropVar[] – struktura MQPROPVARIANT4 określająca wartość właściwości. Dla
wymaganej właściwości: PROPID_M_LABEL wymagane są pola:
VARTYPE vt – indykator typu właściwości (unii). Dla PROPID_M_LABEL jest to typ:
VT_LPWSTR,
LPWSTR pwszVal – ciąg znaków Unicode nazwy wiadomości,
Dla właściwości: PROPID_M_LABEL_LEN wymagane są pola:
VARTYPE vt – indykator typu właściwości (unii). Dla PROPID_M_LABEL_LEN jest to typ:
VT_UI4,
ULONG ulVal – liczba dodatnia reprezentująca długość bufora,
Dla właściwości: PROPID_M_BODY wymagane są pola:
VARTYPE vt – indykator typu właściwości (unii). Dla PROPID_M_BODY jest to typ:
VT_VECTOR | VT_UI1,
http://msdn.microsoft.com/en-us/library/aa926091.aspx
http://msdn.microsoft.com/pl-pl/library/aa925608.aspx
T. Goluch , K.M. Ocetkiewicz
Kolejkowanie wiadomości (MSMQ)
{C91E19C4-8B08-4D63-9B7C-0913AAB2A7CE}
{C91E19C4-8B08-4D63-9B7C-0913AAB2A7CE}
3
CAUB caub – struktura zawierająca dwa pola:
ULONG cElems – liczba dodatnia reprezentująca długość bufora,
UCHAR *pElems – wskaźnik na bufor zawartości wiadomości,
o HRESULT aStatus[] – błąd wskazujący status właściwości (opcjonalny).
ITransaction * pTransaction - obiekt transakcji (dziedziczy po ITransaction) albo NULL.
Odebranie wiadomości:
HRESULT APIENTRY MQReceiveMessage(
QUEUEHANDLE hSource,
DWORD dwTimeout,
DWORD dwAction,
MQMSGPROPS * pMessageProps,
LPOVERLAPPED lpOverlapped,
PMQRECEIVECALLBACK fnReceiveCallback,
HANDLE hCursor,
ITransaction * pTransaction
);
opis parametrów:
QUEUEHANDLE hSource – uchwyt to kolejki,
DWORD dwTimeout – czas w ms oczekiwania na wiadomość (wartość domyślna INFINITE 0),
DWORD dwAction – określa w jaki sposób wiadomość jest odczytywana z kolejki:
o MQ_ACTION_RECEIVE – odczytuje wiadomość określoną położeniem kursora i usuwa ją z kolejki,
o MQ_ACTION_PEEK_CURRENT – odczytuje wiadomość określoną położeniem kursora, nie usuwa jej z
kolejki i nie przesuwa kursora,
o MQ_ACTION_PEEK_NEXT – odczytuje kolejną wiadomość, pomijając określoną położeniem kursora,
nie usuwa jej z kolejki i nie przesuwa kursora (wymaga wywołania metody MQCreateCursor,
hCursor nie może być wartością NULL),
o
MQMSGPROPS * pMessageProps – analogicznie jak przy wysyłaniu wiadomości,
LPOVERLAPPED lpOverlapped – wskaźnik do struktury (OVERLAPPED) asynchronicznej obsługi
wejścia/wyjścia.
PMQRECEIVECALLBACK fnReceiveCallback – Wskaźnik do funkcji wywołania zwrotnego.
HANDLE hCursor – Uchwyt do kursora pozwalającego na przeglądanie wiadomości w kolejce.
ITransaction * pTransaction – analogicznie jak przy wysyłaniu wiadomości.
W celu wyświetlenia w oknie konsoli łańcuchów szerokich znaków można posłużyć się funkcją: wprintf.
4. MSMQ w COM i C++
W celu komunikacji po MSMQ w C++ przy użyciu komponentu COM należy zaimportować bibliotekę
mqoa.dll oraz wygodnie jest dodać przestrzeń nazw MSMQ. Dyrektywa import wygeneruje dwa pliki: mqoa.tlh i
mqoa.tli zawierające deklaracje smart-pointerów dla wszystkich obiektów usługi kolejkowania. Należy pamiętać, że
mamy do czynienia z biblioteką COM, zatem należy wywołać funkcję CoInitialize lub CoInitializeEx oraz CoUnitialize
na końcu programu.
IMSMQQueueInfoPtr – smart pointer do interfejsu MSMQQueueInfo5 pozwalającego na zarządzanie
pojedynczą kolejką. Podczas tworzenia należy przekazać jako parametr ProgID serwera COM MSMQ:
"MSMQ.MSMQQueueInfo".
W celu utworzenia kolejki należy przypisać do właściwości PathName ścieżkę do kolejki. Można
wykorzystać właściwość Label w celu opisania kolejki. Do tworzenia oraz kasowania kolejki służą metody: Create
i Delete.
IMSMQQueuePtr – reprezentuje instancję otwartej kolejki. Jest zwracany poprzez metodę Open klasy
MSMQQueueInfo, do której należy przekazać parametry określające tryb dostępu i współdzielenia. W celu
zamknięcia kolejki należy wywołać metodę Close.
5
http://msdn.microsoft.com/en-us/library/windows/desktop/ms711396(v=vs.85).aspx
T. Goluch , K.M. Ocetkiewicz
Kolejkowanie wiadomości (MSMQ)
{C91E19C4-8B08-4D63-9B7C-0913AAB2A7CE}
{C91E19C4-8B08-4D63-9B7C-0913AAB2A7CE}
4
IMSMQMessagePtr – smart pointer do obiektu MSMQMessage6 pozwalającego na dostęp do właściwości
definiujących wiadomość oraz metod pozwalające na jej wysłanie do kolejki docelowej. Podczas tworzenia należy
przekazać jako parametr ProgID serwera COM MSMQ: "MSMQ.MSMQMessage".
W celu wysłania wiadomości należy przypisać do właściwości Label etykietę wiadomości, a do właściwości
Body treść wiadomości. Wysyłanie wiadomości zapewnia metoda: Send do której należy przekazać obiekt kolejki do
której chcemy wysłać wiadomość . Drugi parametr referencyjny, typu VARIANT, jest opcjonalny i określa czy
wywołana metoda uczestniczy w transakcji. Domyślnie usługa kolejkowania sprawdza czy bieżący obiekt COM+
uczestniczy w transakcji.
W celu odebrania wiadomości należy wywołać metodę Receive obiektu kolejki otwartej w trybie odbioru,
która zwróci obiekt wiadomości. Metoda Receive przyjmuje pięć opcjonalnych parametrów referencyjnych typu
VARIANT:
VARIANT * Transaction – analogicznie jak przy wysyłaniu,
VARIANT * WantDestinationQueue – wartość logiczna, określa czy właściwość
MSMQMessage.DestinationQueueInfo ma być aktualizowana gdy wiadomość jest odczytywana z kolejki
(domyślnie: False),
VARIANT * WantBody – wartość logiczna, określa czy treść wiadomości jest pobierana(domyślnie: True),
VARIANT * ReceiveTimeout – określa czas w ms oczekiwania na wiadomość (domyślnie: INFINITE 0),
VARIANT * WantConnectorType – wartość logiczna,określa czy usługa kolejkowania ma pobierać
właściwość MSMQMessage.ConnectorTypeGuid (domyślnie: False).
5. MSMQ w .NET i C#
W środowisku .NET do usługa kolejkowania jest dostępna poprzez klasę opakowującą: MessageQueue. Pozwala
ona na sprawdzenie czy dana kolejka już istnieje, jej utworzenie bądź skasowanie . Służą do tego metody statyczne:
Exist, Creare i Delete. Wymagają one podania nazwy ścieżki kolejki. Kolejną użyteczną funkcją statyczną jest
GetPrivateQueuesByMachine, która pozwala na otrzymać listę dostępnych kolejek na wyspecyfikowanym
komputerze. Jako parametr wymagana jest nazwa lokalnej maszyny, można ją uzyskać przy pomocy właściwości
System.Environment.MachineName.
Podczas tworzenia obiektu MessageQueue można przekazać nazwę ścieżki kolejki, bądź można później
przypisać ją do właściwości Path. Kolejka automatycznie zostaje otwarta i można już jej używać. Do zamknięcia
kolejki służy metoda Close. Do wysyłania i odbierania wiadomości służą metody: Send i Receive. Jeżeli chcemy
jedynie przeglądnąć wszystkie wiadomości w kolejce, bez usuwania ich, przydatna może okazać się metoda
GetAllMessages. Tablica wiadomości zwróconych poprzez tę metodę nie może służyć do ich modyfikowania.
W .NET możemy łatwo dokonać automatycznej serializacji i deserializacji obiektów do i z treści
wiadomości. W tym celu należy do właściwości Formatter klasy MessageQueue, przypisać obiekt klasy
dziedziczącej po interfejsie IMessageFormatter dla serializacji do XML’a będzie to klasa
XmlMessageFormatter.
Wiadomość w .NET reprezentowana jest poprzez obiekt klasy Message. Podczas tworzenia wiadomości
można przekazać jako parametr do konstruktora obiekt dowolnej klasy, a jako drugi wspomniany wcześniej
Formatter.
Klasa MessageQueueTransaction pozwala na łatwe wysyłanie i odbierania wiadomości jako części
transakcji. Polega to na przekazaniu go jako parametru do wspomnianych metod. Rozpoczęcie zatwierdzenia i
odwołanie transakcji odbywa się poprzez metody: Begin, Commit i Rollback.
6. WCF po MSMQ
W WCF można utworzyć endpointa dla MSMQ:
6
komunikacja musi być jednokierunkowa (IsOneWay = true)
adresy mają postać: net.msmq://localhost/private/nazwa
przez MSMQ nie można udostępniać metadanych
wołanie metod przez klienta nie wymaga uruchomionego serwera (wołania trafią do kolejki,
skąd później może je wydobyć serwer)
http://msdn.microsoft.com/en-us/library/windows/desktop/ms705286(v=vs.85).aspx
T. Goluch , K.M. Ocetkiewicz
Kolejkowanie wiadomości (MSMQ)
{C91E19C4-8B08-4D63-9B7C-0913AAB2A7CE}
{C91E19C4-8B08-4D63-9B7C-0913AAB2A7CE}
5
if(!MessageQueue.Exists(...)) MessageQueue.Create(...);
var bnd = new NetMsmqBinding();
bnd.Security.Mode = NetMsmqSecurityMode.None;
bnd.ExactlyOnce = false;
// jeżeli true to kolejka musi być
//transakcyjna i wiadomość będzie
//dostarczona dokładnie raz
b2.Durable = false;
// jeżeli true, to wiadomości zapisane
// trwale (na dysku) jeżeli nie, to w
// tylko pamięci (nie przeżyją upadku
// systemu
h.AddServiceEndpoint(typeof(Service1), bnd,
@"net.msmq://localhost/private/kolejka");
7. Podkolejki
Ta funkcja umożliwia logiczne grupowanie wiadomości w kolejce bez tworzenia innej kolejki fizycznej. Podkolejki są
niejawnie tworzonymi kolejkami lokalnymi, które są partycjami logicznymi kolejki fizycznej. Aplikacje mogą ich
używać do grupowania wiadomości.
8. Kolejki utraconych wiadomości
W Usłudze kolejkowania wiadomości w wersji 4.0 wprowadzono osobne kolejki utraconych wiadomości dla każdej
aplikacji, dzięki czemu każda aplikacja może korzystać z własnej kolejki utraconych wiadomości. Aplikacja może
zażądać własnej kolejki utraconych wiadomości przy użyciu właściwości PROPID_M_DEADLETTER_QUEUE jako
części wiadomości. Zamiast wysyłania wiadomości do systemowej, transakcyjnej kolejki utraconych wiadomości jest
ona wysyłana do kolejki określonej we właściwości PROPID_M_DEADLETTER_QUEUE.
9. Błędy
0xC00E0003 – usługa kolejkowania nie może odnaleźć kolejki.
0xC00E0014 – wyspecyfikowano błędną nazwę ścieżkę dla kolejki.
0xC00E001E – nieprawidłowy format nazwy.
0xC00E003F – nie wszystkie właściwości zostały wyspecyfikowane
0xC00E001A – podczas odczytu wiadomości za mały bufor dla jednej z jej właściwości. Przeważnie zbyt długie ciało
wiadomości.
T. Goluch , K.M. Ocetkiewicz
Kolejkowanie wiadomości (MSMQ)
{C91E19C4-8B08-4D63-9B7C-0913AAB2A7CE}
{C91E19C4-8B08-4D63-9B7C-0913AAB2A7CE}
6