Suomi

Syväluotaava katsaus Tornadoon, Pythonin web-kehykseen ja asynkroniseen verkkokirjastoon. Opi rakentamaan skaalautuvia, suorituskykyisiä sovelluksia yksityiskohtaisten selitysten, esimerkkien ja parhaiden käytäntöjen avulla.

Tornadon dokumentaatio: Kattava opas kehittäjille maailmanlaajuisesti

Tornado on Python-web-kehys ja asynkroninen verkkokirjasto, joka on alun perin kehitetty FriendFeedissä. Se soveltuu erityisen hyvin pitkiin pollaus-kyselyihin (long-polling), WebSocket-yhteyksiin ja muihin sovelluksiin, jotka vaativat pitkäikäisen yhteyden jokaiseen käyttäjään. Sen ei-blokkaava verkko-I/O tekee siitä erittäin skaalautuvan ja tehokkaan valinnan suorituskykyisten verkkosovellusten rakentamiseen. Tämä kattava opas johdattaa sinut Tornadon ydin-konsepteihin ja tarjoaa käytännön esimerkkejä, joiden avulla pääset alkuun.

Mikä on Tornado?

Ytimeltään Tornado on web-kehys ja asynkroninen verkkokirjasto. Toisin kuin perinteiset synkroniset web-kehykset, Tornado käyttää yksisäikeistä, tapahtumasilmukkaan perustuvaa arkkitehtuuria. Tämä tarkoittaa, että se voi käsitellä monia samanaikaisia yhteyksiä vaatimatta säiettä yhteyttä kohden, mikä tekee siitä tehokkaamman ja skaalautuvamman.

Tornadon tärkeimmät ominaisuudet:

Tornado-kehitysympäristön pystyttäminen

Ennen kuin sukellat Tornadon kehitykseen, sinun on pystytettävä ympäristösi. Tässä on vaiheittainen opas:

  1. Asenna Python: Varmista, että sinulla on asennettuna Python 3.6 tai uudempi. Voit ladata sen virallisilta Python-verkkosivuilta (python.org).
  2. Luo virtuaaliympäristö (suositeltavaa): Käytä venv- tai virtualenv-työkalua luodaksesi eristetyn ympäristön projektillesi:
    python3 -m venv myenv
    source myenv/bin/activate  # Linuxilla/macOS:llä
    myenv\Scripts\activate  # Windowsilla
  3. Asenna Tornado: Asenna Tornado pip-työkalulla:
    pip install tornado

Ensimmäinen Tornado-sovelluksesi

Luodaan yksinkertainen "Hello, World!" -sovellus Tornadolla. Luo tiedosto nimeltä app.py ja lisää seuraava koodi:

import tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
 def get(self):
  self.write("Hello, World!")

def make_app():
 return tornado.web.Application([
  (r"/", MainHandler),
 ])

if __name__ == "__main__":
 app = make_app()
 app.listen(8888)
 tornado.ioloop.IOLoop.current().start()

Suorita sovellus nyt päätteestäsi:

python app.py

Avaa verkkoselaimesi ja siirry osoitteeseen http://localhost:8888. Sinun pitäisi nähdä "Hello, World!" -viesti.

Selitys:

Pyyntöjen käsittelijät ja reititys

Pyyntöjen käsittelijät ovat Tornado-verkkosovellusten perusta. Ne määrittelevät, miten saapuvat HTTP-pyynnöt käsitellään URL-osoitteen perusteella. Reititys yhdistää URL-osoitteet tiettyihin pyyntöjen käsittelijöihin.

Pyyntöjen käsittelijöiden määrittely:

Luodaksesi pyyntöjen käsittelijän, peri luokka tornado.web.RequestHandler ja toteuta asianmukaiset HTTP-metodit (get, post, put, delete, jne.).

class MyHandler(tornado.web.RequestHandler):
 def get(self):
  self.write("Tämä on GET-pyyntö.")

 def post(self):
  data = self.request.body.decode('utf-8')
  self.write(f"Vastaanotettiin POST-dataa: {data}")

Reititys:

Reititys määritetään luotaessa tornado.web.Application-oliota. Annat listan tupleja, joissa kukin tuple sisältää URL-mallin ja vastaavan pyyntöjen käsittelijän.

app = tornado.web.Application([
 (r"/", MainHandler),
 (r"/myhandler", MyHandler),
])

URL-mallit:

URL-mallit ovat säännöllisiä lausekkeita. Voit käyttää säännöllisten lausekkeiden ryhmiä kaapataksesi osia URL-osoitteesta ja välittää ne argumentteina pyyntöjen käsittelijän metodeille.

