Tag Archive for: asiantuntijalta

Asiantuntijalta: Yksinkertainen HTTP-kutsujen tallentaja

Trivoren asiantuntija Stefan Roos esittelee, miten voit toteuttaa yksinkertaisen HTTP-kutsujen tallentajan Pythonilla.


Kirjoittajasta

Stefan Roos toimii Trivoren Product Technical Leadina. Työssään hän toimii erityisesti integraatioiden ja Trivoren IAM-järjestelmän parissa sekä Trivoren johtoryhmän jäsenenä.


Oletko koskaan tarvinnut nopeasti webbi-palvelinta, joka vain vastaanottaa kutsun ja tallentaa sen levylle? Tällainen on hyvin helppo toteuttaa itse muutamalla rivillä Pythonia. Perus Pythonin lisäksi tarvitaan Flask-kirjasto, joka hoitaa suurimman osan asioista taustalla.

Voit asentaa Flaskin yksinkertaisesti käyttämällä Pythonin omaa paketinhallintajärjestelmää seuraavanlaisella komennolla.

Näin voidaan luoda skripti, joka toteuttaa kutsuja vastaanottavan http-palvelimen. Luodaan uusi tieodosto esimerkiksi listener.py-nimellä. Tallennetaan sen sisälle seuraavan listauksen näköinen koodi.

Tällaisten yksinkertaisten työkalujen rakentaminen monesti auttaa huomattavasti erilaisten asioiden testaamista.

Mitä koodissa tapahtuu?

Ohjelman rakenne on melko yksinkertainen. Ensimmäiset kaksi riviä määrittelevät käyttöön tässä ohjelmassa tarvittavat kirjastot. Näitä kirjastoja ovat flask, jonka sisältä erityisesti tarvitaan Flask sekä request. Lisäksi tarvitaan aikaleiman käyttämiseen tiedostonimenä datetime-kirjastosta datetime. Koska molemmista kirjastoista tarvitaan vai nämä tietyt osat, käytetään muotoa from … import …

Seuraavat kolme riviä alustavat sovelluksen globaalit muuttujat. Ensimmäisenä näistä on app, joka käytännössä on siis Flask-sovelluksen instanssi. Tämä Flask-sovellus on käytännössä tämän koko sovelluksen ydin, se hoitaa mm. http-palvelimen hallinnoinnin.

Seuraavana määritellään käytännössä tiedostonimen formaattia, jota käytetään, kun järjestelmään tuleva http-kutsu tallennetaan levylle. Muuttuja dateformat määrittelee aikaleiman muodon, joka lisätään tiedostonimeen. filenameFormat taas määrittelee muilta osin tiedostonimen.

Seuraavana koodissa määritellään python-funktio, jolle sisään tuleva kutsu ohjataan. Ennen varsinaista funktion määrittelyä on ns. decorator. Tätä voisi suomeksi kutsua koristeeksi tai kuorrutukseksi, mutta täysin vakiintunutta suomennosta tälle termille ei taida olla. Decoratorin tarkoitus on kuitenkin tässä tapauksessa tuoda python-funktio Flaskin tietoon muuttamalla se käytännössä Flask-sovelluksen näkymäfunktioksi (engl. view function). Näin saadaan HTTP-kutsu Flaskista ohjattua tietyssä polussa ja tietyllä HTTP-metodilla tähän funktioon. Decoratoriin on määritelty poluksi nyt ”/”, eli sovelluksen juuri, ja vastaanotettavaksi HTTP-metodiksi POST.

Funktion varsinainen toiminnallisuus alkaa siitä, että ensin muodostetaan tiedostonimi käyttäen sen hetkistä aikaleimaa. Aikaleima saadaan datetime-kirjaston datetime-objektilla now()-funktiolla. Aikaleima muunnetaan sitten haluttuun muotoon kutsumalla sen strftime-funktiota siten, että annetaan sille sopiva aikamuoto. Sovelluksen alussa määrittelimme globaaliksi muuttujaksi halutun aikamuodon (dateformat-muuttuja).

