Niezawodny messaging w oparciu o szynę usług ESB – jak podejść do tematu?
Przesyłanie komunikatów (ang. messaging) jest obecnie najpopularniejszym stylem integracji aplikacji w przedsiębiorstwie. Messaging realizowany w oparciu o szynę usług to rozwiązanie, gdzie aplikacje wysyłające komunikaty można podzielić na 3 grupy. Nadawców, odbiorców i pośrednika, którego rolą często jest zapewnienie niezawodności i gwarancji dostarczenia komunikatu. Z artykułu dowiesz się jak zorganizować przetwarzanie komunikatów na szynie usług, żeby funkcjonowała ona jak zaufana, rzetelna firma kurierska.
Kilka słów wprowadzenia do tematu integracji
Istnieje kilka podejść do integracji aplikacji, w każdym z nich występują inne problemy. Generalnie, można wyróżnić cztery style integracji:
- transfer plików
- współdzielenie bazy danych przez aplikacje
- zdalne wywołanie procedury
- przesyłanie komunikatów (ang. messaging)
W artykule tym, zajmiemy się jednym z problemów związanych z przesyłaniem komunikatów przez kanał komunikacyjny za pośrednictwem szyny usług, czyli niezawodnością przetwarzania. Przed przedstawieniem architektury systemu pozwalającego na osiągnięcie niezawodności, należy w pierwszej kolejności określić, w jakich sytuacjach przetwarzanie komunikatów może zawieść. Czyli jakie mogą wystąpić powody niedostarczenia komunikatu od nadawcy do odbiorcy.
Pierwszą z takich sytuacji będzie czasowa niedostępność systemu docelowego, np. spowodowana zaplanowanym okienkiem serwisowym. Kolejną, problemy wydajnościowe, uniemożliwiające odbiorcy pomyślne przetworzenie komunikatu. Czasami, mogą również występować błędy w samym oprogramowaniu, gdzie poprawna wiadomość powoduje problemy przetwarzania po stronie odbiorcy. Zdarzają się również błędy w samym kodzie szyny usług.
Czy w każdej ze wspomnianych sytuacji, nadawca będzie zmuszony do ponownej wysyłki komunikatu? Jak w tysiącach przesyłanych wiadomości, znaleźć te, które nie zostały pomyślnie przetworzone lub spowodowały błąd? Na szczęście, używając odpowiednich narzędzi oraz projektując przemyślaną architekturę systemu, da się zagwarantować dostawę komunikatu od nadawcy do odbiorcy.
Jak pracuje solidny kurier?
Wydaje się, że czytelnikowi powinny już nasuwać się pewne skojarzenia. Mówiąc o nadawcach, odbiorcach i pośredniku, szybko na myśl przychodzi skojarzenie z firmą kurierską. Zastanówmy się zatem krótko, jak przebiega proces dostarczenia paczki przez rzetelnego kuriera.
Po pierwsze, należy zauważyć jeden istotny fakt. Nadawca, po przekazaniu kurierowi paczki, nie czeka bezczynnie, aż dostawca wróci z podpisanym potwierdzeniem odbioru. Wraca do swoich codziennych obowiązków.
Po drugie, kurier odbierając paczkę, nie zawsze zaraz po odebraniu przesyłki od nadawcy dostarcza paczkę do odbiorcy. Często pierwszym miejscem, do którego trafia paczka jest oddział firmy kurierskiej i sortownia. Dopiero w następnym kroku, często po przewiezieniu do innego oddziału w innymi mieście paczka rusza do odbiorcy.
Dalej, dostawca może spotkać się z jedną z dwóch sytuacji – albo odbiorca przyjmie paczkę podpisując potwierdzenie, albo kurier odbiorcy nie zastanie. Z punktu widzenia dalszego procesu dostarczenia, ciekawsza wydaje się ta druga sytuacja, gdzie najczęściej zostaje podjęta próba ponownego doręczenia. Każda z firm posiada własne reguły określające, ile razy dostawca spróbuje dowieźć paczkę, określa się również liczbę dni, po której paczka wraca do nadawcy.
Szyna usług jako kurier wiadomości
Porównując proces dostawy paczki przez kuriera do messagingu, należy zwrócić uwagę na jedną istotną kwestię. Szyna usług sama w sobie nie pozwala na przechowywanie odebranych komunikatów w nieskończoność. Żeby zrealizować niezawodny proces przetwarzania, ESB musi posiłkować się dodatkowymi narzędziami pozwalającymi na utrwalenie odebranych komunikatów. W sytuacji utrwalenia komunikatów wyłącznie w pamięci, w przypadku awarii szyny, dane mogą zostać utracone i wystąpi konieczność ponownej wysyłki.
Jednym z narzędzi pozwalających na poradzenie sobie z tym problemem są kolejki wiadomości, a narzędziem zapewniającym realizację efektywnego kolejkowania jest broker komunikatów RabbitMQ.
Mając na uwadze wprowadzony wcześniej kontekst – dostarczenie paczki przez kuriera – w dalszej części artykułu opowiem, w jaki sposób można zorganizować messaging w oparciu o Mule ESB i RabbitMQ.
Komunikacja asynchroniczna za pośrednictwem kolejek w RabbitMQ
Wróćmy do pierwszego spostrzeżenia odnośnie momentu przekazania paczki do kuriera. Nadawca paczki nie czeka biernie, aż kurier dostarczy paczkę do odbiorcy. W odniesieniu do integracji systemów sytuacja ta przekłada się oczywiście na zastosowanie komunikacji asynchronicznej. ESB bezpośrednio po odebraniu komunikatu od nadawcy, przekazuje wiadomość do kolejki. Następnie, gdy komunikat jest już utrwalony w RabbitMQ, szyna potwierdza przyjęcie wiadomości od nadawcy. Co się stanie, gdy wyłączymy w tym momencie serwer RabbitMQ? Porozmawiajmy zatem o gwarantowanej dostawie.
Wzorzec niezawodności i gwarantowana dostawa
W jednym z artykułów na portalu DZone, autor przedstawia wzorzec niezawodnego przetwarzania w oparciu o Mule ESB oraz natywną dla tej szyny kolejkę VM. Clou tego rozwiązania jest skonfigurowanie kolejki w taki sposób, aby wiadomości nie były przechowywane wyłącznie w pamięci, ale były utrwalane w jednym z tzw. object store dostarczanych przez Mule ESB. Trzeba jednak zaznaczyć, że nie zawsze persystencja komunikatów na tej samej maszynie wirtualnej, na której pracuje szyna, jest rozwiązaniem optymalnym. W przypadku architektury fizycznej projektowanej i wdrażanej przez Unity Group, częstym rozwiązaniem jest instalowanie poszczególnych komponentów systemu na kilku maszynach, co zapewnia minimalizację wpływu poszczególnych komponentów systemu na siebie. Nasuwa się zatem pytanie, czy korzystając z RabbitMQ, zainstalowanego na dedykowanej maszynie wirtualnej, możemy korzystać również z kolejek trwałych? Odpowiedź brzmi – oczywiście, że tak. Wiadomości przechowywane są w bazie danych Mnesia, dostarczanej i instalowanej razem z tym komponentem.
Wiemy już, w jaki sposób utrwalać komunikaty w kolejkach RabbitMQ. Przejdźmy zatem do następnego kroku w procesie, czyli dostarczenia komunikatu do odbiorcy.
Wzorzec producent – konsument oraz Dead Letter Queue
Komunikacja pomiędzy ESB a RabbitMQ odbywa się na zasadzie wzorca producent-konsument. W sytuacji, gdy na kolejce znajdują się komunikaty, szyna usług jako konsument pobiera wiadomości i następnie wysyła do odbiorcy. W przytoczonym przykładzie wspomniałem, że z punktu widzenia procesu dostarczenia, bardziej interesującym przypadkiem jest ten, gdy doręczenie nie powiedzie się. Rozważmy zatem przypadek, gdy ESB pobrało komunikat z kolejki i odbiorca był niedostępny. W sytuacji tej, w pierwszej kolejności należy obsłużyć pobraną już wiadomość w taki sposób, aby nie została utracona. Z pomocą przychodzi tutaj istniejący w RabbitMQ mechanizm potwierdzeń. Po pobraniu wiadomości z kolejki istnieją wyłącznie 2 możliwości – akceptacja lub odrzucenie komunikatu. Zatem po pomyślnej wysyłce do odbiorcy, należy pobraną wiadomość zaakceptować, co poskutkuje usunięciem jej z systemu kolejkowego. W sytuacji, gdy przetwarzanie (z różnych względów) nie powiedzie się, komunikat należy odrzucić.
Odrzucenie komunikatu może zakończyć się na 2 sposoby. W pierwszym przypadku, wróci on na oryginalną kolejkę i zostanie natychmiast pobrany oraz ponownie wysłany. Jak można domyślić się, nie jest to najefektywniejszy sposób, gdyż niedziałająca aplikacja odbierająca, najczęściej potrzebuje czasu na powrót do normalnego stanu. Lepiej będzie, gdy szyna usług ponowi wysyłkę do odbiorcy z określonym opóźnieniem. Ponownie można przywołać w tym miejscu porównanie do kuriera. Doręczyciel stojący pod drzwiami odbiorcy i natrętnie dzwoniący do drzwi nie doręczy paczki, jeżeli w mieszkaniu nie ma nikogo w danej chwili. Rozwiązaniem, pozwalającym na przechowanie wiadomości, której próba wysyłki nie powiodła się, jest tzw. Dead Letter Queue, czyli kolejka, na której komunikat jest przechowywany przez określony czas, a następnie może on wrócić do oryginalnej kolejki, skąd ponownie trafi do odbiorcy.
Powiadomienie o braku możliwości dostarczenia komunikatu
Do rozważenia zostaje ostatni przypadek, czyli sytuacja, gdy została podjęta n-krotna próba wysyłki komunikatu do odbiorcy i żadna z podjętych prób nie powiodła się. Najczęściej oznacza to, że w systemie dzieje się coś bardzo niekorzystnego. A niejednokrotnie klasyczny email informujący administratorów o wystąpieniu błędu i konieczności podjęcia określonych działań jest najlepszym rozwiązaniem.
Podsumowanie
Odpowiadając na postawione we wstępie pytanie – czy szyna usług może pracować, jak rzetelny kurier? Tak, można odpowiedzieć twierdząco, jednak wymaga to odpowiednich narzędzi i odpowiednio zaprojektowanej architektury systemu. Bardzo dobre efekty w kwestii niezawodnego messagingu daje umiejętne połączenie Mule ESB i brokera wiadomości RabbitMQ.