29. září 2013

Architektura integračního řešení

V dnešním článku se opět vracím k mému poslednímu projektu, na kterém jsme realizovali nového virtuálního operátora, viz článek Zkušenosti s Apache Camel. Já konkrétně jsem měl na starosti integrační část celého řešení.

Integrační část je centrálním bodem celého řešení, a proto musí být vždy dostupná. Kromě jiného musí splňovat ještě tyto požadavky:

  • spolehlivost
  • škálovatelnost
  • výkonnost
Pro úplnost uvedu přehled externích systémů, se kterými integrační platforma komunikuje:
Při návrhu aplikací a vlastně i při jejich realizaci se snažím držet mého přesvědčení, že nemá cenu dělat nic zbytečně dopředu, dokud není jasné, že je to opravdu potřeba. Pamatuji si na dobu, kdy jsem se snažil vše řešit co nejobecněji a naivně jsem si myslel, že až se ukáže v budoucnu, že to bude potřeba, tak to na to už bude připravené. Bohužel k tomu nikdy nedocházelo - buď se změnily požadavky nebo k tomu ani nedošlo, aby se něco dodělávalo. Jsem přesvědčený o tom, že pokud jsou věci jednoduché (tedy jednoduchá a jasná architektura), pak je to i srozumitelné a lépe udržovatelné. 

S tímto přístupem jsme navrhovali i toto integrační řešení:
  • operační systém CentOS 6.4 64bit
  • Apache Tomcat 7 - krásný příklad, jak v jednoduchosti je síla. Nevidím žádný (technický) důvod, proč používat něco složitějšího.
  • PostgreSQL 9 - databázi používáme pro persistenci vstupních zpráv, se kterými dále pracujeme a zaručujeme se o jejich zpracování. Mě osobně by se zde více líbilo JMS (např. Apache ActiveMQ nebo RabbitMQ), ale výběr databáze byl již dán, takže jsem s tím musel pracovat jak to bylo dáno. Obával jsem se zde úzkého výkonnostního hrdla, zejména v momentě, kdy se více ESB instancí bude "prát" o nové zprávy ke zpracování, ale zatím se ukazuje, že moje obavy byly zbytečné.
  • Load balancing je prováděn komponentou apache http serveru mod_proxy_balancer pomocí round robbin algoritmu. Balancing zajišťuje rozkládání zátěže na jednotlivé nody a primárně je  použit z důvodu vysoké dostupnosti ESB nodu, jelikož v případě výpadku jednoho z ESB nodů automaticky na daný chybný node přestane směrovat requesty.
  • Samotný apache http server je zároveň provozován také na dvou nodech, mezi kterými je pak pohyblivá IP adresa, která je pak aktivní pouze na jednom ze serverů a přes tento server je pak primárně směřován provoz. Apache na druhém serveru je tak pouze ve stavu standby a přes něj by byl směrován provoz až v případě migrace této „pohyblivé“ IP adresy na tento server, ze kterého je pak prováděn balancing stejným způsobem na oba dva aktivní aplikační servery čímž je zajištěna vysoká dostupnost systému.
  • Na HTTP proxy je zakončena zabezpečená SSL komunikace, dále směrem k aplikačnímu serveru je již komunikace realizována pouze pomocí HTTP protokolu.
Co se týče výběru aplikačního stacku, tak základ je tvořený knihovnou Apache Camel, která zajišťuje samotné routování zpráv. Zbylé věci jsou řešeny Spring knihovnami:
  • Spring Framework tvoří základní stavební kámen pro konfiguraci aplikace
  • Spring Security pro zabezpečení webové admin části a pro zabezpečení komunikace s externími systémy
  • Spring Web Services jako hlavní Camel komponenta pro komunikaci pomocí webových služeb

16. září 2013

Specifika integračních projektů

Integrační projekty mají svoje specifika, která nemusí být pro každého hned na začátku zřejmá, proto bych rád udělal takové jejich resumé v tomto článku.

Logovat, logovat a logovat

U každé aplikace je důležité mít kvalitní logy a být schopen rekonstrukce běhu aplikace, ale z mých zkušeností toto platí dvojnásob pro integrační projekty. Pokud se bavíme o implementaci nějaké integrační platformy (ESB), pak je to ta část celého řešení, která vše propojuje, přes kterou proudí všechny informace,  a proto je nutné umět dohledat chování pro každý požadavek, který do ESB přijde. Je to hlavně kvůli vaší samotné obraně, protože pokud se někde v řešení vyskytne chyba, pak ESB je první koho se ptají. Naštěstí samotné ESB platformy mají většinou kvalitní logování, např. Apache Camel ve své poslední verzi přidal tzv. Message history pro zpětné vypsání celého průchodu vstupní zprávy.

Není to jen o samotném logování, ale také o tom, aby logovací záznamy obsahovaly všechny potřebné informace a bylo zpětné možné dohledat všechny log. záznamy k jedné vstupní zprávě nebo i k jednomu celému procesu (např. proces založení zákazníka se skládá z několika volání externích systémů).