Kun tiedostonimi on muodostettu, yritetään avata tiedosto kirjoitusmoodissa. Koska tässä sovelluksessa ei ole määritelty hakemistoa lainkaan, vaan pelkästään tiedostonimi, yritetään avata tiedostoa sovelluksen työhakemistossa. Mikäli avaaminen onnistuu, kirjoitetaan tiedoston sisälle HTTP-kutsussa vastaanotettu data. HTTP-kutsun data saadaan request-objektista funktiolla get_data().

Mikäli edellä mainitut askeleet toteutuivat onnistueesti, tulostetaan vielä konsoliin print() -kutsulla tietoa tallennetusta tiedostosta.

Lopuksi palautetaan HTTP-kutsun vastaukseksi myös tieto tallennetusta tiedostosta. Mikäli virheitä ei tapahdu, kutsuja saa statuskoodilla 200 OK -vastauksen, jonka sisältönä kerrotaan tallennetun tiedoston nimi.

Lopuksi vielä ohjataan python-sovellus automaattisesti käynnistämään flask-sovellus, kun se ajetaan skriptinä.

Miten sovellus suoritetaan?

Ohjelman voi suorittaa python-skriptinä seuraavasti.

Tämän jälkeen sovelluksen pitäisi olla käynnissä ja tulostaa aluksi jotain seuraavan näköistä:

Kun sovellus on käynnissä, voi siihen lähettää kutsuja. Sovellus ottaa sellaisenaan vain POST-tyyppiset kutsut vastaan juuripolkuun, eli ”/”-polkuun. Oletuksena sovellus kuuntelee porttia 5000/TCP, mutta tämä on toki vaihdettavissa helposti.

Sovelluksen testaaminen käytännössä

Kun olet käynnistänyt sovelluksen, voit kokeilla sen toimintaa kutsumalla sitä komentorivillä curl -komentoa käyttäen:

Sovellus vastaanottaa kutsun ja tulostaa konsoliin ilmoituksen siitä:

Palvelimen tallentama tiedosto pitäisi löytyä samasta hakemistosta, jossa sovellus on käynnistetty:

Tiedoston sisältä pitäisi myös löytyä kutsussa lähetetty data:


Lähteitä ja linkkejä

Flask https://flask.palletsprojects.com/

Python https://www.python.org/

curl https://curl.se/

Asiantuntijalta: Katsaus Apache Kafkaan

Trivoren asiantuntija Stefan Roos kirjoittaa Apache Kafkasta, joka on kiinnostava tietovirtojen kuljetukseen suunniteltu alusta. Alunperin LinkedInin käyttöön suunniteltua alustaa on sittemmin hyödynnetty laajemminkin ohjelmistokehityksessä, mukaan lukien erinäisissä Trivoren projekteissa.


Kirjoittajasta

Stefan Roos toimii Trivoren Product Technical Leadina. Työssään hän toimii erityisesti integraatioiden ja Trivoren IAM-järjestelmän parissa sekä Trivoren johtoryhmän jäsenenä.


Mikä Apache Kafka käytännössä on? 

Apache Kafka on alunperin vuonna 2011 tietovirtojen kuljetukseen suunniteltu alusta. Se suunniteltiin LinkedInin käyttöön sen sisäisten viestien välittämiseksi. (Li 2020; Koutanov 2020.) Tapahtumien kuljettaminen tietovirroissa (event streaming) voidaan kuvata vastaavaksi, kuin mitä ihmisen hermostossa tapahtuu. Kafkaa voisikin siis sanoa digitaaliseksi versioksi keskushermostosta (Apache Kafka, 2022).

