A web ma már egy nagy hely. Egyszerre több ezer ügyfelet kell támogatnunk, és itt jön a Tornado. A Tornado egy Python webes keretrendszer és aszinkron hálózati könyvtár, amelyet eredetileg a FriendFreednél fejlesztettek ki.
A Tornado nem blokkoló hálózati-io-t használ. Ennek köszönhetően több ezer aktív szerverkapcsolatot képes kezelni. Megmentője azoknak az alkalmazásoknak, ahol hosszú pollingot és nagyszámú aktív kapcsolatot kell fenntartani.
A Tornado nem olyan, mint a legtöbb Python keretrendszer. Nem a WSGI-n alapul, bár a WSGI néhány funkcióját támogatja a `tornado.wsgi` modul segítségével. Eseményhurok kialakítást használ, ami gyorsabbá teszi a Tornado kérések végrehajtását.
Mi az a szinkron program?
Egy függvény blokkol, elvégzi a számítását, és visszatér, ha végzett . Egy függvény több okból is blokkolhat: hálózati I/O, lemez I/O, mutexek stb.
Az alkalmazás teljesítménye attól függ, hogy az alkalmazás milyen hatékonyan használja a CPU-ciklusokat, ezért a blokkoló utasításokat/hívásokat komolyan kell venni. Gondoljunk csak a bcrypt-hez hasonló jelszóhasító függvényekre, amelyek eleve több száz ezredmásodpercnyi CPU-időt használnak, sokkal többet, mint egy tipikus hálózati vagy lemezelérés. Mivel a CPU nincs üresjáratban, nincs szükség aszinkron függvényekre.
Egy függvény lehet blokkoló az egyikben, és nem blokkoló a másikban. A Tornado kontextusában általában a hálózati I/O és a lemez miatti blokkolást tekintjük, bár mindenféle blokkolást minimalizálni kell.
Mi az aszinkron program?
1) Egyszálas architektúra:
Azt jelenti, hogy nem tud számításközpontú feladatokat párhuzamosan elvégezni.
2) I/O párhuzamosság:
Átadhatja az IO feladatokat az operációs rendszernek és folytathatja a következő feladattal a párhuzamosság elérése érdekében.
3) epoll/ kqueue:
Aláhúzza a rendszerrel kapcsolatos konstrukciót, amely lehetővé teszi, hogy egy alkalmazás eseményeket kapjon egy fájlleírón vagy I/O specifikus feladatokon.
4) Eseményhurok:
Az epoll vagy kqueue segítségével ellenőrzi, hogy történt-e bármilyen esemény, és végrehajtja a callback-et, amely ezekre a hálózati eseményekre vár.
Aszinkron vs szinkron webes keretrendszer:
A szinkron modell esetében minden egyes kérés vagy feladat átkerül egy szálra vagy útvonalra, és amint befejeződik, az eredményt átadja a hívónak. Itt a dolgok kezelése egyszerű, de az új szálak létrehozása túl nagy overheadet jelent.
Az aszinkron keretrendszerben, mint például a Node.js, egyszálas modell van, így nagyon kevés a overhead, de komplexitással jár.
Tegyük fel, hogy több ezer kérés érkezik, és egy szerver eseményhurkot és callbacket használ. Most, amíg a kérés feldolgozásra kerül, hatékonyan kell tárolnia és kezelnie a kérés állapotát, hogy a callback eredményét leképezze az aktuális ügyfélhez.
Node.js vs Tornado
A legtöbb ilyen összehasonlítási pont a tényleges programozási nyelvhez és nem a keretrendszerhez kötődik:
- A Node.js-nek van egy nagy előnye, hogy az összes könyvtára Async. Pythonban rengeteg elérhető csomag van, de nagyon kevés közülük aszinkron
- Mivel a Node.js JavaScript futtató, és a JS-t használhatjuk front- és back-endhez is, a fejlesztők csak egy kódbázist tarthatnak, és ugyanazt a segédkönyvtárat használhatják
- A Google V8 motorjának köszönhetően a Node.js gyorsabb, mint a Tornado. De sok Python könyvtár C-ben íródott, és gyorsabb alternatívák lehetnek.
Egy egyszerű ‘Hello World’ példa
CODE: https://gist.github.com/velotiotech/b4d91554b739f2487bf6131ac65ec06d.js
Megjegyzés: Ez a példa nem használ semmilyen aszinkron funkciót.
Az AsyncHTTPClient modul használatával a REST hívást aszinkron módon tudjuk végrehajtani.
CODE: https://gist.github.com/velotiotech/5fe63eb5fd6cf3af9bf353c2fd3b4ca7.js
Mint láthatjuk, a `yield http_client.fetch(url)` coroutine-ként fog futni.
Komplex példa a Tornado Async
Nézzük meg az aszinkron kéréskezelőt.
WebSockets a Tornado használatával:
A Tornado rendelkezik beépített csomaggal a WebSockets számára, amely könnyen használható coroutine-okkal az egyidejűség eléréséhez, íme egy példa:
CODE: https://gist.github.com/velotiotech/34d0a0e0ecd57818ae1db1697c075777.js
Egy WebSocket kliensalkalmazást használhatunk a szerverhez való csatlakozáshoz, az üzenet bármilyen egész szám lehet. A feldolgozás után az ügyfél megkapja az eredményt, hogy az egész szám prím-e vagy sem.
Itt van még egy példa a Tornado tényleges aszinkron funkcióira. Sokan hasonlónak fogják találni a Golang Goroutine-hoz és a csatornákhoz.
Ebben a példában elindíthatjuk a worker(eke)t, és azok a ‘tornado.queue’-t hallgatják. Ez a várólista aszinkron, és nagyon hasonlít az asyncio csomaghoz.
CODE: https://gist.github.com/velotiotech/1477131948ca23879167df0281726d02.js
Következtetés
1) Az aszinkron keretrendszereknek nincs sok haszna, ha a számítások nagy része CPU-központú és nem I/O.
2) A magonkénti egy szálas modellnek és az eseményhuroknak köszönhetően több ezer aktív ügyfélkapcsolatot tud kezelni.
3) Sokan azt mondják, hogy a Django túl nagy, a Flask túl kicsi, a Tornado pedig pont jó:)