Vymezení oproti ostatním systémům

Jak už jsem psal, pokud někde nastane nějaký problém, tak integrační platforma je první, kde se hledá možná příčina problému. Proto je potřeba hned na první pohled jasně u každé chyby vidět, zda se jedná o interní chybu integrace nebo o chybu, která se vyskytla v externím systému a pokud ano, tak v jakém.  Z toho důvodu se zavádí katalog chyb, který toto značně zpřehledňuje. Potom kdykoliv se objeví nějaká chyba, tak vždy ji doprovází i jasná identifikace z katalogu chyb.

Bez komunikace a pravidel to nejde

Pokud jste uprostřed celého řešení a propojujete jednotky/desítky/stovky systémů okolo, tak to prostě od stolu neuděláte. Je potřeba komunikovat, volat si, scházet se. Velice se nám osvědčil u integračních projektů přístup, že hned od začátku se integruje celé řešení dohromady - sice to v prvních sprintech bolí, ale hned od začátku máte celé řešení, které funguje end-to-end a nemusíte se obávat nepříjemného překvapení na konci projektu, když budete chtít pospojovat jednotlivé krabičky dohromady.
Integrační platforma musí být vždy o krok napřed před ostatními systémy (proto je i vhodné, aby integrační tým měl aspoň jeden sprint náskok), musí být od začátku jasná pravidla pro vzájemnou komunikaci - povolené komunikační protokoly, povinné informace v každé zprávě, jednotné názvosloví, domluva na společných číselnících, verzování služeb,  atd. Pokud toto nebude hned na začátku, tak se to pak vrátí v době údržby jako bumerang.

Flexibilita musí být   

Integrační procesy se pořád mění, nové systémy se přidávají, staré zanikají nebo jsou nahrazovány novými a je potřeba s tímto hned od začátku počítat, že to není nic výjimečného, že je to prostě realita.

Maximální dostupnost

Je rozdíl pokud nefunguje koncová aplikace nebo integrační platforma uprostřed - to pak nefunguje nic. Hned od začátku je nutné si umět jasně odpovědět na základní scénáře okolo produkčního nasazení - jak budu upgradovat na novou verzi rozhraní, jak budu nasazovat hotfixy, jak budu měnit konfiguraci, jak zaručím co největší dostupnost atd. Hned od začátku je potřeba mít jasno a neříkat si, že se to pak nějak vyřeší.
Pokud budete hledat odpověď na tyto otázky, tak určitě budete přemýšlet nad modulární architekturou (vyplatí se mi použít OSGi a mít možnost upgradovat nezávisle libovolný modul bez restartu celé aplikace?) nebo nad způsobem jak přistupovat k návrhu rozhraní (každá služba bude mít svoje rozhraní, žádné sdílení společných entit vs. jednotlivé rozhraní si sdílejí společné entity).

Jednoduchost nade vše

Více než u jiných typů projektů zde platí, že pokud je něco hodně složitého nebo komplikovaného, tak je to špatně. U dobře navržené integrace nejsou na rozdíl od aplikačního vývoje složité algoritmy, vše musí být jasné a srozumitelné, když to mají všichni pochopit a navzájem se propojit.

2. září 2013

Zkušenosti s Apache Camel

Poslední půlrok jsem pracoval intenzivně na integračním řešení pro jednoho nového virtuálního operátora. Základním stavebním prvkem byl integrační framework Apache Camel. Rád bych se v tomto článku ohlédnul zpět a použití tohoto řešení trochu zhodnotil.

Úplně na začátku bych se zastavil u toho, proč vlastně Camel. Já jsem do projektu přišel na začátku implementace (nebyl jsem tedy součástí obchodních příprav) a musel jsem pracovat s tím, co už bylo slíbeno - buď Apache ServiceMix nebo Apache Camel jako hlavní součást ServiceMixu. ServiceMix je vlastně kompletní ESB řešení, které řeší základní vlastnosti jako stabilitu, škálovatelnost, flexibilitu atd., není tedy nic dalšího potřeba. Mě to ale přišlo hned na začátek příliš velké sousto (ServiceMix je poskládaný s dílčích řešení a s většinou jsem dosud žádné zkušenosti neměl), takže jsem si řekl, že použijeme jen routovací jádro (Apache Camel) a o vše ostatní (stabilitu, škálovatelnost, flexibilitu, ...) se postaráme sami. Pokud bych začínal na zelené louce, tak by mě to určitě více táhlo ke Spring Integration, protože rád a hodně využívám Spring projekty. Spring Integration je přímý konkurent Apache Camelu (stačí vygooglit "spring integration vs camel"), ale bohužel sám zatím nemohu říci, co je lepší, protože mi chybí větší zkušenost se Spring Integration.