Kafkaa voidaan käyttää muun muassa publish-subscribe-mallin viestinvälitykseen, lokien aggregointiin, lokien edelleenlähetykseen (log shipping), asynkronisiin yhteyksiin (SEDA), monimutkaisten tapahtumien prosessointiin (CEP) sekä tapahtumapohjaiseen komento-kyselyvastuun segrekointiin (Event-sourced CQRS) (Koutanov 2020). Kafkaa voidaan käyttää viestikanavana, sovellusten integrointiin, datastorena, tietovirtojen käsittelyjärjestelmiin sekä skaalautuvien ja vikasietoisten mikropalveluiden rakentamiseen (Shapira 2017).

Koutanovin (2020) mukaan Kafka-järjestelmä tarvitsee useita komponentteja toimiakseen oikein.

Avainkomponentit ovat:

  • Brokerit – vastuussa varsinaisista IO-operaatiosta sekä datan persistoinnista
  • Zookeeperit – vastuussa kafka-klusterin tilasta ja sen kontrolloinnista.
  • Producer – asiakasjärjestelmiä/-sovelluksia, jotka tuottavat dataa jonoihin.
  • Consumerit – asiakasjärjestelmiä/-sovelluksia, jotka noutavat dataa jonoista. (Koutanov 2020.)

Messetti (2022) kirjoittaa kuitenkin, että näistä komponenteista Zookeeper voidaan jatkossa jättää pois, sillä Kafkan sisälle toteutettu KRaft-protokolla hoitaa siihen liittyvät tehtävät jatkossa. Uusimmissa versioissa Kafkasta ei siis ole enää tarvetta käyttää ulkopuolista palvelua klusterin metatietojen välitykseen. Tämä muutos käytännössä yksinkertaistaa Kafka-klusterin rakennetta sekä parantaa sen skaalautuvuutta.

Avainkonseptit Kafkan käyttämisessä ovat topicit (aihe) sekä partitiot. Topic tarkoittaa kafkassa käytännössä yhtä jonoa, johon voidaan dataa viedä tai noutaa. Jono voidaan sisäisesti jakaa useiksi partitioiksi. Jokainen partitio on käytännössä järjestetty sarja tietueita (record). Voimme kutsua näitä myös viesteiksi.

Tietueilla on sijainti (offset) ja sillä voi olla myös avain sekä arvo. Koska partitiot ovat täysin järjestettyjä (ordered), on varmuus siitä, että consumer saa viestit/tietueet siinä järjestyksessä, kun producer on ne lähettänyt. Kafkassa on myös tae siitä, että kaikki lukevat viestit aina samassa järjestyksessä. Tämä on hyvin tärkeää suurelle osalle sovelluksista. Huomioitava on kuitenkin, että jos on kyse tilanteesta, jossa on useita producereita, voivat ne lähettää samanaikaisesti viestejä samalle partitiolle, eikä näin ollen ole taetta siitä, että producereiden kesken viestit olisivat oikeassa järjestyksessä. (Koutanov 2020.)

Topic kattaa siis joko yhden tai useamman partition: se on siis looginen kokoelma partitioita. Jokainen partitio voi olla vain tasan yhdessä topicissa. Topicit ovat hyvin tärkeä osa Kafkan rakennetta ja toiminnallisuutta. Ne mahdollistavat muun muassa sovellusten kuormantasauksen sekä rinnakkaisuuden. (Koutanov 2020.)

Avainkonseptit Kafkan käyttämisessä ovat topicit (aihe) sekä partitiot. Topic tarkoittaa kafkassa käytännössä yhtä jonoa, johon voidaan dataa viedä tai noutaa. Jono voidaan sisäisesti jakaa useiksi partitioiksi. Jokainen partitio on käytännössä järjestetty sarja tietueita (record). Voimme kutsua näitä myös viesteiksi.

Producerit määrittelevät, mitä tietueita voidaan samanaikaisesti käsitellä, ja mitä on käsiteltävä lineaarisesti. Kun tuottaja luo tietueita, se voi määritellä avaimen tietueelle, jonka perusteella tietueet voidaan sijoittaa siten samaan partiotioon. Tämä takaa sen, että tietueet ovat järjestyksessä. Kafka vastaanottaessaan tietueen laskee tiivisteen (hash) avaimelle ja sijoittaa sitten tietueen oikeaan partitioon sen mukaisesti. (Koutanov 2020.)

