Dubinska analiza Tornada, Python web okvira i asinkrone mrežne biblioteke. Naučite kako izraditi skalabilne aplikacije visokih performansi uz detaljna objašnjenja, primjere i najbolje prakse.
Tornado dokumentacija: Sveobuhvatni vodič za programere širom svijeta
Tornado je Python web okvir i asinkrona mrežna biblioteka, izvorno razvijena u FriendFeedu. Posebno je prikladan za long-polling, WebSockets i druge aplikacije koje zahtijevaju dugotrajnu vezu sa svakim korisnikom. Njegov neblokirajući mrežni I/O čini ga izuzetno skalabilnim i moćnim izborom za izradu web aplikacija visokih performansi. Ovaj sveobuhvatni vodič provest će vas kroz temeljne koncepte Tornada i pružiti praktične primjere za početak.
Što je Tornado?
U svojoj suštini, Tornado je web okvir i asinkrona mrežna biblioteka. Za razliku od tradicionalnih sinkronih web okvira, Tornado koristi jednorednu arhitekturu temeljenu na petlji događaja (event-loop). To znači da može obraditi mnogo istovremenih veza bez potrebe za jednom dretvom (thread) po vezi, što ga čini učinkovitijim i skalabilnijim.
Ključne značajke Tornada:
- Asinkrono umrežavanje: Srž Tornada izgrađena je oko asinkronog I/O-a, što mu omogućuje učinkovitu obradu tisuća istovremenih veza.
- Web okvir: Uključuje značajke poput rukovatelja zahtjevima (request handlers), usmjeravanja (routing), predložaka (templating) i autentifikacije, što ga čini potpunim web okvirom.
- Podrška za WebSocket: Tornado pruža izvrsnu podršku za WebSockets, omogućujući komunikaciju u stvarnom vremenu između poslužitelja i klijenata.
- Lagan i brz: Dizajniran za performanse, Tornado je lagan i učinkovit, minimizirajući opterećenje i maksimizirajući propusnost.
- Jednostavan za korištenje: Unatoč naprednim značajkama, Tornado je relativno jednostavan za učenje i korištenje, s jasnim i dobro dokumentiranim API-jem.
Postavljanje vašeg Tornado okruženja
Prije nego što uronite u razvoj s Tornadom, trebate postaviti svoje okruženje. Evo vodiča korak po korak:
- Instalirajte Python: Provjerite imate li instaliran Python 3.6 ili noviji. Možete ga preuzeti sa službene Python web stranice (python.org).
- Kreirajte virtualno okruženje (preporučeno): Koristite
venv
ilivirtualenv
za stvaranje izoliranog okruženja za vaš projekt:python3 -m venv myenv source myenv/bin/activate # Na Linuxu/macOS-u myenv\Scripts\activate # Na Windowsima
- Instalirajte Tornado: Instalirajte Tornado pomoću pipa:
pip install tornado
Vaša prva Tornado aplikacija
Kreirajmo jednostavnu "Hello, World!" aplikaciju s Tornadom. Stvorite datoteku naziva app.py
i dodajte sljedeći kod:
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()
Sada pokrenite aplikaciju iz svog terminala:
python app.py
Otvorite svoj web preglednik i idite na http://localhost:8888
. Trebali biste vidjeti poruku "Hello, World!".
Objašnjenje:
tornado.ioloop
: Glavna petlja događaja koja obrađuje asinkrone operacije.tornado.web
: Pruža komponente web okvira, kao što su rukovatelji zahtjevima i usmjeravanje.MainHandler
: Rukovatelj zahtjevima koji definira kako obraditi dolazne HTTP zahtjeve. Metodaget()
poziva se za GET zahtjeve.tornado.web.Application
: Stvara Tornado aplikaciju, mapirajući URL uzorke na rukovatelje zahtjevima.app.listen(8888)
: Pokreće poslužitelj koji sluša dolazne veze na portu 8888.tornado.ioloop.IOLoop.current().start()
: Pokreće petlju događaja, koja obrađuje dolazne zahtjeve i upravlja asinkronim operacijama.
Rukovatelji zahtjevima i usmjeravanje
Rukovatelji zahtjevima temelj su Tornado web aplikacija. Oni definiraju kako se obrađuju dolazni HTTP zahtjevi na temelju URL-a. Usmjeravanje (routing) mapira URL-ove na određene rukovatelje zahtjevima.
Definiranje rukovatelja zahtjevima:
Da biste stvorili rukovatelja zahtjevima, naslijedite klasu tornado.web.RequestHandler
i implementirajte odgovarajuće HTTP metode (get
, post
, put
, delete
, itd.).
class MyHandler(tornado.web.RequestHandler):
def get(self):
self.write("Ovo je GET zahtjev.")
def post(self):
data = self.request.body.decode('utf-8')
self.write(f"Primljeni POST podaci: {data}")
Usmjeravanje:
Usmjeravanje se konfigurira prilikom stvaranja tornado.web.Application
. Pružate popis n-torki, gdje svaka n-torka sadrži URL uzorak i odgovarajućeg rukovatelja zahtjevima.
app = tornado.web.Application([
(r"/", MainHandler),
(r"/myhandler", MyHandler),
])
URL uzorci:
URL uzorci su regularni izrazi. Možete koristiti grupe regularnih izraza za hvatanje dijelova URL-a i njihovo prosljeđivanje kao argumenata metodama rukovatelja zahtjevima.
class UserHandler(tornado.web.RequestHandler):
def get(self, user_id):
self.write(f"Korisnički ID: {user_id}")
app = tornado.web.Application([
(r"/user/([0-9]+)", UserHandler),
])
U ovom primjeru, /user/([0-9]+)
odgovara URL-ovima poput /user/123
. Dio ([0-9]+)
hvata jednu ili više znamenki i prosljeđuje ih kao argument user_id
metodi get
klase UserHandler
.
Predlošci (Templating)
Tornado uključuje jednostavan i učinkovit sustav predložaka. Predlošci se koriste za dinamičko generiranje HTML-a, odvajajući logiku prezentacije od logike aplikacije.
Stvaranje predložaka:
Predlošci se obično pohranjuju u zasebnim datotekama (npr. index.html
). Evo jednostavnog primjera:
<!DOCTYPE html>
<html>
<head>
<title>Moja web stranica</title>
</head>
<body>
<h1>Dobrodošli, {{ name }}!</h1>
<p>Danas je {{ today }}.</p>
</body>
</html>
{{ name }}
i {{ today }}
su rezervirana mjesta koja će biti zamijenjena stvarnim vrijednostima prilikom iscrtavanja predloška.
Iscrtavanje predložaka:
Za iscrtavanje predloška koristite metodu render()
u svom rukovatelju zahtjevima:
class TemplateHandler(tornado.web.RequestHandler):
def get(self):
name = "John Doe"
today = "2023-10-27"
self.render("index.html", name=name, today=today)
Provjerite je li postavka template_path
ispravno konfigurirana u postavkama vaše aplikacije. Prema zadanim postavkama, Tornado traži predloške u direktoriju nazvanom templates
u istom direktoriju kao i vaša aplikacijska datoteka.
app = tornado.web.Application([
(r"/template", TemplateHandler),
], template_path="templates")
Sintaksa predložaka:
Tornado predlošci podržavaju različite značajke, uključujući:
- Varijable:
{{ variable }}
- Kontrola toka:
{% if condition %} ... {% else %} ... {% end %}
,{% for item in items %} ... {% end %}
- Funkcije:
{{ function(argument) }}
- Uključivanja (Includes):
{% include "another_template.html" %}
- Izbjegavanje (Escaping): Tornado automatski izbjegava HTML entitete kako bi spriječio napade cross-site scripting (XSS). Možete onemogućiti izbjegavanje koristeći
{% raw variable %}
.
Asinkrone operacije
Snaga Tornada leži u njegovim asinkronim sposobnostima. Asinkrone operacije omogućuju vašoj aplikaciji izvođenje neblokirajućeg I/O-a, poboljšavajući performanse i skalabilnost. To je posebno korisno za zadatke koji uključuju čekanje na vanjske resurse, kao što su upiti u bazu podataka ili mrežni zahtjevi.
@tornado.gen.coroutine
:
Dekorator @tornado.gen.coroutine
omogućuje vam pisanje asinkronog koda pomoću ključne riječi yield
. To čini da asinkroni kod izgleda i ponaša se više kao sinkroni kod, poboljšavajući čitljivost i održivost.
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'))
U ovom primjeru, http_client.fetch()
je asinkrona operacija koja vraća Future
. Ključna riječ yield
obustavlja izvršenje korutine dok se Future
ne razriješi. Jednom kada je Future
razriješen, korutina se nastavlja, a tijelo odgovora se ispisuje klijentu.
tornado.concurrent.Future
:
Future
predstavlja rezultat asinkrone operacije koji možda još nije dostupan. Možete koristiti Future
objekte za lančano povezivanje asinkronih operacija i rukovanje pogreškama.
tornado.ioloop.IOLoop
:
IOLoop
je srce Tornadovog asinkronog mehanizma. Nadgleda deskriptore datoteka i sockete za događaje te ih prosljeđuje odgovarajućim rukovateljima. Obično ne morate izravno komunicirati s IOLoop
, ali važno je razumjeti njegovu ulogu u rukovanju asinkronim operacijama.
WebSockets
Tornado pruža izvrsnu podršku za WebSockets, omogućujući komunikaciju u stvarnom vremenu između poslužitelja i klijenata. WebSockets su idealni za aplikacije koje zahtijevaju dvosmjernu komunikaciju s malom latencijom, kao što su chat aplikacije, online igre i nadzorne ploče u stvarnom vremenu.
Stvaranje WebSocket rukovatelja:
Da biste stvorili WebSocket rukovatelja, naslijedite klasu tornado.websocket.WebSocketHandler
i implementirajte sljedeće metode:
open()
: Poziva se kada se uspostavi nova WebSocket veza.on_message(message)
: Poziva se kada se od klijenta primi poruka.on_close()
: Poziva se kada se WebSocket veza zatvori.
import tornado.websocket
class WebSocketHandler(tornado.websocket.WebSocketHandler):
def open(self):
print("WebSocket otvoren")
def on_message(self, message):
self.write_message(f"Poslali ste: {message}")
def on_close(self):
print("WebSocket zatvoren")
def check_origin(self, origin):
return True # Omogući WebSocket veze s različitih izvora
Integriranje WebSocketsa u vašu aplikaciju:
Dodajte WebSocket rukovatelja u konfiguraciju usmjeravanja vaše aplikacije:
app = tornado.web.Application([
(r"/ws", WebSocketHandler),
])
Implementacija na strani klijenta:
Na strani klijenta možete koristiti JavaScript za uspostavljanje WebSocket veze i slanje/primanje poruka:
const websocket = new WebSocket("ws://localhost:8888/ws");
websocket.onopen = () => {
console.log("WebSocket veza uspostavljena");
websocket.send("Pozdrav s klijenta!");
};
websocket.onmessage = (event) => {
console.log("Primljena poruka:", event.data);
};
websocket.onclose = () => {
console.log("WebSocket veza zatvorena");
};
Autentifikacija i sigurnost
Sigurnost je ključan aspekt razvoja web aplikacija. Tornado pruža nekoliko značajki koje vam pomažu osigurati vaše aplikacije, uključujući autentifikaciju, autorizaciju i zaštitu od uobičajenih web ranjivosti.
Autentifikacija:
Autentifikacija je proces provjere identiteta korisnika. Tornado pruža ugrađenu podršku za različite sheme autentifikacije, uključujući:
- Autentifikacija temeljena na kolačićima (cookies): Pohranite korisničke vjerodajnice u kolačiće.
- Autentifikacija trećih strana (OAuth): Integrirajte se s popularnim društvenim mrežama poput Googlea, Facebooka i Twittera.
- API ključevi: Koristite API ključeve za autentifikaciju API zahtjeva.
Autorizacija:
Autorizacija je proces određivanja ima li korisnik dopuštenje za pristup određenom resursu. Možete implementirati logiku autorizacije u svojim rukovateljima zahtjevima kako biste ograničili pristup na temelju korisničkih uloga ili dopuštenja.
Najbolje sigurnosne prakse:
- Zaštita od Cross-Site Scripting (XSS): Tornado automatski izbjegava HTML entitete kako bi spriječio XSS napade. Uvijek koristite metodu
render()
za iscrtavanje predložaka i izbjegavajte izravno generiranje HTML-a u svojim rukovateljima zahtjevima. - Zaštita od Cross-Site Request Forgery (CSRF): Omogućite CSRF zaštitu u postavkama svoje aplikacije kako biste spriječili CSRF napade.
- HTTPS: Uvijek koristite HTTPS za enkripciju komunikacije između poslužitelja i klijenata.
- Validacija unosa: Validirajte sav korisnički unos kako biste spriječili napade ubacivanjem (injection attacks) i druge ranjivosti.
- Redovite sigurnosne revizije: Provodite redovite sigurnosne revizije kako biste identificirali i riješili potencijalne ranjivosti.
Implementacija (Deployment)
Implementacija Tornado aplikacije uključuje nekoliko koraka, uključujući konfiguriranje web poslužitelja, postavljanje upravitelja procesa i optimizaciju performansi.
Web poslužitelj:
Možete implementirati Tornado iza web poslužitelja poput Nginxa ili Apachea. Web poslužitelj djeluje kao obrnuti proxy (reverse proxy), prosljeđujući dolazne zahtjeve Tornado aplikaciji.
Upravitelj procesa:
Upravitelj procesa poput Supervisora ili systemd može se koristiti za upravljanje Tornado procesom, osiguravajući da se automatski ponovno pokrene ako se sruši.
Optimizacija performansi:
- Koristite petlju događaja spremnu za produkciju: Koristite petlju događaja spremnu za produkciju poput
uvloop
za poboljšane performanse. - Omogućite gzip kompresiju: Omogućite gzip kompresiju kako biste smanjili veličinu HTTP odgovora.
- Predmemorirajte statičke datoteke: Predmemorirajte statičke datoteke kako biste smanjili opterećenje na poslužitelju.
- Nadzirite performanse: Nadzirite performanse svoje aplikacije pomoću alata kao što su New Relic ili Prometheus.
Internacionalizacija (i18n) i lokalizacija (l10n)
Prilikom izrade aplikacija za globalnu publiku, važno je uzeti u obzir internacionalizaciju (i18n) i lokalizaciju (l10n). i18n je proces dizajniranja aplikacije tako da se može prilagoditi različitim jezicima i regijama bez inženjerskih promjena. l10n je proces prilagodbe internacionalizirane aplikacije za određeni jezik ili regiju dodavanjem lokalno specifičnih komponenti i prevođenjem teksta.
Tornado i i18n/l10n
Sam Tornado nema ugrađene i18n/l10n biblioteke. Međutim, možete jednostavno integrirati standardne Python biblioteke poput `gettext` ili sofisticiranije okvire poput Babela za rukovanje i18n/l10n unutar vaše Tornado aplikacije.
Primjer korištenja `gettext`:
1. **Postavite svoje lokalne postavke (locales):** Stvorite direktorije za svaki jezik koji želite podržati, koji sadrže kataloge poruka (obično `.mo` datoteke).
locales/
en/LC_MESSAGES/messages.mo
fr/LC_MESSAGES/messages.mo
de/LC_MESSAGES/messages.mo
2. **Izdvojite prevodive nizove:** Koristite alat poput `xgettext` za izdvajanje prevodivih nizova iz vašeg Python koda u `.po` datoteku (Portable Object). Ova datoteka će sadržavati originalne nizove i rezervirana mjesta za prijevode.
xgettext -d messages -o locales/messages.po your_tornado_app.py
3. **Prevedite nizove:** Prevedite nizove u `.po` datotekama za svaki jezik.
4. **Kompajlirajte prijevode:** Kompajlirajte `.po` datoteke u `.mo` datoteke (Machine Object) koje `gettext` koristi pri izvođenju.
msgfmt locales/fr/LC_MESSAGES/messages.po -o locales/fr/LC_MESSAGES/messages.mo
5. **Integrirajte u svoju Tornado aplikaciju:**
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:
# Rješavanje slučajeva gdje lokalne postavke nisu podržane od strane sustava
print(f"Lokalne postavke {self.get_user_locale().code} nisu podržane")
translation = gettext.translation('messages', 'locales', languages=[self.get_user_locale().code])
translation.install()
self._ = translation.gettext
def get_current_user_locale(self):
# Logika za određivanje lokalnih postavki korisnika (npr. iz Accept-Language zaglavlja, korisničkih postavki, itd.)
# Ovo je pojednostavljen primjer - trebat će vam robusnije rješenje
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. **Izmijenite svoje predloške:** Koristite funkciju `_()` (povezanu s `gettext.gettext`) za označavanje nizova za prevođenje u vašim predlošcima.
<h1>{{ _("Dobrodošli na našu web stranicu!") }}</h1>
<p>{{ _("Ovo je prevedeni odlomak.") }}</p>
Važna razmatranja za globalnu publiku:
- **Kodiranje znakova:** Uvijek koristite UTF-8 kodiranje kako biste podržali širok raspon znakova.
- **Formatiranje datuma i vremena:** Koristite formatiranje datuma i vremena specifično za lokalne postavke. Pythonove funkcije `strftime` i `strptime` mogu se koristiti s postavkama lokaliteta.
- **Formatiranje brojeva:** Koristite formatiranje brojeva specifično za lokalne postavke (npr. decimalni separatori, separatori tisućica). Modul `locale` pruža funkcije za to.
- **Formatiranje valuta:** Koristite formatiranje valuta specifično za lokalne postavke. Razmislite o korištenju biblioteke poput `Babel` za naprednije rukovanje valutama.
- **Jezici koji se pišu zdesna nalijevo (RTL):** Podržite RTL jezike poput arapskog i hebrejskog. To može uključivati zrcaljenje izgleda vaše web stranice.
- **Kvaliteta prijevoda:** Koristite profesionalne prevoditelje kako biste osigurali točne i kulturno prikladne prijevode. Strojno prevođenje može biti dobar početak, ali često zahtijeva ljudsku provjeru.
- **Detekcija lokalnih postavki korisnika:** Implementirajte robusnu detekciju lokalnih postavki na temelju korisničkih preferencija, postavki preglednika ili IP adrese. Omogućite korisnicima da ručno odaberu željeni jezik.
- **Testiranje:** Temeljito testirajte svoju aplikaciju s različitim lokalnim postavkama kako biste osigurali da se sve prikazuje ispravno.
Napredne teme
Prilagođene stranice s greškama:
Možete prilagoditi stranice s greškama koje Tornado prikazuje kada dođe do greške. To vam omogućuje da pružite korisnički prihvatljivije iskustvo i uključite informacije za otklanjanje grešaka.
Prilagođene postavke:
Možete definirati prilagođene postavke u konfiguraciji svoje aplikacije i pristupati im u svojim rukovateljima zahtjevima. To je korisno za pohranu parametara specifičnih za aplikaciju, kao što su nizovi za povezivanje s bazom podataka ili API ključevi.
Testiranje:
Temeljito testirajte svoje Tornado aplikacije kako biste osigurali da funkcioniraju ispravno i sigurno. Koristite jedinične testove, integracijske testove i end-to-end testove kako biste pokrili sve aspekte vaše aplikacije.
Zaključak
Tornado je moćan i svestran web okvir koji je vrlo prikladan za izradu skalabilnih web aplikacija visokih performansi. Njegova asinkrona arhitektura, podrška za WebSocket i jednostavan API čine ga popularnim izborom za programere širom svijeta. Slijedeći smjernice i primjere u ovom sveobuhvatnom vodiču, možete početi graditi vlastite Tornado aplikacije i iskoristiti njegove brojne značajke.
Ne zaboravite konzultirati službenu Tornado dokumentaciju za najnovije informacije i najbolje prakse. Sretno kodiranje!