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:
- Asynkroninen verkkotyöskentely: Tornadon ydin on rakennettu asynkronisen I/O:n ympärille, mikä mahdollistaa tuhansien samanaikaisten yhteyksien tehokkaan käsittelyn.
- Web-kehys: Se sisältää ominaisuuksia, kuten pyyntöjen käsittelijät (request handlers), reitityksen, mallipohjat (templating) ja todennuksen, tehden siitä täydellisen web-kehyksen.
- WebSocket-tuki: Tornado tarjoaa erinomaisen tuen WebSocketeille, mikä mahdollistaa reaaliaikaisen viestinnän palvelimen ja asiakkaiden välillä.
- Kevyt ja nopea: Suorituskykyä varten suunniteltu Tornado on kevyt ja tehokas, minimoiden yleiskustannukset ja maksimoiden suorituskyvyn.
- Helppokäyttöinen: Edistyneistä ominaisuuksistaan huolimatta Tornado on suhteellisen helppo oppia ja käyttää, ja sillä on selkeä ja hyvin dokumentoitu API.
Tornado-kehitysympäristön pystyttäminen
Ennen kuin sukellat Tornadon kehitykseen, sinun on pystytettävä ympäristösi. Tässä on vaiheittainen opas:
- Asenna Python: Varmista, että sinulla on asennettuna Python 3.6 tai uudempi. Voit ladata sen virallisilta Python-verkkosivuilta (python.org).
- Luo virtuaaliympäristö (suositeltavaa): Käytä
venv
- taivirtualenv
-työkalua luodaksesi eristetyn ympäristön projektillesi:python3 -m venv myenv source myenv/bin/activate # Linuxilla/macOS:llä myenv\Scripts\activate # Windowsilla
- 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:
tornado.ioloop
: Ydintapahtumasilmukka, joka käsittelee asynkronisia operaatioita.tornado.web
: Tarjoaa web-kehyksen komponentit, kuten pyyntöjen käsittelijät ja reitityksen.MainHandler
: Pyyntöjen käsittelijä, joka määrittelee, miten saapuvat HTTP-pyynnöt käsitellään.get()
-metodia kutsutaan GET-pyynnöille.tornado.web.Application
: Luo Tornado-sovelluksen, yhdistäen URL-mallit pyyntöjen käsittelijöihin.app.listen(8888)
: Käynnistää palvelimen, joka kuuntelee saapuvia yhteyksiä portissa 8888.tornado.ioloop.IOLoop.current().start()
: Käynnistää tapahtumasilmukan, joka prosessoi saapuvat pyynnöt ja käsittelee asynkroniset operaatiot.
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:
- Muuttujat:
{{ variable }}
- Kontrollirakenteet:
{% if condition %} ... {% else %} ... {% end %}
,{% for item in items %} ... {% end %}
- Funktiot:
{{ function(argument) }}
- Sisällytykset (Includes):
{% include "another_template.html" %}
- Pakoistus (Escaping): Tornado pakoistaa automaattisesti HTML-entiteetit estääkseen sivustojen väliset komentosarjahyökkäykset (XSS). Voit poistaa pakoistuksen käytöstä komennolla
{% raw variable %}
.
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:
open()
: Kutsutaan, kun uusi WebSocket-yhteys muodostetaan.on_message(message)
: Kutsutaan, kun asiakkaalta vastaanotetaan viesti.on_close()
: Kutsutaan, kun WebSocket-yhteys suljetaan.
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:
- Evästepohjainen todennus: Tallenna käyttäjätiedot evästeisiin.
- Kolmannen osapuolen todennus (OAuth): Integroi suosittuihin sosiaalisen median alustoihin, kuten Google, Facebook ja Twitter.
- API-avaimet: Käytä API-avaimia API-pyyntöjen todentamiseen.
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:
- Sivustojen välisten komentosarjahyökkäysten (XSS) suojaus: Tornado pakoistaa automaattisesti HTML-entiteetit estääkseen XSS-hyökkäykset. Käytä aina
render()
-metodia mallipohjien renderöintiin ja vältä HTML:n luomista suoraan pyyntöjesi käsittelijöissä. - Sivustojen välisten pyyntöjen väärentämisen (CSRF) suojaus: Ota CSRF-suojaus käyttöön sovelluksesi asetuksissa estääksesi CSRF-hyökkäykset.
- HTTPS: Käytä aina HTTPS:ää palvelimen ja asiakkaiden välisen viestinnän salaamiseen.
- Syötteen validointi: Validoi kaikki käyttäjän syötteet estääksesi injektiohyökkäykset ja muut haavoittuvuudet.
- Säännölliset turvallisuustarkastukset: Tee säännöllisiä turvallisuustarkastuksia mahdollisten haavoittuvuuksien tunnistamiseksi ja korjaamiseksi.
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:
- Käytä tuotantovalmista tapahtumasilmukkaa: Käytä tuotantovalmista tapahtumasilmukkaa, kuten
uvloop
, parantaaksesi suorituskykyä. - Ota gzip-pakkaus käyttöön: Ota gzip-pakkaus käyttöön pienentääksesi HTTP-vastausten kokoa.
- Välimuistita staattiset tiedostot: Välimuistita staattiset tiedostot vähentääksesi palvelimen kuormitusta.
- Seuraa suorituskykyä: Seuraa sovelluksesi suorituskykyä työkaluilla, kuten New Relic tai Prometheus.
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:
- **Merkistökoodaus:** Käytä aina UTF-8-koodausta tukeaksesi laajaa valikoimaa merkkejä.
- **Päivämäärän ja ajan muotoilu:** Käytä lokaalikohtaista päivämäärän ja ajan muotoilua. Pythonin `strftime`- ja `strptime`-funktioita voidaan käyttää lokaaliasetusten kanssa.
- **Numeroiden muotoilu:** Käytä lokaalikohtaista numeroiden muotoilua (esim. desimaalierottimet, tuhaterottimet). `locale`-moduuli tarjoaa tähän toimintoja.
- **Valuutan muotoilu:** Käytä lokaalikohtaista valuutan muotoilua. Harkitse kirjaston, kuten `Babel`, käyttöä edistyneempään valuuttojen käsittelyyn.
- **Oikealta vasemmalle (RTL) -kielet:** Tue RTL-kieliä, kuten arabiaa ja hepreaa. Tämä saattaa vaatia verkkosivustosi asettelun peilaamista.
- **Käännöksen laatu:** Käytä ammattikääntäjiä varmistaaksesi tarkat ja kulttuurisesti sopivat käännökset. Koneellinen kääntäminen voi olla hyvä lähtökohta, mutta se vaatii usein ihmisen tarkistuksen.
- **Käyttäjän lokaalin tunnistus:** Toteuta vankka lokaalin tunnistus perustuen käyttäjän mieltymyksiin, selaimen asetuksiin tai IP-osoitteeseen. Tarjoa käyttäjille tapa valita haluamansa kieli manuaalisesti.
- **Testaus:** Testaa sovelluksesi perusteellisesti eri lokaaleilla varmistaaksesi, että kaikki näkyy oikein.
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!