Posts tagged SOA
Dlaczego nie lubię rozproszonych transakcji
Apr 6th
Jakiś czas temu po prostu powiedziałbym, że są niewydajne. Na szczęście, zgodnie z ideą challenge everything przeprowadziłem kilka testów, które przekonały mnie, że problem wydajnościowy wcale nie jest taki straszny. Na pewno nie na tyle, aby dyskwalifikować takie rozwiązanie. Co więc je dyskwalifikuje (w moich oczach)? Oto lista problemów:
- zwiększona podatność na awarię
- skomplikowana administracja infrastrukturą
- problemy związane z zaufaniem i polityką
Mam oczywiście na myśli rozwiązanie, w którym jedna transakcja rozproszona współdzielona jest przez wiele niezależnych usług/systemów/aplikacji. Wykorzystanie transakcji rozproszonych w ramach jednej aplikacji do rozwiązania kwestii technicznych (np. integracja transakcyjna bazy danych i MSMQ) jest dla mnie całkowicie OK.
Historia pewnej transakcji
Aby namierzyć problemy, prześledźmy pewien nie-całkiem-nierealny przypadek użycia: klienta łączącego się z własną bazą danych i z zewnętrzną transakcyjną usługą. Oto, co się dzieje:
- Klient rozpoczyna transakcję w swoim kodzie
using (TransactionScope tx = new TransactionScope())
- Klient wykonuje operację na bazie danych. W przypadku bazy SQL Server po tym kroku transakcja jest wciąż lokalna (brak zaangażowania Distributed Transaction Coordinator, DTC). W przypadku innych silników może być inaczej
- Klient łączy się z usługą zdalną “A” w sposób transakcyjny (wykorzystując mechanizmy WCF). W tym momencie transakcja jest promowana i staje się transakcją rozproszoną — otrzymuje odpowiedni identyfikator.
W tym momencie pojawia się problem natury administracyjnej. Aby usługi DTC na różnych maszynach, być może w różnych firmach, na różnych kontynentach, mogły się porozumieć, niezbędne jest stworzenie odpowiednich kanałów (“wybicie dziur” w firewallach). Tego typu działania są ściśle związane z polityką bezpieczeństwa każdej świadomej organizacji i dlatego zwykle wymagają uruchomienia skomplikowanego i długotrwałego procesu. Każda zmiana w logicznej topologii wywoływanych usług, jakkolwiek prosta w kodzie, może się wiązać z koniecznością uruchomienia trwających tygodniami procesów w dziale IT. Ile nic to, idźmy dalej.
- Usługa “A” do wykonania swojego biznesu musi skorzystać z pewnej zewnętrznej funkcji udostępnianej przez usługę “B”. Oczywiście, dla utrudnienia, usługa “B” także jest transakcyjna.
Nagle i niespodziewanie pojawia się nam zależność od usługi “B”. Teoretycznie klient nie musiałby wiedzieć nic o istnieniu “B”. Teoria jednak ma się nijak do praktyki. Praktycznie bowiem, powodzenie transakcji klienta jest zależne o działania usługi “B”. Co jeśli jest ona prowadzona przez firmę konkurencyjną dla naszego klienta? Wcale nie musi jej zależeć na najwyższym poziomie obsługi. Niektóre (te najbardziej lukratywne?) transakcje mogą być umyślnie sabotowane przez zrywanie połączenia. Polityka, polityka, wszędzie polityka. Załóżmy jednak, że tym razem kwestie polityczne zostały rozwiązane pokojowo. Co dalej?
- Usługa “B” wykonuje swoją część pracy i zwraca sterowanie do “A”.
- Usługa “A” kończy pracę i zwraca sterowanie do klienta.
- Klient inicjuje proces zatwierdzania transakcji.
Proces zatwierdzania składa się zwykle z dwóch faz (2-phase commit). Jest on ukoronowaniem trwającej nierzadko kilka lub nawet kilkanaście sekund interakcji mogącej dotyczyć komputerów na wielu kontynentach. Bardzo wiele rzeczy morze pójść “nie tak”. Połączenia mogą zostać zerwane, pakiety zgubione itp.
Każdy, praktycznie, problem powoduje zerwanie misternie utkanej sieci powiązań pomiędzy usługami i koordynatorami transakcji, skutkiem czego cała transakcja zostaje wycofana.
Epilog
Przekonałem Was, że transakcje rozproszone to ryzykowny biznes? Mam nadzieję, że tak. W następnym odcinku postaram się opowiedzieć o technikach, które można stosować, aby ich uniknąć.
Słowniczek pojęć bliskoznacznych
Mar 15th
Moja żona zainspirowała mnie do tego, aby przerwać strumień notek opisujących jakieś techniczne nowinki, tricki i sztuczki i pochylić się na moment nad tematami bardziej podstawowymi. Czym właściwie jest Domain-Driven Desing? Czym design (projektowanie) różni się od architektury? I czy w ogóle można to w jakiś sensowny sposób wytłumaczyć nie-programiście?
Ostrzegam na wstępie, że niniejsza notka jest wyrazem moich osobistych opinii i nie należy ją traktować jako prawdę objawioną — nie znajduję się w tym momencie w proroczym transie:-)
Architektura
Zacznijmy od wysokiego poziomu abstrakcji. Co rozumiem pod pojęciem architektura? Przede wszystkim dla mnie jest to skrót myślowy prowadzący do architektury oprogramowania. Podczas, gdy istnieje wiele innych dziedzin architektury (jak enterprise architecture), ja ograniczam się w moim blogopisarstwie do tej jednej. Podoba mi się określenie znalezione na tym blogu:
architektura jest rodzajem projektowania, ale nie każde projektowanie to architektura
Architektura oprogramowania, jako zajęcie, to ten podzbiór aktywności projektowych o największym znaczeniu — takich, których skutki są trudne i kosztowne do zmiany.
Jeszcze bardziej jednak podoba mi się inne określenie, zainspirowane artykułem Martina Fowlera. Pomysł polega na tym, że w tworzeniu oprogramowania nie ma narzuconej z góry ważności decyzji: to, czy dana decyzja jest trudna do zmiany,czy nie wynika ze sposobu w jaki budujemy nasz system. Architektura w takim ujęciu jest zestawem metadecyzji: decyzji o tym, które kwestii związanych z projektowaniem systemu mają być trudne do zmiany, a które nie. Wszystko inne (w tym same decyzje) są już “jedynie” projektowaniem.
Service-Oriented Architecture
SOA to chyba najbardziej chwytliwy trzyliterowy skrót ostatniej dekady. Wszystko, co produkuje nasza branża musi mieć plakietkę “SOA”, aby się sprzedało. Ale czym właściwie jest to całe SOA? Ja mam przynajmniej dwie równoległe teorie. Każda z nich odwołuje się do abstrakcyjnej definicji, zgodnie z którą SOA to architektura, w której centralnym punktem są usługi — autonomiczne (jedna z 4 zasad SOA) byty udostępniające pewne funkcjonalności dla innych podobnych bytów.
SOA “klasyczne”
SOA “wg Thomasa Erla” to dla mnie kwintesencja klasycznego podejścia do usług. W tym rozumieniu katalog usług podzielony jest na warstwy, w obrębie których dominującym wzorcem jest definiowania funkcjonalności usług jest CRUD. Dominującym mechanizmem komunikacji jest zaś synchroniczna komunikacja WS-*. Nie jestem fanem tej definicji. Abstrahując od kwestii technicznych (nie wierzę w efektywność komunikacji synchronicznej), głównym problemem z tak rozumianym SOA są wymagania i założenia organizacyjne.
Pierwsze z nich mówi, że aby SOA było zrealizowane efektywnie, całe przedsiębiorstwo musi być przeanalizowane pod kątem odkrywania usług, które mają się składać na implementację SOA, zanim rozpocznie się jakakolwiek implementacja. Bardzo brzydko pachnie mi to procesami wodospadowymi.
Drugie, jeszcze bardziej problematyczne, założenie sugeruje, że wszystkie usługi powinny posługiwać się tym samym modelem danych w celu zminimalizowania transformacji. Nie zgadzam się z dwóch powodów. Po pierwsze modelowanie danych (a nie zachowania) jest wg mnie mało użyteczne. Po drugie jestem przekonany (a moje przekonanie zbudowane jest na własnym doświadczeniu i lekturze publikacji związanych z DDD), że model powinien rozwiązywać dokładnie jeden problem, dla którego powstał. Model do wszystkiego jest do niczego. Kropka.
Pozostawmy na chwilę SOA i rozważmy inny sposób definiowania architektury…
Event-Driven Architecture
EDA nie jest pomysłem nowym. Nigdy jednak nie zyskała takiego uznania, jak jej siostra, SOA. Architektura oparta o zdarzenia nie jest aż tak napakowana różnymi standardami, wzorcami, dobrymi radami. Jedyne co mówi to, że poszczególne komponenty wchodzące w jej skład porozumiewają się za pomocą zdarzeń mających dobrze określone znaczenie w domenie rozwiązywanego problemu. Żeby nie szukać daleko przykładów, Java-owy Swing posiada architekturę EDA.
SOA wg Udiego Dahana
Wracamy do SOA aby przyjrzeć się wersji, którą proponuje nam Udi Dahan. Jest to architektura spełniająca założenia SOA (tenets), jednak jest także architekturą EDA. Kluczowym elementem tak zdefiniowanej architektury są autonomiczne (a jakże by inaczej) usługi komunikujące się poprzez publikowanie zdarzeń. Zainteresowanych odsyłam do prezentacji “How to avoid failed SOA”, którą Udi prezentował na zeszłorocznym C2C oraz (a może przede wszystkim) do bloga Udiego.
Domain-Driven Design
Schodząc z abstrakcyjnego poziomu architektury na ziemię, stwierdzamy, że coś musi sterować naszym projektowaniem. Na przykład domena — stąd Domain-Driven Design. W odróżnieniu od tego, co się zwykle sądzi, DDD nie jest czymś, co można zrealizować w konkretnym systemie jedynie poprzez wykorzystanie kilku technicznych tricków. DDD jest sposobem pracy zespołów produkcyjnych, który jest zorientowany na modelowanie domeny. To, co zwykle rozumie się pod pojęciem DDD, czyli wszystkie kwestie techniczne, to jedynie wzorzec projektowy Domain Model.
Domain-Driven Design to wiele więcej niż ten wzorzec. Praktyki DDD obejmują sposób rozdziału zadań programistycznych, sposób projektowania implementacji, sposób współpracy między zespołami. DDD wpływa także na architekturę poprzez definiowania map kontekstów i struktur wielkoskalowych wpływających nie tylko na jeden budowany system.
Domain Model
To wzorzec projektowy sugerujący implementację logiki biznesowej w specjalnej warstwie nazywanej modelem domeny. Z modelem związanych jest wiele dobrych praktyk oraz mniejszych wzorców dotyczących m.in. organizacji kodu (na agregaty, encje oraz obiekty ValueObject). Model domeny zwykle składa się z klas reprezentujących jeden-do-jednego byty z przestrzeni biznesowej. Także zwykle jego stan jest trwale przechowywany, za zwyczaj przy pomocy narzędzia mapowania obiektowo-relacyjnego (O/RM).
Domain Events
To jeden z wzorców projektowych związanych z modelem domeny. Dlaczego go wyróżniłem i postanowiłem omówić osobno? Po pierwsze dlatego, że bardzo często się do niego odwołuję w swoich postach. Po drugie, zaś, dlatego, że zdarzenia domenowe często bywają mylone ze zdarzeniami Event-Driven Architecture. Domain Events to sposób na wypychanie informacji z modelu domeny konkretnego systemu. Informacje te mogą, ale nie muszą, zostać później przetransformowane na postać zdarzeń EDA. Równie dobrze mogą zostać przetransformowane na, bardziej klasyczne, asynchroniczne komunikaty. Nic nie stoi temu na przeszkodzie, ponieważ decyzje o użyciu Domain Events i EDA są zupełnie niezależne. Więcej o Domain Events możecie dowiedzieć się tutaj.
To wszystko na dziś. Jeśli macie jakieś pytania lub sugestię co jeszcze w moich postach jest niejasne i wymaga zdefiniowania, zostawcie komentarz.
Does My Bus Look Big in This?
Aug 26th
A przesłaniem tym jest: nie potrzebujemy wielkich, ciężkich i kosztownych produktów ESB!
Pierwsza część prezentacj poświęcona jest charakteryzacji typowego produktu ESB. Panowie bardzo mocno “jeżdżą sobie” po WebSphere (szczególnie) i podobnych tworach. Widać, że świetnie czują się na scenie (nic dziwnego…), więc dowcipy brzmią bardzo naturalnie i powodują prawdziwe salwy śmiechu, np.
ESB jest skalowalne, bo protokąt je reprezentujący można dowolnie rozciągnąć na boki na diaramie.
Fowler i Webber krytykują produkty ESB w szerszym kontekście: budowy wszelkiego rodzaju frameworków. Kontrastują ideę budowy frameworka od podstaw (wg czyjegoś marketingowego widzimisię) z “harvestowaniem” (nie wiem jak to dobrze przetłumaczyć) frameworków z istniejących i działających rozwiązań. Te drugie mają jedną podstawową przewagę nad pierwszymi: jest dowiedzione, że przynajmniej w jednym wypadku zadziałały. To już dobry punkt startowy. Przykładem tego typu rozwiązań, na który panowie prelegnci się powołują, jest Ruby on Rails. Ja dorzuciłbym od siebie NServiceBus.
Następnie Fowler i Webber dosyć płynnie przechodzą do przedstawienia idei Internetu. Wychodząc od starych komutowanych sieci telefoniczych postulują, że wielkość Internetu bierze się z tego że jest to “najgłupsza sieć na świecie”. Sieci komutowane były bardzo mądre w optymalnym przesyłaniu głosu między abonentami, dlatego zawiodły, kiedy próbowano je dostosować do przesyłania danych (przykład modemów 56K – nie powstało praktycznie nic szybszego). Internet potrafi tylko i wyłącznie przesyłać pakiety tak, aby poruszały się mniej-więcej w kierunku adresu docelowego. Dzięki prostocie tej “chmury”, inni mogą budować swoje zaawansowane rozwiązania wykorzystując ją jako infrastrukturę.
Finałowa część pokazuje, jak technologie internetowe mogą z powodzeniem zastąpić wielkie, ciężkie i kosztowne rozwiązania ESB. Zdania takie, jak:
Jeśli chcesz mieć ESB, zrób weż Sqida!
zapamiętuje się na długo. Podsumowanie prezentacji nie jest już dla oglądającego zaskoczeniem: rozwiązania oparte o Internet są we wszystkich kategoriach lepsze, niż stare, cieżkie ESB. Oczywiście należy pamiętać, że prezentacje tego typu celowo są przerysowane. Nie należy ich rozumieć dosłownie, ponieważ w wypadku ESB, jak w wypadku każdej kwestii architektonicznej, jedyną słuszną odpowiedzią jest:
well, it depends…
Gorąco polecam, koniecnie obejrzyjcie!
SOA Design Patterns: Dual Protocols
Jul 13th
Wzorzec Canonical Protocol zaleca wykorzystania jednego, standardowego, protokołu do komunikacji między usługami w ramach jednego inwentarza. Domyślnie oczywiście, protokołem tym są jakiegoś rodzaju usługi webowe (Basic WS, WS-*, REST), jednak nie jest to twarde wymaganie. Niezależnie od wyboru standardowego protokołu, mogą zdarzyć się sytuacje, kiedy jest on z jakichś przyczyn nieodpowiedni.
Przyczyny te mogą dotyczyć m.in.
- ograniczenia zakresu wykorzystania usługi do tej samej maszyny, co oznacza brak konieczności komunikacji zdalnej
- ograniczenie zakresu wykorzystania usługi do tej samej technologi
- konieczność zapewnienia zgodności wstecz dla klienta o szczególnych wymaganiach
Rozwiązaniem problemu niedopadowania protokołu standardowego jest wzorzec Dual Protocols. Jak sama nazwa wskazuje, wzorzec ten zaleca zastosowanie dwóch (ogólnie – wielu) protokołów dostępu do jednej usługi. Każda usługa inwenatrza powinna bowiem być udostępniona w oparciu o protokół standardowy; dodatkowo zaś może udostępniać inne punkty końcowe obsługujące protokoły specyficzne dla danego zastosowania.
Wzorzec ten jest świetnym przykładem tego, do czego w architekturze zorientowanej na usługi możemy wykorzystać WCF. Dual Protocols może być świetnie zaimplementowany za pomocą różnych binding-ów przypisanych do jednej usługi. Dzięki temu możemy zrobić śmiałe założenia, że cała komunikacja w naszym systemie jest zorientowana usługowo, natomiast:
- komponenty zbudowane w oparciu o .NET mogą korzystać z komunikacji via TCP
- komponenty wdrożone na tych samych maszych mogą korzystać z komunikacji IPC
Dzięki temu i wilk jest syty, i owca cała.
SOA Design Patterns: UI Mediator
Jul 8th
Rozwiązaniem jest specjalna usługa Mediatora, która jest umieszczana pomiędzy kodem interfejsu użytkownika, a rzeczywistą usługą dostarczającą funkcjonalności biznesowej. Mediator jest odpowiedzialny za dostarczanie użytkownikowi informacji o stanie zainicjowanego przez niego procesu oraz o wszelkich zdarzeniach występujących w trakcie jego działania.
Mediator może być zrealizowany na dwa sposoby:
- jako specjalna usługa warstwy Utility. Usłga ta posiada generyczny kontrakt ze słabo typowanymi operacjami (akceptującymi i zwracającymi dowolne komunikaty) i po prostu przekazuje otrzymaną wiadomość do docelowej usługi biznesowej. Taki Mediator zawiera także logikę dotyczącą tego, w jaki sposób i kiedy skontaktować się zwrotnie z interfejsem użytkownika.
- jako agent (wzorzec Service Agent). W tym wypadku komunikaty między interfejsem użytkownika, a usługą biznesową są automatycznie przechwytywane przez agenta. Agent monitoruje konwersjację i przechowuje jej stan, informując w odpowiednich momentach interfejs użytkownika o zaistniałych zdarzeniach.
Najczęstszą formą interakcji z użytkownikiem podczas trwania realizacji jego żądania jest wyświetlenie paska postępu, jednak możliwe są także inne działania, jak np. przeniesienie użytkownika na inny formularz.





