Asynkroninen ohjelmointi on monessa tapauksessa tehokas työkalu sovellusten suorituskyvyn parantamiseen, erityisesti silloin, kun käsitellään korkean latenssin operaatioita, kuten tietokanta- tai verkko-osoitepyyntöjä. Tällöin tärkeimmät edut tulevat esiin siinä, että pääsäie ei esty odottamaan operaatioiden valmistumista, vaan sovellus voi jatkaa muiden tehtävien käsittelyä samalla kun odottaa vastausta.
Yksi esimerkki asynkronisten toimintojen hyödyntämisestä on verkko-osoitteiden kutsuminen. Tähän voidaan käyttää esimerkiksi FastAPI:n ja asyncio-kirjaston tarjoamia mahdollisuuksia. Otetaanpa tarkasteluun esimerkki, jossa tehdään samanaikaisia pyyntöjä kahteen eri päätepisteeseen – synkroniseen ja asynkroniseen.
Ensimmäinen askel on määritellä palvelimen käynnistäminen erillisessä prosessissa käyttäen context manageria. Tämä voi näyttää seuraavalta:
Tässä käytämme contextmanager-koristetta luodaksemme yksinkertaisen kontekstin, joka käynnistää palvelimen ja sulkee sen oikein käytön jälkeen. Seuraavaksi voimme luoda asynkronisen funktion, joka suorittaa n samanaikaista pyyntöä tietylle polulle.
Tässä AsyncClient suorittaa HTTP GET -pyynnöt, ja asyncio.gather odottaa, että kaikki pyynnöt ovat valmiit ennen kuin etenee seuraavaan vaiheeseen. Tämä voi merkittävästi parantaa suorituskykyä verrattuna synkroniseen lähestymistapaan.
Kun nämä osat on rakennettu, voidaan tehdä pääfunktio, joka kutsuu näitä funktioita ja mittaa, kuinka kauan pyynnöt kestävät. Esimerkiksi:
Tässä mittaamme aikaa, joka kuluu n pyynnön tekemiseen synkronisesti ja asynkronisesti. Jos pyynnön määrä on suuri, asynkroninen malli tuo merkittävän parannuksen suoritusaikaan.
Testin tulokset voivat näyttää tältä:
Vaikka 10 pyynnön välillä ei ole merkittävää eroa, suuremmilla määrillä, kuten 100 pyynnöllä, asynkroninen lähestymistapa tuo huomattavan edun:
Tämä parannus johtuu asynkronisten funktioiden käytöstä, joka mahdollistaa sen, että pääsäie ei jää odottamaan yksittäisten pyyntöjen valmistumista.
Asynkronisten operaatioiden hyödyntäminen ei kuitenkaan ole aina oikea valinta. Asynkronia tuo monia etuja erityisesti I/O-keskeisissä operaatioissa, kuten verkkopyynnöissä tai tietokantaoperaatioissa, mutta se voi lisätä monimutkaisuutta ja virheiden hallintaa, erityisesti silloin, kun tarvitaan useita samanaikaisia tehtäviä.
Tässä on joitain parhaita käytäntöjä asynkronisen ohjelmoinnin hyödyntämisessä FastAPI:ssa:
-
I/O-keskeiset toiminnot: Asynkroninen ohjelmointi on erityisen hyödyllistä I/O-keskeisissä toiminnoissa, kuten tietokantaoperaatioissa, verkkopyynnöissä ja tiedosto-operaatioissa. Sen sijaan raskaat laskentatehtävät, jotka kuluttavat paljon prosessoritehoa, eivät hyödy asynkroniasta yhtä paljon.
-
Tietokantatransaktiot: Asynkronisten tietokantaoperaatioiden yhteydessä on tärkeää hallita transaktioita huolellisesti. Tämä varmistaa, että tiedon eheys säilyy. Yksi tapa tehdä tämä on käyttää
async with-kontekstinhallintaa. -
Virheiden käsittely: Asynkroninen ohjelmointi voi tehdä virheiden käsittelystä monimutkaisempaa, erityisesti silloin, kun useita samanaikaisia tehtäviä suoritetaan. On suositeltavaa käyttää
try-except-lohkot virheiden asianmukaiseen käsittelyyn. -
Testaus: Asynkronisten toimintojen testaaminen vaatii erityistä huomiota. Varmista, että testikehys tukee asynkronisia testejä ja käytä
asyncjaawait-avainsanoja tarpeen mukaan testikoodissasi.
Näiden periaatteiden ymmärtäminen ja soveltaminen auttaa rakentamaan sovelluksia, jotka eivät ole vain kestäviä, vaan myös suorituskykyisiä ja optimoituja kuormitustilanteissa.
Miten WebSocket-yhteyksien hallinta toteutetaan FastAPI:ssa chat-sovelluksessa?
WebSocket-yhteyksien hallinta on keskeinen osa reaaliaikaisia chat-sovelluksia, ja FastAPI tarjoaa tähän tehokkaat asynkroniset työkalut. Yhteyksien hallinta voidaan toteuttaa luomalla erillinen ConnectionManager-luokka, jonka vastuulla on ylläpitää aktiivisten WebSocket-yhteyksien listaa, vastaanottaa ja lähettää viestejä sekä käsitellä yhteyksien muodostaminen ja katkaiseminen.
ConnectionManager-luokka sisältää menetelmät, jotka ovat keskeisiä WebSocket-toiminnallisuudelle. connect-metodi lisää uuden yhteyden aktiivisten yhteyksien joukkoon ja vastaa kädenpuristuksesta (handshake). disconnect-metodi puolestaan poistaa WebSocket-yhteyden listalta, kun asiakas irrottautuu. Viestien lähetys voidaan jakaa kahteen päätyyppiin: yksittäiselle yhteydelle kohdennettu viesti (send_personal_message) ja viestin välittäminen kaikille muille aktiivisille yhteyksille paitsi lähettäjälle (broadcast). Viestien lähetys toteutetaan asynkronisesti, hyödyntäen asyncio.gather-funktiota, joka mahdollistaa rinnakkaisen suorittamisen.
WebSocket-päätepiste määritellään erillisessä moduulissa, esimerkiksi chat.py:ssä. Tämä parantaa sovelluksen rakennetta ja ylläpidettävyyttä. Päätepisteessä, joka on merkitty reitille /chatroom/{username}, kutsutaan yhteyksien hallintaluokan metodeja yhteyden muodostamiseksi, viestien vastaanottamiseksi ja niiden broadcastaamiseksi. Kun uusi käyttäjä liittyy chattiin, lähetetään ilmoitus muille osallistujille. Viestien vastaanotto tapahtuu silmukassa, joka kuuntelee jatkuvasti uusia viestejä WebSocketin kautta. Jokainen viesti lähetetään kaikille muille, ja lähettäjälle lähetetään vahvistusviesti henkilökohtaisesti.
Kun yhteys katkeaa, esimerkiksi käyttäjän poistuessa, WebSocketDisconnect-poikkeus käsitellään irrottamalla yhteys ja lähettämällä ilmoitus muille. Tämä varmistaa reaaliaikaisen tilannetietoisuuden kaikille käyttäjille.
FastAPI:n reititin liitetään pääsovellukseen include_router-metodilla, jolloin WebSocket-päätepisteet ovat käytettävissä sovelluksen kautta. Lisäksi chat-sovelluksen käyttöliittymä voidaan toteuttaa yksinkertaisena HTML-sivuna, joka renderöidään Jinja2-mallinnuksella. Sivulle lisätään JavaScript-koodi, joka avaa WebSocket-yhteyden ja mahdollistaa viestien lähettämisen ja vastaanoton selaimessa.
On tärkeää ymmärtää, että WebSocket-pohjainen chat-ratkaisu perustuu vahvasti asynkroniseen ohjelmointiin ja yhteyksien hallintaan rinnakkaisesti. Suorituskyvyn ja skaalautuvuuden kannalta on olennaista, että kaikki yhteydet ja viestinvälitykset hoidetaan ei-estävällä tavalla. Tämä mahdollistaa suuren käyttäjämäärän käsittelyn ilman, että yksittäinen hidas yhteys hidastaa koko järjestelmää.
Lisäksi on merkittävää huomioida, että WebSocket-yhteyksien hallinnassa tulee varautua myös poikkeustilanteisiin, kuten yhteyden odottamattomaan katkeamiseen tai virheellisiin viesteihin, jotta sovellus pysyy vakaana ja turvallisena. Käyttäjien tunnistaminen, esimerkiksi polun parametrina välitettävän käyttäjänimen avulla, on myös olennainen osa chatin toimivuutta ja käyttäjäkokemusta.
Miten kehittää väliohjelmistoa vastauksen muokkaamiseksi FastAPI:ssa?
Väliohjelmisto on ohjelmiston kerros, joka sijaitsee sovelluksen ja HTTP-pyynnön käsittelijän välillä. Se tarjoaa joustavan tavan käsitellä pyyntöjä ja vastauksia ennen kuin ne saavuttavat loppukäyttäjän tai ennen kuin pyyntö menee edelleen palvelimelle. Tällaisen välikerroksen hyödyntäminen voi tuoda monia etuja, kuten turvallisuuden parantamisen, suorituskyvyn optimoinnin tai erityisten otsikoiden lisäämisen vastauksiin ilman, että tarvitsee muokata alkuperäisiä käsittelijöitä.
Tässä artikkelissa tarkastelemme, kuinka luodaan väliohjelmisto FastAPI:lle, joka muokkaa HTTP-vastauksia lisäämällä niihin uusia otsikoita. Tämä voidaan toteuttaa Starlette-kirjaston avulla, joka tarjoaa kaikki tarvittavat työkalut FastAPI:n väliohjelmistojen luomiseen ja käsittelemiseen.
Ensimmäinen askel on luoda ExtraHeadersResponseMiddleware -luokka, joka ottaa vastaan listan lisättävistä otsikoista ja liittää ne jokaiseen vastaukseen ennen sen lähettämistä asiakkaalle. Tämä luokka tarvitsee muutaman keskeisen komponentin: app (FastAPI-sovelluksen instanssi), headers (otsikoiden lista) sekä __call__-metodi, joka käsittelee pyynnöt ja vastaukset.
Tässä määritellään ExtraHeadersResponseMiddleware-luokka, joka tarkistaa, onko saapuva pyyntö HTTP-tyyppinen. Mikäli pyyntö ei ole HTTP-tyyppinen, se ohjataan normaalisti seuraavaan vaiheeseen. Muussa tapauksessa väliohjelmisto lisää määritellyt otsikot send-funktion kautta vastaukseen, joka lähetetään asiakkaalle.
Kun tämä väliohjelmisto on luotu, se tulee lisätä FastAPI-sovellukseen. Tämä voidaan tehdä app.add_middleware-metodilla, jossa määritellään lisättävät otsikot. Esimerkiksi:
Kun sovellus on käynnissä, voidaan tarkistaa, että otsikot on lisätty onnistuneesti, tarkastelemalla vastauksen otsikoita selaimessa tai API-työkalussa, kuten Postmanissa tai curl-komennolla.
Toinen tärkeä näkökohta on CORS (Cross-Origin Resource Sharing) -politiikka. CORS on tärkeä turvallisuusominaisuus, joka estää kolmansien osapuolten verkkosivustoja tekemästä luvattomia pyyntöjä toisille verkkosivustoille. Tämä estää niin sanotut XSS-hyökkäykset ja muut verkkohyökkäykset, jotka voivat käyttää verkkosovelluksia väärin. CORS-politiikan hallinta voidaan toteuttaa erillisen CORSMiddleware-luokan avulla, joka antaa sovelluksen määritellä, mitkä alkuperät voivat tehdä pyyntöjä sovellukseen.
Tässä määritellään, että kaikki alkuperät, HTTP-menetelmät ja otsikot ovat sallittuja. Tämä on käytännöllistä kehitysympäristössä, mutta tuotantoympäristössä on tärkeää rajata nämä asetukset tiukemmiksi, jotta sovellus pysyy turvassa. CORS-politiikan hallinta mahdollistaa sovelluksen joustavan käytön erilaisissa verkkoympäristöissä samalla, kun se estää haitallisia pyyntöjä.
Kolmas tärkeä osa sovellusten turvallisuuden parantamista on varmistaa, että vain tietyt luotetut isäntäkoneet voivat tehdä pyyntöjä palvelimelle. Tämän voi toteuttaa TrustedHostMiddleware-luokalla, joka varmistaa, että pyyntö hyväksytään vain määritellyistä isännistä. Tämä on erityisen tärkeää estämään DNS-rebinding-hyökkäyksiä, joissa haitallinen toimija voi huijata käyttäjän selaimen tekemään pyyntöjä väärille palvelimille.
Tässä esimerkissä pyyntö hyväksytään vain, jos se tulee localhost-isännältä. Tämä auttaa estämään epäluotettavien lähteiden pääsyn sovellukseen.
Yhteenvetona voidaan todeta, että FastAPI ja Starlette tarjoavat monia tehokkaita työkaluja väliohjelmistojen kehittämiseen ja hallintaan. Kehittäjät voivat helposti lisätä erikoistoimintoja, kuten otsikoiden muokkaamista, CORS-hallintaa ja isäntärajoituksia, parantaakseen sovelluksensa turvallisuutta ja joustavuutta. On kuitenkin tärkeää, että jokaisessa käytetyssä väliohjelmistossa noudatetaan hyviä turvallisuuskäytäntöjä, erityisesti tuotantoympäristössä.

Deutsch
Francais
Nederlands
Svenska
Norsk
Dansk
Suomi
Espanol
Italiano
Portugues
Magyar
Polski
Cestina
Русский