Consumerit saavat dataa tilaamalla tietyn topicin ja liittymällä kuluttajaryhmään (consumer group). Kun consumer tilaa tällaisen topicin, saa se aluksi kaikki topicissa olevat partitiot käyttöönsä, mikäli muita consumereita ei ole. Tämän jälkeen seuraava liittyvä consumer saa puolet partitioista, eli näin saadaan jaettua kuormitusta järjestelmässä. Vastaavasti consumerin poistuessa jaetaan sillä olleet partitiot muille, vielä mukana oleville consumereille samassa ryhmässä. Kafka takaa, että kuluttajaryhmän sisällä ei koskaan anneta samaa partitiota useammalle kuin yhdelle consumerille. Useat kuluttajaryhmät voivat toki käyttää samaa topicia. (Koutanov 2020.)

Huomion arvioista Kafkassa on se, että tietueen lukeminen ei poista sitä järjestelmästä. Consumerit eivät voi siis poistaa dataa lainkaan jonoista/topiceista tai partitioista. Topicia voi muokata ainoastaan producer itse. Consumereilla on tieto lukemisen sijainnista (offset), jonka perusteella ne tietävät, mistä kohtaa luetaan seuraava tietue.

Kafka oletuksena tekee automaattista offsetin tallennusta 5 sekunnin välein. Tämä on kuitenkin useille sovelluksille huono vaihtoehto, koska datan käsittely voi olla vielä kesken. Jos siis operaatio epäonnistuu täysin ja consumer kaatuu, pitäisi sen seuraavalla kerralla yrittää käsitellä samaa tietuetta, mutta offset kertoo sen olevan jo käsitelty. On siis usein hyvä vaihtoehto muuttaa asetus enable.auto.commit asentoon false. (Koutanov 2020.)

Miten Kafka eroaa perinteisistä viestijonojärjestelmistä?

Kafka tarjoaa käytännössä yleisemmän mallin viestien välitykseen kuin monet muut järjestelmät. Kafkassa voidaan yhtä ja samaa topicia käyttää usean kaltaiseen tarkoitukseen useille erilaisille consumereille. Toinen mielenkiintoinen ero on se, että kafkasta viestit eivät oletuksena poistu, kun ne luetaan. Monissa muissa viestijärjestelmissä viesti poistuu, kun joku kuittaa sen käsitellyksi. (Koutanov 2020.)

Kafka on optimoitu suurelle määrälle viestien käsittelyä. Se kykenee kevyesti käsittelemään miljoonia viestejä sekunneissa. Yksi syy tähän on juuri se, että Kafka ei poista käsiteltyjä viestejä. Tämä ominaisuus poistaa levyoperaation, joka hidastaisi järjestelmää. Kafka myös käsittelee tietueita erissä, jolloin käsittely on tehokkaampaa. Tärkeä huomio on myös se, että Kafka ei synkronoi levylle asti tietueita ennen kuin se kuittaa producerille vastaanottamisesta, vaan se vie tietueen vain puskurille asti. (Koutanov 2020.)

Miinuspuolina Kafkan käyttöön voidaan nähdä esimerkiksi mahdollinen latenssi viestien välityksessä. Kafka on optimoitu suuren viestimäärän kuljettamiseksi, mutta ei varsinaisesti pienelle latenssille producerin ja consumerin välillä. Kafkan optimointiin on myös hyvin suuri määrä erilaisia parametreja, mikä voi tuntua etenkin vasta-alkajista hurjalta. Kafkan oletusasetukset voivat olla myös turvattomat joillekin sovelluksille. (Koutanov 2020.)

Turvallisuus ja autentikointimahdollisuudet