Náš technologický stack vypadal následovně:

  • Apache Camel
  • Spring framework
  • Spring Web Services
  • Spring Security
  • Hibernate
  • PostgreSQL
  • Apache Tomcat
  • Apache HTTP server
Pozn. o architektuře řešení bych rád napsal v některém dalším článku.

Když jsme začínali s projektem, tak Camel byl ve verzi 2.9, když jsme projekt končili, tak jsme používali verzi 2.11.

Mám již 3 týdny od konce projektu, takže s lehkým odstupem času mě napadají tyto body, když se řekne Apache Camel:
  • pro mě nezvyklá chybovost. Jak asi víte, mám rád projekty od Springu a u nich si člověk rychle zvykne na opravdu vysoký standard - vysoká kvalita kódu a nízká chybovost. Toto bohužel u Camelu úplně neplatí. Kvalita kódu a JavaDoc jsou určitě nadprůměrné, ale chybovost mi přišla celkem velká. Po nějakém čase člověk zjistí co funguje a co ne, takže v průběhu vývoje šla naše efektivita určitě hodně nahoru, ale na začátku jsme museli trochu hledat cesty, které fungují a které ne. Zase musím uznat, že pokud jsme nějakou chybu nahlásili, tak v dalším releasu byla opravená. 
  • rozsáhlá podpora knihoven třetích stran. Pokud chcete v Camelu komunikovat nějakým protokolem nebo využít nějakou knihovnu třetí strany, pak je toto v Camelu řešeno přes komponenty a těch je v nabídce Camelu opravdu hodně.
  • Spring WS vs. Apache CXF. Webové služby jsou základním komunikačním způsobem u integračních řešení, takže výběr této Camel komponenty byl stěžejní. Začal jsem s Apache CXF, protože na první pohled je vidět, že integrace obou knihoven je opravdu úzká. Ale bohužel mi časem došla trpělivost s CXF (omlouvám se, ale já prostě tuto knihovnu opravdu nemám rád) a přešel jsem na Spring WS. Bohužel některé potřebné věci jsme si museli napsat sami nebo jsme počkali na další verze Camelu, ale při pohledu zpět to vidím jako správně rozhodnutí.
  • výborná podpora pro unit testy. Integrační řešení jsou specifická tím, že je nutné se pojit na spoustu externích systémů, které většinou nemáte vůbec pod svojí kontrolou. Proto je hodně důležité, když je možné pro potřeby unit testů se oproti externím systémům vymezit, což Camel umí hodně dobře. Navíc Camel nabízí opravdu flexibilní řešení, kdy si pro účely unit testů můžete originální routu upravit přesně podle svých potřeb.
  • dostatek informací. Úspěšné řešení doprovází dostatek dostupných informací a to pro Camel určitě platí. Samotná dokumentace je obsáhlá a vše potřebné je tam k nalezení, diskuzní fórum je aktivní a na všechny mé dotazy se objevila odpověď celkem rychle. Já osobně jsem s Camelem začínal přečtením knížky Camel in Action. Knížka je sice v řadě oblastí zastaralá (myslím, že byla psána ve verzi 2.4), nicméně základní informace jsou pořád stejné, jen se mění a rozvijí jednotlivé Camel komponenty.
  • komerční podpora a nástroje třetích stran. Při výběru nové technologie si člověk vždy chce nechat otevřená zadní vrátka pro případ, že vše nepůjde tak jak se očekávalo. Proto je vhodné vědět, že existuje i možnost komerční podpory ze strany FuseSource, což je firma, kterou nedávnou koupil RedHat. Kromě možné podpory nabízí FuseSource i své ESB a další zajímavé produkty, které lze s Camelem využít - Fuse IDE a Fuse Management Console
  • routovací jádro. Samotný Apache Camel je pouze jen routovací jádro, které implementuje EIS vzory. Samotné moc nezabírá a je tedy ho možné využít v libovolných aplikacích pro dílčí úkoly.
  • Java DSL vs. Spring XML konfigurace. Zápis integračních route je možné buď přímo v jazyce Java (Java DSL) a nebo využít Spring namespaces a route konfigurovat pomocí Spring XML. My jsme si vybrali Java DSL, protože nám to hned od začátku bylo bližší, ale teď nevím, zda bych to udělal znovu stejně. Pokud potřebuji volat z routy nějakou Java metodu, tak to nejčastěji volám přes referenci na beanu včetně zadání názvu metody jako řetězce. Mě tento přístup do Javy moc nesedí, takže bych to raději konfiguroval v XML, ale zase to má tu nevýhodu, že je to mnohem více upovídané, a že musím pořád přepínat mezi Javou a XML. Jinak by ale oba přístupy z pohledu funkcionality měly být zcela rovnocenné.
Apache Camel jsem si za intenzivní půlrok slušně ošahal, již vím co funguje a co ne a musím se přiznat, že jsem si Camel i celkem oblíbil.