Mikropalveluarkkitehtuurissa sovellus rakennetaan pienistä itsenäisistä palveluista yhden suuren sijaan. Millä periaatteilla sovellus kannattaa pilkkoa erillisiksi palveluiksi ja miksi? Tässä domain driven design astuu esiin. Artikkelissamme ohjelmistoarkkitehti Marko Lauronen tarjoaa johdannon aiheeseen.
Mitä mikropalvelut ovat? Milloin mikropalveluarkkitehtuuria kannattaa käyttää?
Mikropalveluarkkitehtuuri on arkkitehtuurityyli, jossa sovellus rakennetaan pienemmistä palveluista yhden suuren monoliittisen sovelluksen sijaan.
Yksittäinen mikropalvelu:
- Omaa yhden vastuualueen
- Omistaa datansa ja tarjoaa rajapinnan sen käsittelyyn
- On löyhästi kytketty muihin palveluihin
- On itsenäisesti kehitettävissä, testattavissa ja julkaistavissa
Mikropalveluiden vahvuuksiksi monoliittiin verrattuna mainitaan usein mm. pienempien palveluiden helpompi ymmärrettävyys, sovelluksen helpompi evoluutio, skaalattavuus ja mahdollisuus valita soveltuvimmat teknologiat kunkin palvelun toteuttamiseen.
Mikropalvelutyyli on validi lähestymistapa suurissa projekteissa ja organisaatioissa, jotka luonnollisesti koostuvat – tai pystytään koostamaan – pienistä tiimeistä. Olennaisesti mikropalveluiden suurin hyöty on enemmän työnjaollinen kuin tekninen. Joustavuudella on hintansa – mikropalveluiden hajautetusta luonteesta johtuen tekninen monimutkaisuus kasvaa nimittäin merkittävästi.
Yksi tärkeimmistä asioista mikropalveluarkkitehtuurissa on palveludekompositio, eli sovelluksen pilkkominen kooltaan ja rajaukseltaan sopiviin palveluihin. Puuttuvilla tai väärillä periaatteilla tehtynä se johtaa huonoihin laatuattribuutteihin, kuten vaikeaan ylläpidettävyyteen, suorituskykyongelmiin ja työnjaollisten etujen katoamiseen hallitsemattomien riippuvuuksien vuoksi. Pahin mahdollinen virhe on pilkkoa palvelut teknisin perustein, esimerkiksi kerroksiin. Tulos on niin sanottu hajautettu monoliitti, joka vesittää kaikki mikropalveluiden tarjoamat hyödyt.
Millä periaatteilla pilkkominen kannattaa sitten tehdä ja miten tunnistaa potentiaaliset mikropalvelut?
Vastaus löytyy syvällisestä domain-ymmärryksestä, johon Domain Driven Design tarjoaa erinomaisia työkaluja.
Domain Driven Design
Domain Driven Design (DDD) on Eric Evansin vuonna 2003 julkaisemassa kirjassaan esittelemä ohjelmistokehityksen filosofia, jossa painotetaan ohjelmiston rakentamista toimialansa mallina (domain model). Ydinajatus on, että koodina ilmaistun mallin tulee heijastaa mahdollisimman pitkälle toimialan luonnollista kieltä ja rakennetta.
Domain driven design tarjoaa sekä strategisen että taktisen tason suunnittelukaavoja.
Strategiset suunnittelukaavat ovat:
- Ubiquitous language
- Bounded Context ja Context map
Ubiquitous language – projektin kieli
Ubiquitous language on kaikkien projektin sidosryhmien kanssa yhteistyössä sovittu kieli (sisältää toimialan termistön, käsitteet ja ilmaisut), jota käytetään kaikessa projektiin liittyvässä kommunikaatiossa ja toimialamallin rakentamisessa kooditasolla.
Kielen löytämiseen voidaan käyttää esimerkiksi event storming -tekniikkaa, jossa toimiala-asiantuntijoiden kanssa yhteisissä sessioissa muodostetaan kokonaiskuva toimialan tapahtumista ja kielestä.
Käsitteiden määrittelyyn kuuluu olennaisena osana konteksti eli asiayhteys, jossa käsitteellä on yksikäsitteinen merkitys – sama termi voi usein tarkoittaa hieman eri asioita eri näkökulmista katsottuna. Esimerkiksi ”tuote” sisältää ostoskorin kontekstissa vain tuotteen kuvan, hinnan ja tuotteen nimen, kun taas varaston tai tilausten käsittelyn konteksteissa käsite voi olla huomattavasti laajempi.
Tällaisia yksikäsitteisen kielen sisältäviä rakenteita kutsutaan nimellä Bounded Context.
Bounded Context ja Context Map
Bounded Context on kielellinen rajaus, jonka sisällä mallinnusta tehdään. Jokaisella kontekstilla on oma, yksikäsitteiset termit sisältävä kielensä. Näiden toimialan kielestä rakentuvien kontekstien perusajatus on jo hyvin lähellä mikropalvelua: sovelluksen toimialamallia ei Domain Driven Design -ajattelussa pyritä rakentamaan yhtenä suurena kokonaisuutena, vaan joukkona pienempiä, itsenäisesti mallinnettavia palasia.
Apuna kontekstien rajaamisessa voidaan käyttää niin sanottua context map:ia, visuaalista tapaa havainnollistaa kontekstien rajoja ja integraatiosuhteita. Esimerkiksi edellä mainitun tuote-käsitteen erilaisista merkityksistä tunnistetut varasto- ja tilausten käsittely -asiayhteydet olisivat hyviä konteksteja, joihin muita samassa yhteydessä esiintyviä käsitteitä voi sijoitella.
Kontekstien omaa kieltä suojellaan tarkasti: niiden välillä tapahtuva kommunikaatio tapahtuu yleensä ns. Anti Corruption Layerin kautta, joka suorittaa muunnoksen kontekstien käsitteiden välillä. REST-rajapinta (ns. Open Host Service) voi myös toimia luonnollisena muunnoskerroksena.
Bounded contextien mallinnus – taktiset suunnittelukaavat
Kontekstien käsitteet luokitellaan ja kuvataan koodiksi käyttäen jotakin seuraavista taktisista suunnittelukaavoista:
- Value object – käsite, jolla ei ole identiteettiä (esimerkiksi rahasumma)
- Entity – käsite, jolla on elinkaari ja identiteetti (esimerkiksi tuote)
- Aggregate
- Domain Service – (tilatonta) logiikkaa, joka ei sovi luonnollisesti edellä mainittuihin objekteihin, esimerkiksi työnkulkujen koordinointi
Aggregaatti on erityinen entiteetti, joka omistaa kokoelman muita entiteettejä/value objecteja – niitä voi käsitellä ainoastaan aggregaatin rajapinnan kautta. Kokoelmaa sitoo yhteen ns. invariantit eli tietyt ehdot, joiden tulee aina olla voimassa. Esimerkkinä ”tilaus” joka sisältää kokoelman tilattuja tuotteita, joista vain yksi voi olla erikoistarjoustuote.
Aggregaatti on myös persistenssin yksikkö: se haetaan ja tallennetaan aina kokonaisena, yhdessä transaktiossa. Usean aggregaatin päivittäminen samassa transaktiossa on kielletty.
Tilamuutoksistaan aggregaatti generoi tapahtumia, ns. domain eventtejä, jotka kuvaavat mitä aggregaatin tilassa tapahtui muille kiinnostuneille tahoille, kuten toisten kontekstien aggregaateille, jotka reagoivat tapahtumaan omissa transaktioissaan.
Mikropalveluiden määritelmään peilattuna yksittäinen aggregaatti muistuttaa itsenäistä mikropalvelua: ne omistavat oman datansa, tarjoavat rajapinnan datan käsittelyyn ja ovat tapahtumapohjaisina itsenäisesti kehitettävissä ja testattavissa.
Sovelluksen pilkkominen
Domain Driven Designin ajatuksia soveltamalla syntyy siis kahdentyyppisiä selkeitä kandidaatteja itsenäisiksi mikropalveluiksi – bounded contextit ja niiden sisältä löytyvät aggregaatit.
Tyypillisesti yksi bounded context muodostaa yhden mikropalvelun. Kontekstin koosta ja ei-toiminnallisista vaatimuksista johtuen (esim. skaalautuvuus, työnjakorakenne) konteksti voi olla syytä hajottaa mikropalveluiksi aggregaattitasolle.
Suositeltavaa on aloittaa sovelluksen rakentaminen monoliittisessa arkkitehtuurissa. On tyypillistä, että kontekstien rajat voivat mallinnuksen edetessä aluksi elää, jolloin muutokset ovat helpompia monoliitin sisällä. Kun kontekstin rajat stabiloituvat, se voidaan irrottaa omaksi mikropalvelukseen.
Yhteenveto – Domain Driven Design ja mikropalvelut
Tärkein tekijä mikropalveluarkkitehtuurin onnistuneessa soveltamisessa on palveludekompositio. Domain Driven Design tarjoaa periaatteet ja työkalut toimialan mallintamiseksi palasiin, joiden joukosta mikropalvelukandidaatit voidaan tunnistaa. Palaset perustuvat toimialan kieleen ja siinä esiintyviin luonnollisiin asiayhteyksiin, jolloin syntyvien palveluiden riippuvuussuhteet ovat linjassa toimialan rakenteen kanssa.
- Selvitä toimialan ”ubiquitous language” ja tunnista siinä esiintyvät asiayhteydet
- Rajaa bounded contextit löytyneiden asiayhteyksien perusteella
- Mallinna kontekstit taktisia suunnittelukaavoja käyttäen ja tunnista aggregaatit
- Valitse sopivimmat kandidaatit omiksi mikropalveluikseen
Jos kaipaat apua esimerkiksi yrityksesi ohjelmistokehityshankkeisiin tai sinulle jäi jotain kysyttävää artikkelista, voit olla suoraan yhteydessä ohjelmistokehitystiimin vetäjäämme Veikkoon (+358 40 713 1576 / veikko.savijoki@solidabis.com).
Saman katon alta löydät ohjelmistokehityspalveluiden lisäksi myös prosessikehitys- ja desiginpalvelut.
Saattaisit olla kiinnostunut myös näistä
- Näin saat IT-hankkeesi pysymään paremmin budjetissa ja aikataulussa
- Aikaa ja olosuhteita kestäviä teollisuuskoneiden ohjelmistoja – Case Sandvik
- Juniorista senioriksi – Fullstack-kehittäjä Henri Lehtinen