Entä turvallisuus ja autentikointimahdollisuudet? Kafka tukee TLS:n versiota 1.2, joten liikenne eri tahojen välillä saadaan turvattua. Tämän lisäksi on mahdollista konfiguroida SASL-pohjainen autentikointi (Kerberos,OAuth, SCRAM, yms). Autentikoinnin lisäksi Kafka tukee ACL:iä tarkemman autorisoinnin määrittelemiseksi. (Koutanov 2020.)

Carder (2022) esittää viisi erinomaista käytännön toimea, joilla saadaan varmistettua hyvä turvallisuus Kafkan kanssa.

  1. Autentikointi on syytä aktivoida Kafkassa.
  2. Kaikki yhteydet tulee salata. Yksi helppo ratkaisu tämän toteuttamiseksi ovat LetsEncrypt-sertifikaatit.
  3. Päivitetään järjestelmä säännöllisesti.
  4. Aktivoidaan ja konfiguroidaan ACL:t, eli pääsynhallintalistat
  5. Ei turhaan pelätä hankalampiakin tietoturvaa parantavia asioita, kuten SELinux. SELinux liian usein kytketään sallivaan tilaan tai jopa kokonaan pois päältä. Sen käyttäminen kuitenkin tuo lisäturvaa.

Käyttäjät eri rooleissa

Shapiran (2017) mukaan Kafkan käyttöön tutustumisessa on järkevä huomioida rooli, jossa olet Kafkan kanssa tekemisissä. Eri rooleissa olevat henkilöt operoivat eri tavoin Kafkan kanssa. Sovelluskehittäjät tarvitset jonkinlaisen kirjaston tyypillisesti Kafka topicien käyttämiseksi sovelluksessaan. On suositeltava luoda jokin pieni harjoitusprojekti, jossa kokeilee ensin sopivaa Kafka-kirjastoa. Soton (2022) mukaan Quarkuksessa on erinomainen tuki Kafkan käyttämiseksi. Quarkus on koko pinon kattava (full-stack) Kubernetes-natiivi Java-sovelluskehityksen sovelluskehys (framework). Soto (2022) kuvaa kirjoituksessaan kattavasti, miten Kafkaa käyttävän Quarkus-sovelluksen voi luoda.

Sysadminit taas joutuvat operoimaan varsinaisen Kafka-instanssin kanssa, eli huolehtimaan siitä, että se on ajossa, tarkistamaan sen lokeja sekä valvomaan sitä esimerkiksi JMX:n kautta. Tietovarastojen kanssa työskentelevät ihmiset taas ovat kiinnostuneita siitä, että tieto kulkee luotettavasti Kafkan kautta esimerkiksi MySQL-teitokannasta johonkin toiseen tietovarastoon. (Shapira 2017.) 


Lähteet

Apache Kafka 2022. Dokumentaatio. Saatavilla https://kafka.apache.org/documentation/ Viitattu 14.11.2022.

Carder J. 2022. OpenLogic. https://www.openlogic.com/blog/apache-kafka-best-practicessecurity Viitattu 21.11.2022. 

Koutanov E. 2020. Medium. Saatavilla https://medium.com/swlh/apache-kafka-in-a-nutshell-5782b01d9ffb Viitattu 14.11.2022.

Li S. 2020. He Left His High-Paying Job At LinkedIn And Then Built A $4.5 Billion Business In A Niche You’ve Never Heard Of. Forbes. https://www.forbes.com/sites/stevenli1/2020/05/11/confluent-jay-kreps-kafka-4-billion-2020/ Viitattu 14.11.2022.

Messetti A. 2022. Apache Kafka 3.3 Replaces ZooKeeper with the New KRaft Consensus Protocol. https://www.infoq.com/news/2022/10/apache-kafka-kraft/ Viitattu 15.11.2022

Shapira G. 2017. Apache Kafka: Getting Started. Saatavilla https://www.confluent.io/blog/apache-kafka-getting-started/ Viitattu 14.11.2022.

Soto A. 2022. Getting Started to Quarkus Reactive Messaging with Apache Kafka. https://www.infoq.com/articles/data-with-quarkus-kafka/ Viitattu 14.11.2022