class UserHandler(tornado.web.RequestHandler):
 def get(self, user_id):
  self.write(f"Käyttäjätunnus: {user_id}")

app = tornado.web.Application([
 (r"/user/([0-9]+)", UserHandler),
])

Tässä esimerkissä /user/([0-9]+) vastaa URL-osoitteita kuten /user/123. Osa ([0-9]+) kaappaa yhden tai useamman numeron ja välittää ne user_id-argumenttina UserHandler-luokan get-metodille.

Mallipohjat

Tornado sisältää yksinkertaisen ja tehokkaan mallipohjajärjestelmän (templating engine). Mallipohjia käytetään dynaamisen HTML:n luomiseen, erottaen esityslogiikan sovelluslogiikasta.

Mallipohjien luominen:

Mallipohjat tallennetaan tyypillisesti erillisiin tiedostoihin (esim. index.html). Tässä on yksinkertainen esimerkki:

<!DOCTYPE html>
<html>
<head>
 <title>Verkkosivustoni</title>
</head>
<body>
 <h1>Tervetuloa, {{ name }}!</h1>
 <p>Tänään on {{ today }}.</p>
</body>
</html>

{{ name }} ja {{ today }} ovat paikkamerkkejä, jotka korvataan todellisilla arvoilla, kun mallipohja renderöidään.

Mallipohjien renderöinti:

Renderöidäksesi mallipohjan, käytä render()-metodia pyyntöjesi käsittelijässä:

class TemplateHandler(tornado.web.RequestHandler):
 def get(self):
  name = "Matti Meikäläinen"
  today = "2023-10-27"
  self.render("index.html", name=name, today=today)

Varmista, että template_path-asetus on määritetty oikein sovelluksesi asetuksissa. Oletuksena Tornado etsii mallipohjia hakemistosta nimeltä templates, joka sijaitsee samassa hakemistossa kuin sovellustiedostosi.

app = tornado.web.Application([
 (r"/template", TemplateHandler),
], template_path="templates")

Mallipohjien syntaksi:

Tornadon mallipohjat tukevat useita ominaisuuksia, kuten:

Asynkroniset operaatiot

Tornadon vahvuus piilee sen asynkronisissa ominaisuuksissa. Asynkroniset operaatiot antavat sovelluksesi suorittaa ei-blokkaavaa I/O:ta, mikä parantaa suorituskykyä ja skaalautuvuutta. Tämä on erityisen hyödyllistä tehtävissä, jotka vaativat ulkoisten resurssien odottamista, kuten tietokantakyselyissä tai verkkopyynnöissä.

@tornado.gen.coroutine:

Dekoraattori @tornado.gen.coroutine mahdollistaa asynkronisen koodin kirjoittamisen yield-avainsanalla. Tämä saa asynkronisen koodin näyttämään ja käyttäytymään enemmän kuin synkroninen koodi, mikä parantaa luettavuutta ja ylläpidettävyyttä.

import tornado.gen
import tornado.httpclient

class AsyncHandler(tornado.web.RequestHandler):
 @tornado.gen.coroutine
 def get(self):
  http_client = tornado.httpclient.AsyncHTTPClient()
  response = yield http_client.fetch("http://example.com")
  self.write(response.body.decode('utf-8'))

Tässä esimerkissä http_client.fetch() on asynkroninen operaatio, joka palauttaa Future-olion. Avainsana yield keskeyttää korutiinin suorituksen, kunnes Future on ratkaistu. Kun Future on ratkaistu, korutiini jatkaa toimintaansa ja vastausrunko kirjoitetaan asiakkaalle.

tornado.concurrent.Future:

Future edustaa asynkronisen operaation tulosta, joka ei välttämättä ole vielä saatavilla. Voit käyttää Future-olioita ketjuttaaksesi asynkronisia operaatioita yhteen ja käsitelläksesi virheitä.

tornado.ioloop.IOLoop:

IOLoop on Tornadon asynkronisen moottorin sydän. Se valvoo tiedostokahvoja ja socketeja tapahtumien varalta ja välittää ne asianmukaisille käsittelijöille. Yleensä sinun ei tarvitse olla suoraan vuorovaikutuksessa IOLoop-olion kanssa, mutta on tärkeää ymmärtää sen rooli asynkronisten operaatioiden käsittelyssä.

WebSocketit

