viŠeagentna aplikacija za analitiku api pristupnih … · istina je da razina kompleksnosti ovisi...
TRANSCRIPT
SVEUČILIŠTE U ZAGREBU
FAKULTET ORGANIZACIJE I INFORMATIKE
V A R A Ž D I N Mario Novoselec
VIŠEAGENTNA APLIKACIJA ZA ANALITIKU API PRISTUPNIH TOČAKA TEMELJENA NA MIKROSERVNISNOJ
ARHITEKTURI
DIPLOMSKI RAD
Varaždin, 2016.
SVEUČILIŠTE U ZAGREBU
FAKULTET ORGANIZACIJE I INFORMATIKE
V A R A Ž D I N
Mario Novoselec Matični broj: 43538/14–R
Studij: Baze podataka i baze znanja
VIŠEAGENTNA APLIKACIJA ZA ANALITIKU API PRISTUPNIH TOČAKA TEMELJENA NA MIKROSERVNISNOJ
ARHITEKTURI
DIPLOMSKI RAD
Mentor:
Doc.dr.sc. Markus Schatten
Varaždin, rujan 2016.
I
Sadržaj 1. Uvod ....................................................................................................................................... 12. Ključni principi mikroservisa ................................................................................................. 2
2.1. Mikroservis kao samostalni modul ................................................................................. 22.2. Komunikacija mikroservisa ............................................................................................ 3
2.2.1. Decentralizirana implementacija .............................................................................. 33. SOA i mikroservisna arhitektura ............................................................................................ 54. Uvod u implementaciju mikroservisne arhitekture ................................................................ 6
4.1. Motivacija i ciljevi aplikacije .......................................................................................... 64.2. Arhitektura aplikacije ...................................................................................................... 74.3. Upravljanje podacima ..................................................................................................... 74.4. Izazovi implementacije klijenta ...................................................................................... 8
5. Karakteristike Node.js razvojnog okvira ................................................................................ 96. Uvod u Seneca.js razvojni okvir .......................................................................................... 10
6.1. Metode seneca.add() i seneca.act() .............................................................................. 107. Uvod u višeagentne sustave ................................................................................................. 12
7.1. Reaktivni agenti ............................................................................................................ 128. Agent u službi prikupljanja podataka ................................................................................... 149. Implementacija mikroservisne arhitekture ........................................................................... 21
9.1. Autorizacija i autentikacija u mikroservisnoj arhitekturi .............................................. 229.2. Konfiguracija MongoDB baze podataka ....................................................................... 239.3. Konfiguracija Seneca.js aplikacijskog okvira ............................................................... 25
10. Implementacija klijenta ................................................................................................. 3611. Testiranje rada aplikacije .............................................................................................. 4012. Zaključak ....................................................................................................................... 41Literatura ................................................................................................................................... 42
1
1. Uvod Kontinuirani rast kompleksnosti programskih rješenja doveo je do pojave novih, izrazito
drugačijih načina organizacije i implementacije elemenata aplikacija. Rast implementacijskih
zahtjeva doveo je do porasta broja ljudi potrebnih za realizaciju određenog rješenja što za
sobom povlači konstantnu integraciju tehničkih i organizacijskih zahtjeva.
Zbog boljeg razumijevanja izrečenog, postavimo fokus na mrežne (web) aplikacije koje
zadnjih godina predstavljaju jedan od najzastupljenijih tipova aplikacija na tržištu.
Everts (2013.) navodi kako se veličina prosječne web aplikacije u zadnjih desetak godina
najmanje udvostručila.
Takvo drastično povećanje programskog koda, multimedijskih dodataka i ostalih
aspekata web aplikacije omogućeno je ponajviše tehnološkim poboljšanjima na području brzine
i dostupnosti interneta.1
Zbog takvog rasta veličine i zahtijeva koje određena web aplikacija nameće, monolitna je
struktura postala neodrživa i nestabilna. (Richardson, 2015)
Monolitna arhitektura podrazumijeva organizaciju aplikacije vezanu uz jedan izvorišni
element, u kontekstu web aplikacije to može biti web server, čija je organizacije najčešće
organizirana u zasebne module.
Takva arhitektura i danas može uspješno funkcionirati u manjem (djelomično i srednjem)
opsegu web aplikacije, ali zahtjevi za visokom skalabilnošću i konzumacijom sadržaja u
realnom vremenu, nametnuli su mikroservise kao de facto standardni način implementacije
programskih rješenja. (Richardson, 2015)
Fokus ovog rada teoretski su i praktični aspekti mikroservisa, kao i vlastiti osvrt na pozitivne i
negativne elemente implementacije ovakve arhitekture.
1 https://www.entrepreneur.com/article/228489
2
2. Ključni principi mikroservisa Mikroservisi su relativno ''mlad'' pojam u kontekstu računalne znanosti i ne postoje
striktno definirana pravila implementacije u postojeći ili novi sustav. (Richardson, 2015)
Iz tehničkih i organizacijskih izazova mogu se izvesti barem principi koje mikroservisi moraju
zadovoljavati:
1. Mikroservis nije komponenta, već samostalni modul
2. Mogu (najčešće i moraju) međusobno komunicirati koristeći poznate i strogo definirane
protokole
3. Implementacija poslovne logike nije centralizirana
Razumijevanje ključnih principa otkriva značenje i neke od najvažnijih aspekata mikroservisa
te ih je potrebno pobliže opisati.
2.1. Mikroservis kao samostalni modul Aplikacija za online trgovinu može poslužiti kao odličan primjer za razmatranje ovog
principa mikroservisa. Takva je aplikacija u suštini bazična, ali kompleksnost može drastično
narasti zbog širokog spektra mogućih implementacijskih zahtjeva.
Zahtjev implementacije slanja potvrde narudžbe u obliku email poruke može se razmotriti s
aspekta monolitne aplikacije i mikroservisa.
Slika 1. Usporedba monolitne i mikroservisne arhitekture (Prikaz autora)
3
Ovakav zahtjev unutar monolitne aplikacije predstavlja jedan modul koji, zajedno s ostalim
modulima, čini funkcionalni dio aplikacije. (Gonzalez, 2016:12)
Mikroservisna arhitektura omogućuje implementaciju neovisnu o postojećim rješenjima te čak
dozvoljava i promjenu implementacijske tehnologije. U tehničkom bi smislu takva aplikacija
radila na drugoj domeni, aplikacijskom portu, serveru i sl.
2.2. Komunikacija mikroservisa Spomenuto je da mikroservisi komuniciraju postojećim protokolima. U tehničkom
smislu, mikroservisi najčešće komuniciraju koristeći TCP/IP ili HTTP protokol, ali su moguće
implementacije koristeći i druge protokole.
Način komunikacije ovisi o razvojnom okviru, okolini i korištenom protokolu, a sredstvo
komunikacije su podaci koji čine dio poslovne logike sustava.
2.2.1. Decentralizirana implementacija Ovakav tip implementacije najlakše je prikazati u kontekstu web aplikacija. Tipična web
aplikacija sadrži web sučelje (prednji dio aplikacije) koje je povezano na stražnji dio aplikacije.
Stražnji dio nije jedna aplikacija, već nekolicina njih, od kojih svaka obavlja zasebne funkcije.
Slika 1. Prikaz klasične mikroservnisne arhitekture (Richardson, 2014.)
Sa stajališta baze podataka, u mikroservisnoj arhitekturi ne vrijede ACID principi. Specifično,
ACID principi nisu primjenjivi globalno, jer iako transakcija može biti uspješna na lokalnoj
razini, ne postoje mehanizmi osiguranja transakcije na globalnoj razini. (Gonzalez, 2016:17)
4
Kod projektiranja mikroservisne arhitekture, uvijek u obzir treba uzeti mogućnost
nasumičnog ispada pojedinog servisa te samim time obaveznu implementaciju podsustava za
rješavanje pogrešaka. Osim implementacijskih problema, moderni se web sustavi susreću s
problemom optimizacije procesa objave aplikacije (deployment). Taj proces često zna biti
dugotrajan i sklon pogreškama. Mikroservisi ovaj proces uvelike olakšavaju jer, u slučaju
ispada, samo jedan servis nije u funkciji, a smanjenjem obujma zadataka skraćuje se i trajanje
procesa objave aplikacije.
5
3. SOA i mikroservisna arhitektura SOA je daleko starija arhitektura u usporedbi s mikroservisnom te ju karakterizira
podjela na samostalne komponente koje pružaju servise ostalim komponentama. (Gonzalez,
2016:19)
Razlika je vidljiva u pogledu granuliranosti modula. Mikroservisi postižu mnogo finiju
granuliranost pojedinog modula, što u direktnoj usporedbi znači da pojedini SOA modul
možemo raščlaniti na nekoliko mikroservisnih modula.
J2EE je tehnologija korištena za povezivanje servisa u SOA arhitekturi i forsira striktne
(enterprise) standarde pisanja servisa. (Gonzalez 2016:18)
Okosnicu SOA arhitekture čini Enterprise Servise Bus (ESB) ekosustav unutar kojeg se
razvijaju i održavaju SOA aplikacije.
Slika 2. Usporedba SOA i mikroservisne arhitekture (Gonzalez, 2016:19)
Upravo je kompleksnost faktor koji sve više potiskuje SOA arhitekturu u drugi plan u odnosu
na heterogenost tehnologija koju pružaju mikroservisi.
6
4. Uvod u implementaciju mikroservisne arhitekture Iako teorijski opis mikroservisne arhitekture nudi uvid u najbitnije segmente te je, kroz
različite izvore, moguće pronaći adekvatan prikaz mikroservisa u pojedinom kontekstu,
konkretna implementacija u realnom scenariju daje potrebnu dubinu teorijskim temeljima.
Implementaciju aplikacije za analitiku API pristupnih točaka moguće je podijeliti u četiri glavna
segmenta:
1. Motivacija i ciljevi aplikacije
2. Prikaz arhitekture i odnosa dijelova aplikacije
3. Upravljanje podacima
4. Izazovi s aspekta klijenta
Ovakvo raščlanjivanje aplikacije preslikava moguće realne procese implementacije
programskog proizvoda.
4.1. Motivacija i ciljevi aplikacije Aplikacije za analitiku okvirno predstavljaju osrednju razinu kompleksnosti. Istina je da
razina kompleksnosti ovisi o detaljnoj specifikaciji, ali analitiku API pristupnih točaka možemo
razlomiti na dvije osnovne komponente te samim time smanjiti kompleksnost za potrebe ovog
rada:
1. Temporalna komponenta
2. Vrijednosna komponenta
Temporalna se komponenta odnosi na vremenski dio analitike. Vremenski je dio najlakše
prikazati kao pristupne točke koje vraćaju skup podataka koji je kreiran ili ažuriran u
određenom intervalu ili trenutku.
Vrijednosna komponenta prikazuje analitiku temeljenu na podudaranju traženih pojmova i
vrijednosti.
Motivacija za razvoj ovakvog tipa aplikacije vezana je uglavnom uz tehničke i arhitekturalne
izazove. Ono što aplikacija mora postići je ispravna analitika pristupnih točaka koja se obavlja
u realnom vremenu.
7
4.2. Arhitektura aplikacije Arhitektura projekta prati spomenute principe mikroservisa te pritom povezuje druge,
standardne elemente web aplikacije.
Slika 3. Prikaz ciljane arhitekture aplikacije (Prikaz autora)
Tehnički se aspekt aplikacije temelji na JavaScript razvojnim okvirima. Najbitniji razlozi za
odabir JavaScript skriptnog jezika kao sredstva implementacije ogledaju se u odličnoj razvojnoj
platformi na strani poslužitelja (Node.js) i stabilnim razvojnim okvirima na strani klijenta
(React). Također u JavaScript ekosustavu postoji i skup razvojnih okvira za upravljanja
agentima, zajedničkog naziva Enmasse.
Za realizaciju ovog projekta najbitniji je razvojni okvir namijenjen upravljanju temeljnim
elementima mikroservisne arhitekture. Razvojni okvir Seneca pruža mogućnosti
implementacije mikroservisne arhitekture te omogućuje proširenje izvornih funkcionalnosti
dodatnim bibliotekama.
4.3. Upravljanje podacima Kod modeliranja podatkovnog sloja aplikacije, potrebno je razmotriti format ulaznih
podataka, stabilnost sustava za upravljanje bazama podataka, podršku za ciljano okruženje i
skalabilnost kao bitan faktor projektiranja web sustava.
Agent koji 'osluškuje'' i prosljeđuje API zahtjeve (request) na definirana odredišta u aplikaciji
ne smije znati ništa o strukturi i pohrani podataka.
8
Agent je minimalni modul kojeg krajnji klijent povezuje u svoju API infrastrukturu te kao
takav mora biti realiziran bez nepotrebnih dodataka i blokirajuće programske logike.
Agent ne oblikuje podatke, već ih samo prikuplja i prosljeđuje. Željena brzina odaziva ne
dozvoljava dodatna mapiranja podataka u strukturirane module. Duga i nepotrebna mapiranja
mogu drastično smanjiti brzinu odaziva te samim time usporiti klijentsku API infrastrukturu.
Podaci koje agent prikuplja varijabilne su strukture generirane unutar dinamičnog okruženja
koje može kreirati N simultanih zahtjeva. Sustav za upravljanje bazama podataka mora moći
zadovoljiti takve nedeterminističke zahtjeve.
Prijašnje iskustvo u razvoju aplikacija, specifični zahtjevi i literatura suzili su izbor na
nekoliko NoSQL sustava (CouchDB, MongoDB i CassandraDB). MongoDB nametnuo se kao
logičan izbor zbog lakoće integracije, bogatog upitnog jezika i dostatnih performansi.
MongoDB je izvorišna točka daljnjeg modeliranja arhitekture sustava, ali prije ulaska u taj
proces, potrebno je dobiti dojam o ostalim aspektima sustava.
4.4. Izazovi implementacije klijenta Iz arhitekture aplikacije vidljivo je da je klijent samo konzument obrađenih podataka kroz
predefinirane API pristupne točke. Uniformne API pristupne točke omogućuju nezavisnost
implementacije klijenta, drugim riječima, mobilni, web i ostali klijenti mogu jednako koristiti
iste izvore podataka.
Tehnički gledano, ovakav tip arhitekture zahtjeva puno AJAX poziva od strane klijenta te
čekanje na završetak istih. Implementacija tako kompleksne logike zahtjeva dosta testiranja i
vremena, te je u kontekstu JavaScript okruženja racionalno iskoristiti postojeće razvojne okvire.
(Mikowski i sur., 2013:48)
U domeni SPA razvojnih okvira (Single Page Application) svakako dominira React kao
visoko performansni razvojni okvir korišten u velikom broju aplikacija koje omogućuju
simultani rad mnogo korisnika (Facebook, Netflix itd.)
SPA aplikacije predstavljaju zasebni sustav koji također donosi izazove vezane uz organizaciju
i arhitekturu aplikacije. Samim time postoje i striktne paradigme i razvojni okviri koje
omogućuju skalabilnost SPA aplikacija.
Jedna od takvih paradigmi je svakako Redux, koji je nastao kao pandan Flux paradigmi i donio
nekoliko bitnih noviteta na područje realizacije SPA aplikacija. Spomenuto je da je strana
klijenta konzument obrađenih podataka, te kao takva dolazi zadnja u procesu razvoja aplikacije.
9
5. Karakteristike Node.js razvojnog okvira Razvoj Node.js okvira započeo je 2006. godine kao privatni projekt Ryana Dahla. Node
inicijalno nije bio zamišljen kao aplikacijski okvir za JavaScript, a autor je eksperimentirao s
različitim razvojnim okruženjima. ''Lua nije toliko idealan, ali je zanimljiv jezik no nije mi se
dopadalo što već postoji mnogo dodataka koji su sadržavali blokirajući kod. Programski jezik
C je imao istih problema kao i Lua i nije široko rasprostranjen. V8 je došao u to vrijeme te sam
doživio prosvijetljenje. Shvatio sam da je JavaScript idealan jezik za ono što sam želio:
jednodretven, bez prijašnjih susreta sa serverskom stranom i bez postojećih
dodataka.''(McCarthy, 2011)
Node.js platforma je jednodretvena zbog korištenja JavaScript programskog jezika.
Node.js koristi takozvanu ''petlju događaja'' (event loop). Petlja događaja služi za korigiranje
pristupa određenih dijelova programa pojedinim resursima u određenoj jedinici vremena.
Nekoliko je karakterističnih elemenata petlje događaja. Na početku učitava se program te slijedi
evaluacija preostalih zadataka Ako isti postoje, čeka se izvršavanje pojedinih akcija. Svaka
akcija unutar petlje događaja implementirana je povratnim pozivom funkcije (callback
function).Ta funkcija sadrži i svu logiku za obradu odgovora petlje događaja. Nakon završetka
izvršavanja funkcije, petlja provjerava ima li još aktivnosti za izvršiti i u suprotnom prekida
program ili ponovno prolazi cijeli postupak. Bitno je napomenuti da se samo jedna funkcija
može izvršavati u određenom trenutku te stoga nije moguće prognozirati slijed izvršavanja. S
druge strane time je omogućeno konkurentno izvršavanje dvije ili više funkcija.
Slika 4. Prikaz petlje događaja (Mills, 2015)
10
6. Uvod u Seneca.js razvojni okvir Prije ulaska u proces implementacije programskog rješenja, potrebno je razumjeti način
rada i ključne termine vezane uz Seneca.js razvojni okvir2
Za početak, potrebno je shvatiti što je Seneca.js uopće. Seneca.js je razvojni okvir za Node.js
platformu čija je posebnost u tome što apstrahira organizaciju i komunikaciju mikroservisa te
učahuruje potrebnu logiku za realizaciju tih kompleksnih zadataka.
Seneca je proizvod otvorenog koda, dozvoljen za modificiranje i proširivanje od zajednice.
Jednostavnost je ključna karakteristika Seneca okvira koji povezuje mikroservise kroz napredni
sustav poklapanja uzoraka (pattern-matching) koji odvaja komunikacijski sustav od
implementacije.
Sustav za poklapanje uzoraka moguće je predočiti na jednostavnijem primjeru. Ako postoje tri
inicijalna uzorka sljedećih oblika:
• { a: 0, } oznaka X
• { a: 0, b: 0 } oznaka Y
• { a:0, b:1 } oznaka Z
Neka dolazi zahtjev oblika {a: 0}. Taj zahtjev u potpunosti se podudara s uzorkom X te se isti
uzorak vraća kao odgovor. Zahtjev oblika {b:2} ne podudara se ni s jednim uzorkom, a odgovor
je prazan skup {}. Ako u sustav stigne zahtjev {a: 0, b:1} on se djelomično poklapa s uzorkom
X, ali potpuno poklapanje ima uzorak Z te se taj uzorak vraća kao odgovor.
Osnovni Seneca razvojni API pruža dvije osnovne metode za realizaciju opisane komunikacije
te se na iste potrebno detaljnije osvrnuti.
6.1. Metode seneca.add() i seneca.act() Ove dvije metode najlakše je razumjeti povuče li se paralela sa sustavom događaja i
osluškivača (event handlers).
Metoda seneca.act({role: 'shopping-cart', action: 'buy}) odašilje proizvoljni uzorak. Vodeći se
opisanim algoritmom podudaranja uzoraka, metoda seneca.add({role: 'shopping-cart', action:
'buy'}) prihvaća uzorak te radi daljnju obradu.
Navedene stavke predstavljaju okosnicu komunikacije mikroservisa. Termin akcija koristi se
za formatirani zapis kojim komuniciraju ove dvije metode.
2 http://senecajs.org/
11
Organizacijski problem mikroservisa Seneca.js rješava kroz koncept ponovo iskoristivih
biblioteka (plugins). Svaka biblioteka sadržava jednu ili više akcija. Biblioteka sa samo jednom
akcijom ima slijedeći oblik:
Slika 5. Biblioteka sa samo jednom akcijom (Prikaz autora)
Navedenu biblioteku, Seneca.js može koristiti u različitim kontekstima pozivajući
seneca.use(plugin) metodu. Programer ima zadaću identificirati moguće biblioteke na temelju
specifikacije projekta i drugih izvora.
U poglavlju 4.2. Arhitektura aplikacije prikazan je raspored i okvirne metode
komunikacije mikroservisa. Vidljivo je da svaki mikroservis djeluje zasebno, što u tehničkom
smislu znači da je svaka instanca mikroservisa zasebna aplikacija koja koristi odvojene mrežne
resurse.
Seneca razvojni API pruža metodu seneca.client() za odvajanje instance mikroservisa u
drugačiju mrežnu okolinu.
Navedena metoda prihvaća konfiguracijski objekt koji sadrži ciljanu web ili IP adresu te
komunikacijski port na kojem određeni mikroservis osluškuje zahtjeve.
Slika 6. Inicijalna konfiguracija Seneca klijenta (Prikaz autora)
Spomenute metode i dodatne JavaScript biblioteke čine većinu potrebnih programskih
elemenata za realizaciju mikroservisne arhitekture.
12
7. Uvod u višeagentne sustave Prema Schatten (2015.) višeagentni sustav je sustav koji se sastoji od niza agenata koji
su u međusobnoj interakciji. Agent posjeduje mogućnost suradnje i pregovaranja nalik ljudima.
Pregovaranja i suradnja čine osnovu uspješne suradnje između dva ili više agenata. Agenti ne
moraju imati samo jednu aktivnost te svaki od agenata može obavljati niz akcija koje daju
krajnji rezultat ili prenose rezultat sljedećem agentu u nizu.
Za potrebe ovog rada bitno je istaknuti nekoliko vrsta agenata. Svaki od tipova agenata
karakterističan je za određeni oblik okruženja i zadataka koje obavlja.
1. Reaktivni agenti – prate promjene u okolini. Svaka promjena u okolini kao
rezultat ima pravovremenu reakciju agenta.
2. Proaktivni agenti – kao ulaz primaju niz zadataka koje mogu izvršiti samostalno,
bez ljudskog faktora.
Uz navedene agente, potrebno je spomenuti i okruženja u kojima se isti mogu izvršavati. Naime,
pojedini agent ovisan je o razini promjena u okolini. Kontinuirana su okruženja neopisiva
diskretnim skupom stanja, tj. skupovi vrijednosti imaju jednako značenje, ali različite
vrijednosne grupe. Dinamična se okruženja mijenjaju neovisno o agentima i njihovim akcijama.
U neepizodičnim okruženjima akcija agenta posljedica je prošlih završenih akcija.
Iako ovaj rad u praktičnoj formi ne obuhvaća sva navedena stanja, bitno ih je spomenuti zbog
shvaćanja različite prirode agenata.
7.1. Reaktivni agenti
Reaktivni agent prati stanje okoline te na temelju određenih promjena izvještavaju ostale
agente ili elemente sustava. Postoje primjeri implementacije reaktivnih agenata u svrhu
analiziranja i obrade skupa podataka3, ali primjena reaktivnih agenata u području analize
zahtjeva i odgovora na implementacijski niskim razinama web aplikacije i dalje nije dovoljno
pokriveno područje.
U kontekstu ovog rada, reaktivni agenti raspoređeni su u manje module koji međusobno
komuniciraju i razmjenjuju informacije. Rezultat akcija reaktivnih agenata skup je informacija
koje predstavljaju temelj donošenja zaključka o sustavu.
3 http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=1233840
13
Reaktivni agenti djeluju unutar kontinuiranog okruženja koje prima veliki broj ulaznih
informacija u jedinici vremena. Agent mora razumjeti ulazne informacije, imati definirane
akcije koje izvršava te na temelju akcija, agent daje krajnji rezultat.
Dio aplikacije namijenjen grupiranju i pretraživanju informacija moguće je realizirati u obliku
proaktivnog agenta. Zbog drugih implementacijskih faktora, proaktivni agenti nisu dio
implementacije pretraživanja informacija, ali predstavljaju jedno od prikladnih rješenja.
14
8. Agent u službi prikupljanja podataka Specifičnost implementacije agenta ogleda se u njegovoj ulozi i zahtjevima koje mora
ostvariti. Naime, cilj agenta je neovisno funkcioniranje u obliku zasebnog modula kojeg je
moguće preuzeti na repozitoriju JavaScript paketa (NPM). Kao takav, agent mora djelovati
samostalno, ne smije imati specifičnih zahtjeva za okolinom u kojoj se izvršava i zbog konteksta
u kojem se odvija njegovo izvršavanje, performanse moraju biti na visokoj razini.
Prikupljanje podataka klijentskog API servisa povlači nekoliko relativno kompleksnih zadataka
koji se moraju simultano izvršavati, a Enmasse razvojni okvir omogućit će razvoj manjeg
višeagentnog sustava za prikupljanje podataka u realnom vremenu.
Struktura višeagentnog sustava prilično je jednostavna, a komunikacija između pojedinih
agenata implementira se koristeći Babble biblioteku.
Slika 7. Detaljni prikaz komunikacije elemenata web aplikacije (Prikaz autora)
Nazivi agenata na slici odgovaraju konkretnim JavaScript datotekama. Svaki zahtjev i
odgovor (request, response) iz okoline ulazi u Middleware agent. Termin middleware u razvoju
web aplikacija koristi se za oznaku sloja posrednika, koji prihvaća podatke iz prijašnjih slojeva,
izvrši obradu te šalje nove podatke slijedećim slojevima.
Zbog specifične strukture request i response objekata, navedeni agent mora izvući potrebne
podatke i prilagoditi ih daljnjem slanju preko mreže.
15
Svaki je agent vezan za odgovarajući korisnički račun koristeći jedinstvenu oznaku klijenta
(client secret). Middleware agent kao inicijalna točka komunikacije sa stranom poslužitelja
mora napraviti provjeru potrebnih parametara za autentikaciju s vanjskim servisom.
Slika 8. Autentikacija middleware agenta s vanjskim servisom (Prikaz autora)
Podaci koje agent mora prikupiti čine osnovu podataka za daljnju analitiku. Svi se podaci
spremaju u jedan JavaScript objekt koji se putem mreže prenosi u JSON formatu.
Slika 9. JavaScript objekt za pohranu podataka agenta (Prikaz autora)
HTTP protokol pruža nekoliko načina slanja podataka. U REST terminologiji nazivaju se
metode a mogu biti slijedeće:
1. GET
2. POST
3. PUT
4. DELETE
5. PATCH
Metodologije poput RESTful aplikacija definiraju kontekst korištenja pojedinih metoda, ali za
agenta takav je kontekst nebitan. Potrebno je pohraniti samo tip metode koju će krajnji korisnik
16
znati postaviti u implementacijski kontekst aplikacije. Uspješnost izvršavanja pojedinog
zahtjeva ogleda se u HTTP statusnom kodu kojeg vrati poslužitelj.
HTTP protokol definira grupe kodova prema njihovoj namjeni:
1. Grupa 1xx - informacijski kodovi
2. Grupa 2xx – indikator uspješnosti
3. Grupa 3xx – preusmjeravanje
4. Grupa 4xx – pogreška na strani klijenta
5. Grupa 5xx – pogreška na strani poslužitelja
Gledano na primjeru, statusni kod 200 označava uspješan zahtjev, 404 je oznaka nepostojećeg
resursa dok statusni kod 500 prikazuje pogrešku poslužitelja.
Uz podatke o poslužitelju i veličini zahtjeva i odgovora, agent mora generirati jedinstveni
identifikator (uid) svakog podatka koji se šalje na poslužitelj. Takav identifikator služi
pojednostavljenoj i bržoj analizi jer pruža jedinstvenu oznaku svakog entiteta.
Latencija služi kao primitivni indikator performansi sustava. U ovakvoj se okolini latencija
računa kao razlika vremena slanja zahtjeva i primanja odgovora od strane poslužitelja.
Faktori koji utječi na latenciju ogledaju se u brzini mreže, složenosti infrastrukture poslužitelja,
performansama poslužitelja i optimiziranosti programskog koda.
Slika 10. Latencija odgovora poslužitelja (Prikaz autora)
Implementacija Middleware agent modula je prilično bazična, uz nekoliko elemenata
koji iziskuju posebnu pozornost.
Zbog potencijalno većeg broja slojeva posrednika, moguće je da agent neće u svakom trenutku
biti u mogućnosti pročitati sadržaj request i response objekata. Takav je problem moguće
jedino riješiti vlastitom implementacijom metoda korištenih u tijeku izvršavanja zahtjeva i
odgovora koje nakon obrade pozivaju nativne metode kako bi se nastavio daljnji slijed
izvršavanja programa.
Prikupljeni se podaci prosljeđuju u Delegate agenta čija je uloga koordinacija daljnjih koraka
izvršavanja.
Delegate agent mora iskoristiti metode koje pruža Babble razvojni okvir kako bi aktivirao akcije
drugih agenata.
17
Slika 11. Vlastita implementacija nativnih metoda (Prikaz autora)
Prikupljeni se podaci prosljeđuju u Delegate agenta čija je uloga koordinacija daljnjih koraka
izvršavanja.
Delegate agent kao reaktivni agent mora iskoristiti metode koje pruža Babble razvojni okvir
kako bi aktivirao akcije drugih agenata.
Svi agenti koriste Logger agent koji pruža metode za zapisivanje i praćenje ispada i akcija u
sustavu. Agent reagira na temelju zahtjeva koje prima od ostalih agenata. Logger agent koristi
vanjski modul simple-node-logger4 Vanjski modul apstrahira funkcionalnost kreiranja i
upisivanja podataka u datoteku, a zbog svoje stabilnosti i provedenih testova puno je
adekvatnije rješenje nego vlastita implementacija istih funkcionalnosti. Logger agent sadrži
metodu log koja u zadanu datoteku upisuje kontekst i poruku.
Slika 12. Implementacija Logger agenta (Prikaz autora)
4 https://www.npmjs.com/package/simple-node-logger
18
Krajnji rezultat je datoteka formatirana po recima, a svaki se red odnosi na jednu akciju u
sustavu.
Slika 13. Log datoteka (Prikaz autora)
Svaki kompleksniji sustav mora imati oblik evidentiranja akcija jer to, u slučaju ispada
ili neadekvatnog funkcioniranja pojedinih elemenata istog, osigurava mehanizam pronalaska i
ispravaka pogrešaka.
Podatke koje middleware agent uspije odrediti iz request i response objekata, potrebno je
pohraniti u bazi podataka. Agent mora napraviti zahtjev na određeni servis, proslijediti podatke
formatirane na spomenuti način te evidentirati akciju u tzv. log datoteku.
Iako ovakav postupak ne izgleda komplicirano, za sobom povlači veliki optimizacijski problem.
Gledano na primjeru, ako manji API sustav zaprimi 300 zahtjeva u rasponu od sat vremena,
agent mora poslati zahtjev na vanjski servis isto toliko puta. Zaprimljeni zahtjev, vanjski servis
mora obraditi i proslijediti u bazu podataka.
Ovakav proces je blokirajući i osjetno usporava performanse svih dijelova sustava. Rješavanje
ovog problema izvodi se prividnim ograničavanjem broja zadataka i paralelnom obradom.
Slika 14. Paralelna obrada zadataka u redu konkurentnosti = 4 (Prikaz autora)
Ako je svaki zahtjev prema poslužitelju jedan zadatak {Z1…ZN}. U red Q moguće je pohraniti
N istovremeno aktivnih zadataka {Q1…QN} dok se ostatak stavlja na čekanje. Broj aktivnih
19
zadataka određen je unaprijed definiranom konstantom. Takvi međusobno aktivni zadaci
paralelno se obrađuju i odašilju prema poslužitelju.
S tehničkog aspekta, implementacija ovakvog oblika paralelnosti zahtjevna je i kompleksna za
testiranje.
Korištenjem biblioteka otvorenog koda moguće je implementirati ovakav tehnički izazov.
Jedna od takvih biblioteka je async.js5. Unutar skupa metoda async biblioteke, postoji metoda
queue koja rješava problem prikazan na slici.
Prvi korak je definiranje zadatka Z koji će se izvršavati. Više je puta spomenuto da je zadatak
agenta prosljeđivanje prikupljenih podataka na udaljeni servis. Implementacija takvog zadatka
je oblika:
Slika 15. Implementacija Async Queue strukture (Prikaz autora)
Svaki zadatak je funkcija koja prihvaća dva parametra. Prvi parametar su podaci koje zadatak
koristi. Podaci mogu biti proizvoljna struktura (objekt, polje, primitivni tip itd.) Drugi
parametar je obavezna funkcija s povratnim pozivom (callback). Funkcija ima signalnu ulogu,
tj. označava kraj konkretnog zadatka i mogućnost obrade sljedećeg u nizu. Definirani zadatak
5 https://github.com/caolan/async
20
prima skup podataka od Middleware agenta, šalje zahtjev POST metodom na udaljeni
poslužitelj. Zahtjev u svojem definicijskom dijelu, tzv. tijelo zahtjeva, sadrži zaprimljeni skup
podataka. U slučaju pogreške s udaljenog servisa, zadatak ispisuje adekvatnu poruku i u svakom
slučaju završava.
Uz definiciju funkcije zadatka, određuje se i stupanj konkurentnosti (concurrency level).
Taj broj definira maksimalni limit zadataka koji se istovremeno izvršavaju. Broj 20 je dobiven
analizom broja zahtjeva sličnih sustava.6 Kod implementacije ozbiljnih, visoko skalabilnih
sustava, broj konkurentnih zadataka određuje je strogim metodama ispitivanja performansi
(benchmark). Definirani se zadaci dodaju u poseban asinkroni red čekanja (async queue) koji
se inicijalno definira unutar Queue agenta.
Slika 16. Implementacija Queue agenta (Prikaz autora)
Ovim korakom zaokružena je implementacija višeagentnog sustava za prikupljanje podataka iz
API sustava.
6 http://www.slideshare.net/apigee/predict-prepare-for-and-overcome-api-scale-challenges
21
9. Implementacija mikroservisne arhitekture Centralna točka web sustava, kao i glavni fokus ovog rada, svakako su mikroservisi na
strani poslužitelja.
Funkcionalnosti koje strana poslužitelja mora imati moguće je segmentirati po generički
opisanim grupama. Ovakav pristup daje uvid u potrebne značajke aplikacije te omogućuje
planiranje i procjenu razvoja.
Prije ulaska u razvoj aplikacije, moguće je identificirati nekoliko grupa funkcionalnosti:
1. Autentikacija i autorizacija korisnika
2. Temporalna analiza
3. Vrijednosna analiza
4. Komunikacija s agentom
5. Pohrana podataka
Ovu listu funkcionalnosti moguće je grupirati na još višoj razini apstrakcije. Gledano s točke
razine pristupa, postoje dvije grupe funkcionalnosti. Zaštićene funkcionalnosti koje zahtijevaju
autorizaciju korisnika i nezaštićene funkcionalnosti koje, iako mogu koristiti osnovne metode
identifikacije korisnika, ne zahtijevaju autorizaciju i obavljaju se neovisno o akcijama
korisnika.
Seneca.js nudi mogućnost prefiksiranja akcija. Svaku je zaštićenu akciju moguće prefiksirati
oznakom /api, dok one nezaštićene nose prefiks /raw.
Autentikacija i autorizacija korisnika osnovna je komponenta web aplikacije. Iako standardna,
nije tehnički trivijalna. U monolitnim aplikacijama ovaj se problem rješava jednostavnije nego
u slučaju mikroservisne arhitekture.
Slika 17. Autentikacija i autorizacija u monolitnim sustavima (Prikaz autora)
22
U monolitnoj se aplikaciji autentikacija rješava na razini komponente. Svaka komponenta čini
jedan dio monolitne aplikacije. Vanjski zahtjev dolazi do autentikacijske komponente koja,
ovisno o stupnju autoriziranosti korisnika, prosljeđuje zahtjev na slijedeću komponentu ili vraća
korisnika na početnu (neautoriziranu komponentu)
U mikroservisnim se arhitekturama proces autorizacije komplicira zbog specifičnosti
arhitekture.
9.1. Autorizacija i autentikacija u mikroservisnoj arhitekturi U procesu autorizacije i autentikacije u mikroservisnoj arhitekturi moguće je uočiti nekoliko
bitnih razlika u odnosu na monolitnu arhitekturu.
Slika 18. Autentikacija i autorizacija u mikroservisnoj arhitekturi (Prikaz autora)
Svaki servis s kojim komunicira autentikacijski (autorizacijski) servis zasebna je aplikacija.
Održavanje i praćenja korisnikovog stanja unutar monolitne aplikacije izvodi se jednostavno
korištenjem sesija, lokalne pohrane i sličnih mehanizama. Mikroservisna arhitektura ne pruža
takve mehanizme pohrane jer, promatrajući s tehničkog aspekta, takve mehanizme nije moguće
implementirati u okruženju u kojem svaka aplikacija održava zasebno stanje.
Primjene li se principi održavanja stanja iz monolitne aplikacije u ovakvom okruženju, svaka
od aplikacija ne bi znala ništa o autenticiranim korisnicima u drugoj aplikaciji.
23
Svaka web aplikacija posjeduje izvor podataka. Taj izvor ne mora biti u potpunosti centralan,
ali omogućuje upravljanje stanjem određenog broja aplikacija.
U ovom konkretnom slučaju, takav je izvor spomenuta MongoDB baza podataka. Iz arhitekture
prikazane u jednom od uvodnih poglavlja, vidljivo je da svi servisi, iako konceptualno zasebni,
koriste MongoDB bazu podataka kao centralizirani izvor. Ovakva implementacija ne
predstavlja primjer dobre prakse za visoko skalabilne sustave. U takvom bi sustavu postojalo
nekoliko izvora podataka sa zajedničkim izvorima za spremanje autentikacijskih sesija i drugih
osnovnih podataka.
Tehnički zahtjevi tog oblika spadaju u domene optimizacije i skaliranja sustava što je
izvan opsega ovog rada.
Seneca razvojni okvir u svojem osnovnom obliku nema metode za autentikaciju korisnika.
Vanjske biblioteke poput seneca-user7 i seneca-auth8 omogućuju rješavanje ovog problema.
Implementacija bilo kojeg od traženih elemenata aplikacije nije moguća prije konfiguracije
baze podataka.
9.2. Konfiguracija MongoDB baze podataka Kod projektiranja modernih aplikacija, jedna od bitnih odluka koju programeri i projektanti
moraju donijeti je smještaj i način pristupa bazi podataka. Jedna od mogućnosti je smještaj baze
podataka na vlastitom poslužitelju. Programeri i administratori imaju veću kontrolu nad
konfiguracijom baze podataka, ali troškovi održavanja i skaliranja nisu minimalni.
Druga opcija ogleda se u sve rasprostranjenijim bazama podataka kao servisima (Database as
a Service). Iako takva konfiguracija ne pruža toliko opcija za podešavanje, uvelike ubrzava
proces skaliranja.
Servis MongoLab jedan je od poznatijih Database as a Service sustava.
MongoLab povezuje instance baze podataka na korisnički račun. Nakon prijave i registracije
moguće je koristiti besplatne verzije MongoDB baze podataka. Za potrebe ovog rada dovoljna
je upravo osnovna opcija koja pruža 500MB prostora, dovoljno radne memorije i brzi SSD disk.
7 https://github.com/senecajs/seneca-user 8 https://github.com/senecajs/seneca-auth
24
Kod kreiranja instance baze podataka postoji nekoliko opcija na koje je potrebno obratiti
pozornost.
Slika 19. Administrativno sučelje MongoLab servisa (Prikaz autora)
MongoLab ne koristi vlastite pružatelje infrastrukture pa se instance baze podataka smještaju
na neke od najpoznatijih pružatelja usluga pohrane (Amazon Web Services, Google Cloud
Platform itd.) Odabir pružatelja usluga pohrane ne predstavlja veliki faktor za performanse baze
podataka, ali može biti odlučujući faktor ako baza podataka ili aplikacija koristi neki od servisa
određenog pružatelja.
U besplatnoj je inačici moguće postaviti samo jednu instancu baze podataka. Druga, skuplja
opcija, odnosi se na skupinu (cluster) instanci baze podataka koje se međusobno sinkroniziraju
nativnim MongoDB mehanizmima.
25
MongoLab podržava zadnje dvije verzije MongoDB baze podataka, a konkretna instanca koristi
posljednju, MongoDB 3.0.x verziju.
Inicijalna konfiguracija baze podataka i dalje ne dozvoljava udaljeni pristup istoj. Aplikacija
radi na zasebnom poslužitelju te se svaki pristup udaljenoj bazi podataka mora autenticirati.
MongoLab pruža sučelje za kreiranje korisnika i razina pristupa bazi podataka. Rezultat
konfiguracije jedinstveni je identifikator resursa (uri) koji ulazi kao parametar u programski
dio namijenjen komunikaciji s bazom podataka.
Slika 20. Jedinstveni URI identifikator za udaljeni pristup MongoDB bazi podataka (Prikaz autora)
Ovako konfigurirana baza podataka posjeduje osnovne elemente potrebne za komunikaciju s
aplikativnim rješenjem.
9.3. Konfiguracija Seneca.js aplikacijskog okvira Sukladno najboljoj praksi, svaka Node.js aplikacija trebala bi sadržavati inicijalnu opisnu
datoteku. Takva JSON datoteka sadržava različite meta podatke (naziv, verzija, opis i sl.) i listu
biblioteke o kojima aplikacija ovisi (dependencies).
Slika 21. Prikaz package.json opisne datoteke (Prikaz autora)
26
Lista biblioteka sadrži osnovne Seneca ekstenzije zajedno s bibliotekama koje olakšavaju
strukturiranje koda i kontrolu izvršavanja aplikacije.
Jedna od zanimljivijih biblioteka je svakako Q.js9. Za razumijevanje ove biblioteke potrebno je
prvo razjasniti mehanizam Promises koji je svakako jedan od atraktivnijih mehanizama jezika
JavaScript.
Asinkrona akcija u JavaScript jeziku ima slijedeći osnovni oblik:
Slika 22. Osnovni oblik asinkrone akcije u JavaScript jeziku (Prikaz autora)
Funkcija s povratnim pozivom (callback function) je zadatak koji se okida pri završetku
asinkrone akcije i sadrži logiku za daljnju obradu podataka. U ovakvom obliku asinkrone akcije
funkcioniraju dobro, ali problem se odvija u slučaju sinkroniziranja dvije ili više asinkronih
akcija. Gledano na primjeru, ako postoji asinkroni zadatak koji radi upit na bazu te po završetku
šalje rezultat na udaljeni poslužitelj. Slanje podataka je također asinkroni zadatak koji po
svojem završetku poziva asinkroni zadatak upisa rezultata slanja u datoteku.
Slika 23. Sinkronizacija asinkronih zadataka (Prikaz autora)
I na manjem primjeru poput ovoga, vidljivo je da je ovakvo učahurivanje akcija teško čitljivo,
a pronalaženje pogrešaka u nizu asinkronih zadataka jako je teško provedivo.
9 https://github.com/kriskowal/q
27
Mehanizam Promises dolazi kao standardni dio nove verzije JavaScript jezika, ali zbog trenutno
male zastupljenosti, koriste se vanjske biblioteke poput Q.js. Koristeći navedeni mehanizam
prethodni blok koda poprima oblik:
Slika 24. Sinkronizacija asinkronih zadataka koristeći Q.js biblioteku (Prikaz autora)
Iako se ovaj blok programskog koda doima kompleksnijim, ovakvo kontroliranje slijeda
izvršavanja asinkronih akcija uvelike olakšava pronalaženje pogrešaka i povećava preglednost
koda.
Završetkom određene asinkrone akcije, pokreće se metoda then() koja započinje izvršavanje
slijedeće akcije. Ako se u nizu izvršavanja dogodi pogreška, metoda catch() prima detalje
pogreške.
Seneca u standardnoj konfiguraciji ne koristi potrebne mehanizme za komunikaciju
mikroservisa u web okruženju. Prilikom inicijalizacije Seneca razvojnog okvira potrebno je
povezati poseban seneca-web biblioteku s Express.js poslužiteljem (https://expressjs.com/ ).
Express.js jedan je od najpoznatijih poslužitelja za Node.js platformu. Glavna prednost mu je
svakako minimalizam i fleksibilnija politika u strukturiranju projekta.
28
Express u ovom kontekstu služi kao lijepilo koje omogućuje sinkronizaciju rada zasebnih
mikroservisa. Integracija Seneca i Express razvojnih okvira izvodi se slijedećim blokom
programskog koda:
Slika 25. Integracija Express i Seneca razvojnih okvira (Prikaz autora)
Seneca posjeduje metodu ready() koja je oznaka završetka učitavanja svih elemenata Seneca
razvojnog okvira.
Unutar te metode potrebno je inicijalizirati Express poslužitelj. Ključna linija programskog
koda koja integrira funkcionalnosti Seneca i Express poslužitelja je:
Slika 26. Povezivanje Seneca Web modula s Express poslužiteljem (Prikaz autora)
Na kraju je potrebno definirati pristupni port na kojem će poslužitelj osluškivati zahtjeve iz
okoline (za testiranje koristit će se port 3020).
Nakon osnovne konfiguracije potrebno je razmotriti strukturu aplikacije.
29
Inicijalna struktura aplikacije pruža dobar uvid u neke od tehnoloških izazova s kojima se
moguće susresti.
Slika 27. Inicijalna struktura aplikacije (Prikaz autora)
Aplikacija ima nekoliko osnovnih modula. Srž aplikacije predstavlja analytics modul koji radi
prikupljanje i filtriranje postojećih podataka na temelju parametara iz okoline.
Modul exchange-data komunicira s agentom i prihvaća te zapisuje inicijalne skupove podataka
u MongoDB bazu podataka.
Autorizacija i autentikacija korisnika obavlja se u modulu auth, a moduli helpers i config sadrže
niz metoda koji potpomažu rad ostalih modula.
Svaki od modula također ima definiranu internu strukturu. Po pravilima najbolje prakse svaki
kompleksniji programski modul mora biti sastavljen od nekoliko manjih logičkih cjelina
Slika 28. Struktura pojedinog modula (Prikaz autora)
Svaki modul ima inicijalnu index.js datoteku koja definira ulogu modula i povezuje
elemente iz clients i plugins direktorija. Svaki modul može instancirati jednog ili nekoliko
klijenata koji djeluju kao zasebni mikroservisi. Klijenti koriste metode unutar plugins
direktorija koji apstrahiraju operacije različite namjene.
Iako postoji inicijalna opisna datoteka, package.json, svaki od modula sadrži zasebnu
package.json datoteku. Razlog tome je pokušaj potpunog razdvajanja modula te zajedno sa
ovisnim datotekama čini jednu zasebnu cjelinu.
30
Seneca okvir mora pružiti metode komunikacije s MongoDB bazom podataka. Inicijalna
instalacija Seneca okvira je minimalna i ne sadrži integracijske mehanizme za pojedinu bazu
podataka.
Vanjska biblioteka, seneca-mongo-store10 povezuje postojeće Seneca entitete s
istoimenim entitetima u bazi podataka.
Entiteti u Seneca razvojnom okviru nisu ništa osim skupa akcija koji rade upit nad bazom
podataka. Pojedini entitet ne zna ništa o tipu baze podataka, ali koristi dodatne biblioteke koji
su posrednik između entiteta i baze podataka.
Konfiguracija entiteta obavlja se prije inicijalizacije Seneca razvojnog okvira te predstavlja
jedan od preduvjeta za uspješnu inicijalizaciju.
Zbog spomenutih autentikacijskih i autorizacijskih izazova, modul entity kombinira se s
modulima user i auth. Također, seneca-mongo-store biblioteka mora znati putanju do izvora
podataka te kao konfiguracijski parametar prihvaća URI identifikator kakav je vidljiv na
MongoLab sustavu. Konfiguracija auth biblioteke također se obavlja prije inicijalizacije Seneca
razvojnog okvira. Seneca u osnovnoj inačici sadrži minimalan oblik auth biblioteke.
Autentikacija se izvodi na skupu programskih metoda koje se prefiksiraju jedinstvenom /api
oznakom. Svaki zahtjev koji dolazi na /api mora sadržavati potrebne autorizacijske elemente.
Autorizacija se obavlja korištenjem posebne oznake (token) koja sadrži podatke o tipu
korisnika, opisne podatke i ulogu koju korisnik ima u sustavu.
Slika 29. Konfiguracija auth biblioteke (Prikaz autora)
10 https://github.com/senecajs/seneca-mongo-store
31
Svi se podaci o korisniku i prijavi zapisuju u dva strukturirana entiteta (sys_login i sys_user).
Za kreaciju i upravljanje korisničkim računom postoje tri osnovna URL-a koji pozivaju
pripadne metode
1. /auth/register
2. /auth/login
3. /auth/logout
Prva metoda kreira podatke u oba spomenuta entiteta. Metoda za prijavu, /auth/login,
modificira podatke iz sys_login, ali samo čita i djelomično modificira podatke o korisniku.
Posljednja se metoda odnosi na odjavu korisnika sa sustava i djelomično modificira stanje
kolekcije sys_login.
Termin kolekcija u NoSQL se bazama koristi za opisivanje strukture koja sadrži više
dokumenata. Dokument zapis u strukturiranom formatu. MongoDB koristi poseban format
binarni JSON, tzv. BSON. Na tehničkoj razini BSON je binarno kodirani JSON objekt koji
podržava unaprijed definirane tipove podataka
MongoLab sučelje pruža uvid u kreirane kolekcije i nizove dokumenata u pojedinoj kolekciji.
Slika 30.1. Prikaz kolekcije kroz MongoLab administraciju (Prikaz autora)
32
Na primjeru exchange-data modula moguće je prikazati sve elemente implementacije
mikroservisne arhitekture u Seneca.js okviru.
Inicijalna (index.js) datoteka ima ulogu povezivanja ostalih dijelova programskog koda iz
plugins i clients direktorija. Stoga je implementacija inicijalne datoteke minimalna i uvidom u
strukturu moguće je odrediti koje biblioteke i module exchange-data koristi za obavljanje
funkcionalnosti
Slika 31. Inicijalizacija exchangeData klijenta (Prikaz autora)
Svaki modul u Node.js platformi mora se definirati kroz module.exports objekt. Taj objekt je
globalni izvor definicije modula. Svaki modul moguće je koristiti u drugoj datoteci koristeći
require metodu.
Klijent apstrahira svu potrebnu logiku i to je jedini modul o kojem exchange-data ovisi.
Implementacija klijenta razlaže logiku za obradu zahtjeva na manje module. Konfiguracijski
objekt koji se prenosi kao parametar u seneca.client metodu definira mrežnu okolinu unutar
koje klijent djeluje.
Slika 32. Konfiguracijski objekt seneca.client metode (Prikaz autora)
33
Instanca klijenta pohranjena je u senecaClient varijabli. Svaki Seneca modul posjeduje
mehanizam pozivanja povratne funkcije pri inicijalizaciji. U toj povratnoj funkciji spajaju se
standardni URL identifikatori i akcije mikroservisa.
Slika 33. Inicijalizacija exchangeData modula (Prikaz autora)
Kod mapiranja URL identifikatora i akcija, Seneca prvo u obzir uzima polje prefix. U objektu
map uzima se ključ kao slijedeći element identifikatora. U ovom primjeru identikator je
/raw/insert. To u pravilu znači da kad klijent napravi POST tip zahtjeva na URL /raw/insert
izvršava se akcija oblika {service: ''exchange-raw'', action: ''insert''}. Takav oblik mapiranja
dozvoljava veliku fleksibilnost i široki aspekt implementacijskih mogućnosti.
Izvršavanja akcije seneca.act() uvjetovano je postojanjem seneca.add() metode. Ranije
inicijalizirani klijent mora kao odgovor na zahtjev kroz URL aktivirati pripadnu akciju
formiranu kroz proces mapiranja.
Slika 34. Seneca.act metoda u ulozi sinkronizacije klijenata (Prikaz autora)
34
Dosad spomenuti elementi čine komunikacijsku razinu mikroservisa. Konkretna
implementacija koja stoji iza spomenute akcije zadnji je korak u lancu prosljeđivanja akcija.
Konkretna se implementacija najčešće nalazi u jednom ili više biblioteka u plugins direktoriju.
Zbog specifičnih se zahtjeva često koriste i vanjske biblioteke koje ubrzavaju i olakšavaju
pisanje konkretnog programskog rješenja.
U ovom je slučaju veliki naglasak na Q.js biblioteci i korištenju Promise mehanizama za
strukturiranje izvršavanja koda.
Slika 35. Sinkronizacija asinkronih akcija u implementaciji logike klijenta (Prikaz autora)
U varijablama users i exchange pohranjuju se instance entiteta koji omogućuju direktan pristup
bazi podataka.
Svaki korak izvršavanja programa razdvojen je u funkciju koja, po principu jedne odgovornosti,
radi jedan tip obrade podataka i vraća Promise kao odgovor.
Slika 36. Asinkrona metoda za dohvaćanje podataka o korisniku (Prikaz autora)
35
Ovakva implementacijska struktura jednaka je za svakog od spomenutih klijenata u aplikaciji.
Time se zaokružuje cjelina vezana uz implementaciju mikroservisa i poslužitelja. Kako bi
podaci imali svrhu, strana klijenta ih mora konzumirati i omogućiti prikaz rezultata korisniku.
36
10. Implementacija klijenta Izvedba klijenta u formi SPA (Single Page Application) omogućuje konzumaciju API
pristupnih točaka neovisno o poslužitelju na kojem se nalazi.
Aplikacija je realizirana korištenjem React programskog okvira i Redux biblioteka i
metodologija. Uz standardne tehnologije poput CSS stilskog jezika, aplikacija koristi novi ES6
standard JavaScript jezika. ES6 standard dozvoljava korištenje klasa i ostalih naprednih
struktura. Problem slabe podrške u web preglednicima rješava se korištenjem JavaScript
kompajlera poput Babel.js11. JavaScript kompajler kao ulaz prima ES6 programski kod, a kao
izlaz vraća programski kod prilagođen današnjim preglednicima. Automatizacija zadatka
pretvorbe programskog koda obavlja se Webpack12 bibliotekom.
Webpack biblioteka iz konfiguracijske webpack.js datoteke čita podatke o okolini, te na temelju
definiranih parametara automatizira definirane procese.
Slika 37. Isječak webpack.config.js datoteke (Prikaz autora)
11 https://babeljs.io/ 12 https://webpack.github.io/
37
Minimalna jedinica funkcionalnosti u React razvojnom okruženju je komponenta. Jedna
komponenta posjeduje nekoliko unaprijed definiranih metoda koje se pokreću u različitim
fazama rada pojedine komponente. (Fedosejev, 2015:27)
1. componentWillMount
2. componentDidMount
3. componentWillReceiveProps
4. shouldComponentUpdate
5. componentWillUpdate
6. componentDidUpdate
7. componentWillUnmount
Svaka od tih metoda ima ulogu da na temelju trenutnog stanja komponente i dodatnih
modifikacija definira novo stanje komponente.
U Redux metodologiji postoje dva stanja podataka. Prvo je bazično unutarnje stanje
komponente koje zavisi o spomenutim metodama. Drugo, puno važnije, je globalno stanje
podataka koje se definira kao globalni JavaScript objekt podijeljen na podobjekte. U Redux
paradigmi najbitnije je shvatiti nekoliko ključnih koncepata:
1. akcija (action)
2. reduktor (reducer)
3. odašiljanje (dispatch)
4. objekt pohrane (store)
Proces ažuriranja stanja u Redux metodologiju počinje odašiljanjem akcije. Akcija predstavlja
samo ''uputu'' koji tip reduktora mora djelovati. Reduktor ažurira globalno stanje na način da ga
ne modificira direktno, nego vraća novu instancu objekta pohrane.
Slika 38. Prikaz akcije u Redux paradigmi (Prikaz autora)
38
Takva akcija ulazi u reduktor koji potom vraća kopiju objekta.
Slika 39. Prikaz reduktora u Redux paradigmi (Prikaz autora)
Svaka komponenta prilikom inicijalizacije odašilje akcije potrebne za rad komponente i
završava inicijalizaciju kad se ažurira objekt pohrane.
Slika 40. Isječak implementacije React komponente (Prikaz autora)
Finalna aplikacija povezuje se s API sučelja preko AJAX zahtjeva. Za apstrakciju AJAX
zahtjeva korištena je biblioteka axios.13
13 https://github.com/mzabriskie/axios
39
Finalna aplikacija integrirana je u Express poslužitelj te predstavlja inicijalnu točku pristupa
aplikaciji iz okoline.
Slika 41. Finalni izgled aplikacije (Prikaz autor)
40
11. Testiranje rada aplikacije Ovisnost aplikacije o postojećem API okruženju iziskuje dodatne napore u provođenju
testiranja. Za testiranje ove aplikacije, koristit će se API okruženje PinList14 aplikacije. PinList
je aplikacija temeljena na Node.js platformi koja pruža veliki broj API sučelja. Integracija u
PinList okruženje svodi se na povezivanje agenta s postojećom konfiguracijom.
Slika 42. Prikaz integracije agenta u PinList okruženje (Prikaz autora)
Upite na API sučelje moguće je kreirati kroz aplikacije posebne namjene. Jedna od
takvih aplikacija namijenjena testiranju API pristupnih točaka zove se Postman15. Postman
omogućuje definiranje metoda, pristupnih točaka i ostalih parametara za komunikaciju s API
okruženjem.
Slika 43. Prikaz testiranja kroz Postman alat (Prikaz autora)
14 http://pinlist.me/ 15 https://www.getpostman.com/
41
12. Zaključak Nediskutabilno je da mikroservisna arhitektura postaje standard implementacije
kompleksnijih, visoko skalabilnih aplikacija. Kombinacija s modernim pristupom izrade SPA
aplikacija omogućuje dosad neviđenu fleksibilnost i heterogenost web aplikacija.
Pogrešno je smatrati da je mikroservisna arhitektura odgovor na svaki zahtjev razvoja web
aplikacija. Kod jednostavnijih se aplikacija uvođenje i održavanje mikroservisne arhitektura
povezuje s velikim troškovima koji mogu proizaći iz razvoja. Mikroservisna arhitektura
proizašla je prvenstveno iz potrebe kontroliranog ispada sustava. Konkretno, ispadom jednog
od klijenata u mikroservisnoj arhitekturi, ostali klijenti neovisno obavljaju svoje
funkcionalnosti.
U radu kompleksnih aplikacija, najbitnije je osigurati minimalnu razinu ispada jer to smanjuje
troškove i gubitke na najmanju vrijednost. Mikroservisna je arhitektura odgovor industrije na
sve veće zahtjeve web aplikacija. (Richardson, 2015)
42
Literatura [1] Everts T (2013) Web Performance Today dostupno 5.9.2016. na
http://www.webperformancetoday.com/2013/06/05/web-page-growth-2010-2013/ [2] Richardson C (2014) Pattern: Microservices arhitecture dostupno 5.9.2016. na
http://microservices.io/patterns/microservices.html [3] Gonzalez D (2007) Developing Microservices with Node.js (1. izd.) Packtpub.
[4] Mikowski M, Powell J (2013) Single Page Web Applications. Manning [5] McCarthy J (2011) Node.JS Interview with creator Ryan Dahl, dostupno 5.9.2016. na
http://bostinno.streetwise.co/2011/01/31/node-js-interview-4-questions-with-creator-ryan-dahl/
[6] Mills A (2015) How does Node.js work asynchronously without multithreading dostupno 5.9.2016. na http://softwareengineeringdaily.com/2015/08/02/how-does-node-js-work-asynchronously-without-multithreading/
[7] Fedosejev A (2015) React.js Essentials. Packtpub
[8] React Component API dostupno 12.9.2016. na https://facebook.github.io/react/docs/component-api.html
[9] Seneca API reference dostupno 12.9.2016. na http://senecajs.org/api/ [10] Express.js 4.x API reference dostupno 13.9.2016. na http://expressjs.com/en/api.html
[11] Schatten M (2015) Višeagentni sustavi – nadopuna predavanju. Fakultet organizacije i informatike, Varaždin
[12] Chang H., Jeng J., Schiefer J. (2003) An agent based architecture for analyzing business processes of real-time enterprises, IEEE.
[13] Pickering H. (2015) Reimagining Single-Page Applications With Progressive Enhancement, dostupno 13.9.2016. na https://www.smashingmagazine.com/2015/12/reimagining-single-page-applications-progressive-enhancement/
[14] McNeil M, Nathan I (2015) Sails.js in Action. Manning [15] Axios API reference, dostupno 13.9.2016. na https://github.com/mzabriskie/axios
[16] Babel API reference, dostupno 13.9.2016. na https://babeljs.io/docs/usage/api/ [17] Richardson C (2015) Pattern: Monolithic Architecture. dostupno 12.9.2016. na
http://microservices.io/patterns/monolithic.html [18] Eha B. (2013) An Accelerated History of Internet Speed (Infographic), dostupno
13.9.2016. na https://www.entrepreneur.com/article/228489