Tornado tarjoaa erinomaisen tuen WebSocketeille, mikä mahdollistaa reaaliaikaisen viestinnän palvelimen ja asiakkaiden välillä. WebSocketit ovat ihanteellisia sovelluksiin, jotka vaativat kaksisuuntaista, matalan viiveen viestintää, kuten chat-sovellukset, online-pelit ja reaaliaikaiset kojelaudat.

WebSocket-käsittelijän luominen:

Luodaksesi WebSocket-käsittelijän, peri luokka tornado.websocket.WebSocketHandler ja toteuta seuraavat metodit:

import tornado.websocket

class WebSocketHandler(tornado.websocket.WebSocketHandler):
 def open(self):
  print("WebSocket avattu")

 def on_message(self, message):
  self.write_message(f"Lähetit: {message}")

 def on_close(self):
  print("WebSocket suljettu")

 def check_origin(self, origin):
  return True # Salli alkuperärajat ylittävät WebSocket-yhteydet

WebSocketien integrointi sovellukseesi:

Lisää WebSocket-käsittelijä sovelluksesi reititysmäärityksiin:

app = tornado.web.Application([
 (r"/ws", WebSocketHandler),
])

Asiakaspuolen toteutus:

Asiakaspuolella voit käyttää JavaScriptiä WebSocket-yhteyden muodostamiseen ja viestien lähettämiseen/vastaanottamiseen:

const websocket = new WebSocket("ws://localhost:8888/ws");

websocket.onopen = () => {
 console.log("WebSocket-yhteys muodostettu");
 websocket.send("Hei asiakaspuolelta!");
};

websocket.onmessage = (event) => {
 console.log("Vastaanotettu viesti:", event.data);
};

websocket.onclose = () => {
 console.log("WebSocket-yhteys suljettu");
};

Todennus ja turvallisuus

Turvallisuus on kriittinen osa verkkosovellusten kehitystä. Tornado tarjoaa useita ominaisuuksia, jotka auttavat sinua turvaamaan sovelluksesi, mukaan lukien todennus, valtuutus ja suojaus yleisiä verkkohaavoittuvuuksia vastaan.

Todennus:

Todennus on prosessi, jolla varmistetaan käyttäjän henkilöllisyys. Tornado tarjoaa sisäänrakennetun tuen erilaisille todennusmenetelmille, mukaan lukien:

Valtuutus:

Valtuutus on prosessi, jolla määritetään, onko käyttäjällä lupa käyttää tiettyä resurssia. Voit toteuttaa valtuutuslogiikan pyyntöjesi käsittelijöissä rajoittaaksesi pääsyä käyttäjäroolien tai käyttöoikeuksien perusteella.

Turvallisuuden parhaat käytännöt:

Käyttöönotto

Tornado-sovelluksen käyttöönotto sisältää useita vaiheita, kuten web-palvelimen määrittämisen, prosessinhallinnan pystyttämisen ja suorituskyvyn optimoinnin.

Web-palvelin:

Voit ottaa Tornadon käyttöön web-palvelimen, kuten Nginxin tai Apachen, takana. Web-palvelin toimii käänteisenä välityspalvelimena (reverse proxy), joka välittää saapuvat pyynnöt Tornado-sovellukselle.

Prosessinhallinta:

Prosessinhallintatyökalua, kuten Supervisoria tai systemd:tä, voidaan käyttää Tornado-prosessin hallintaan, varmistaen, että se käynnistetään automaattisesti uudelleen, jos se kaatuu.

Suorituskyvyn optimointi:

Kansainvälistäminen (i18n) ja lokalisointi (l10n)

Kun rakennetaan sovelluksia globaalille yleisölle, on tärkeää ottaa huomioon kansainvälistäminen (i18n) ja lokalisointi (l10n). i18n on prosessi, jossa sovellus suunnitellaan siten, että se voidaan mukauttaa eri kieliin ja alueille ilman teknisiä muutoksia. l10n on prosessi, jossa kansainvälistetty sovellus mukautetaan tietylle kielelle tai alueelle lisäämällä paikkakuntakohtaisia komponentteja ja kääntämällä tekstiä.

Tornado ja i18n/l10n

Tornadossa itsessään ei ole sisäänrakennettuja i18n/l10n-kirjastoja. Voit kuitenkin helposti integroida standardeja Python-kirjastoja, kuten `gettext`, tai kehittyneempiä kehyksiä, kuten Babel, hoitamaan i18n/l10n-toiminnallisuuden Tornado-sovelluksessasi.

Esimerkki `gettext`-kirjaston käytöstä:

1. **Aseta lokaalit:** Luo hakemistot jokaiselle kielelle, jota haluat tukea. Nämä hakemistot sisältävät viestiluetteloita (yleensä `.mo`-tiedostoja).

locales/
 en/LC_MESSAGES/messages.mo
 fr/LC_MESSAGES/messages.mo
 de/LC_MESSAGES/messages.mo

2. **Pura käännettävät merkkijonot:** Käytä työkalua, kuten `xgettext`, purkaaksesi käännettävät merkkijonot Python-koodistasi `.po`-tiedostoon (Portable Object). Tämä tiedosto sisältää alkuperäiset merkkijonot ja paikkamerkit käännöksille.

xgettext -d messages -o locales/messages.po your_tornado_app.py

3. **Käännä merkkijonot:** Käännä `.po`-tiedostojen merkkijonot kullekin kielelle.

4. **Käännä käännökset:** Käännä `.po`-tiedostot `.mo`-tiedostoiksi (Machine Object), joita `gettext` käyttää ajon aikana.

msgfmt locales/fr/LC_MESSAGES/messages.po -o locales/fr/LC_MESSAGES/messages.mo

5. **Integroi Tornado-sovellukseesi:**

import gettext
import locale
import os
import tornado.web

class BaseHandler(tornado.web.RequestHandler):
 def initialize(self):
  try:
  locale.setlocale(locale.LC_ALL, self.get_user_locale().code)
  except locale.Error:
  # Käsittele tapaukset, joissa järjestelmä ei tue lokaalia
  print(f"Lokaalia {self.get_user_locale().code} ei tueta")

  translation = gettext.translation('messages', 'locales', languages=[self.get_user_locale().code])
  translation.install()
  self._ = translation.gettext

 def get_current_user_locale(self):
  # Logiikka käyttäjän lokaalin määrittämiseksi (esim. Accept-Language-otsakkeesta, käyttäjäasetuksista jne.)
  # Tämä on yksinkertaistettu esimerkki - tarvitset vankemman ratkaisun
  accept_language = self.request.headers.get('Accept-Language', 'en')
  return tornado.locale.get(accept_language.split(',')[0].split(';')[0])

class MainHandler(BaseHandler):
 def get(self):
  self.render("index.html", _=self._)

settings = {
 "template_path": os.path.join(os.path.dirname(__file__), "templates"),
}

app = tornado.web.Application([
 (r"/", MainHandler),
], **settings)

6. **Muokkaa mallipohjiasi:** Käytä `_()`-funktiota (joka on sidottu `gettext.gettext`-funktioon) merkitsemään käännettävät merkkijonot mallipohjissasi.

<h1>{{ _("Welcome to our website!") }}</h1>
<p>{{ _("This is a translated paragraph.") }}</p>

Tärkeitä huomioita globaaleille yleisöille:

Edistyneemmät aiheet

Mukautetut virhesivut:

Voit mukauttaa virhesivuja, jotka Tornado näyttää virheen sattuessa. Tämä mahdollistaa käyttäjäystävällisemmän kokemuksen tarjoamisen ja virheenkorjaustietojen sisällyttämisen.

Mukautetut asetukset:

Voit määrittää mukautettuja asetuksia sovelluksesi konfiguraatiossa ja käyttää niitä pyyntöjesi käsittelijöissä. Tämä on hyödyllistä sovelluskohtaisten parametrien, kuten tietokantayhteysmerkkijonojen tai API-avainten, tallentamiseen.

Testaus:

Testaa Tornado-sovelluksesi perusteellisesti varmistaaksesi, että ne toimivat oikein ja turvallisesti. Käytä yksikkötestejä, integraatiotestejä ja päästä-päähän-testejä kattamaan kaikki sovelluksesi osa-alueet.

Yhteenveto

Tornado on tehokas ja monipuolinen web-kehys, joka soveltuu hyvin skaalautuvien, suorituskykyisten verkkosovellusten rakentamiseen. Sen asynkroninen arkkitehtuuri, WebSocket-tuki ja helppokäyttöinen API tekevät siitä suositun valinnan kehittäjille maailmanlaajuisesti. Noudattamalla tämän kattavan oppaan ohjeita ja esimerkkejä voit aloittaa omien Tornado-sovellusten rakentamisen ja hyödyntää sen monia ominaisuuksia.

Muista tutustua viralliseen Tornadon dokumentaatioon saadaksesi ajantasaisimmat tiedot ja parhaat käytännöt. Hyvää koodausta!