Django je asi nejznámější Python web framework a my ho používáme téměř na všech projektech kvůli jeho stabilitě, funkcionalitám a ekosystému. Aktuálně prochází důležitou změnou, a sice zavedením podpory pro asynchronní funkcionalitu. V tomto článku nahlédneme této změně pod pokličku.
Django patří k nejstarším stále používaným open source webovým frameworkům v programovacím jazyce Python. Za svoji existenci prošel mnoha změnami (built-in migrace, konec podpory Python 2 atd.) a příchodem verze 3.0 tu můžeme logicky přivítat další.
Hlavní předností Djanga oproti jiným frameworkům je to, že je tzv. „batteries included“, což znamená, že ve chvíli, kdy poprvé spustíte nějaký projekt, tak máte dopředu nastavené obrovské množství funkcionalit připravených k použití.
U jiných frameworků je nutné spoustu těchto funkcionalit vytvořit nebo dohledat v další knihovně – takto funguje například framework Flask. Někomu toto detailní nastavování může vyhovovat, ale nám nejvíce sedí přístup Djanga.
Další výhodou Djanga je geniální dokumentace a obrovský ekosystém knihoven, který tento framework doplňuje. My Django používáme převážně v kombinaci s Django REST frameworkem, který využívá stability a vyspělosti Djanga a umožňuje nám rychle a kvalitně stavět REST API.
Nyní Django funguje pouze synchronně (s opomenutím skvělého Django Channels). To v praxi znamená, že když aplikace provádí akce, které jsou „I/O bound“ (například volání třetí služby, vyžádání dat z databáze apod.), tak vlákno obsluhující daný požadavek je “blokováno” čekáním na odpověď z dané akce.
Akce může být samozřejmě dokončena během několika desítek milisekund, což je ale z pohledu počítače věčnost. Jak lze tedy tento problém řešit?
Zde přicházejí na řadu principy asynchronního programování. V Pythonu je možné pracovat s vlákny jako takovými, což má za následek násobného zvýšení komplexity projektu. Ovšem, se schválením několika důležitých PEP (PEP 3156 – asyncio modul, PEP 492 – async and await, PEP 380 a další) je možné v Pythonu využívat tzn. coroutines. Ty umožňují využití tzv. kooperativní souběžnosti (cooperative concurrency).
Tento princip znamená, že veškerou práci stále odvádí pouze jedno vlákno, ale je mu umožněno určitou práci pozastavit (např. čekání na I/O akci) a pokračovat v ní později. A mezitím může právě dělat něco jiného.
To tedy znamená, že aplikace nemusí úplně zastavit a čekat na odpověď z databáze (i když je to několik milisekund), ale místo čekání může konat jinou práci – např. obsluhovat další požadavek. Až bude akce, která komunikuje s databází, dokončena (= databáze vrátila data, které jsme si vyžádali), může být daný požadavek zpracován a může být odeslána odpověď.
Dalším důležitým termínem je tzv. „event loop“, který mimo jiné umožňuje sledovat stavy jednotlivých úkolů a přijímá úkoly další.
Také je potřeba podívat se na rozdíl mezi WSGI a ASGI. WSGI definuje rozhraní mezi webovým serverem a aplikačním serverem. Toto rozhraní bylo specifikováno v roce 2003 v rámci PEP-333 (PEP-3333 to poté specifikuje pro Python 3). Díky tomuto rozhraní je možné používat jakýkoliv webový server (např. Nginx) a jakýkoliv aplikační server (např. Gunicorn). Jelikož je ale WSGI už poměrně starý standard, který nebere v ohledu asynchronní funkce moderních webových frameworků, bylo nutné přijít s novým standardem.
Tím se dostáváme právě k ASGI. Tento standard se staví do pozice nástupce WSGI. Je kompatibilní s WSGI servery, zárověň ale umožňuje nativní využití moderních protokolů – např. WebSockets. Specifikace “asgiref” nyní patří pod Django projekt. ASGI standard také umožňuje integraci dalších ASGI aplikací.
Co to tedy znamená pro Django? Přepsat celý projekt, aby podporoval asynchronní funkcionalitu? To opravdu ne. Jelikož vývojářům Djanga jde o zpětnou kompatibilitu (upgrade na novou verzi nic nerozbije), rozhodli se zvolit jinou taktiku.
Nové asynchronní části Djanga budou “žít” vedle těch stávajících. To znamená, že vývojáři aplikací nebudou muset vůbec nic měnit (pokud nebudou chtít). Bude tedy možné využít výhody asynchronních funkcí pouze tam, kde to dává smysl (např. volání API třetí služby, možnost odeslání e-mailu rovnou z view bez potřeby asynchronní fronty (např. Celery, atp.).
Podpora async pro byla představena v DEP 0009 (Django Enhancement Proposal; autor Andrew Godwin). Ta je potom rozdělena do 3 fází. V první fázi přijde podpora ASGI, kde bude možné využít aplikační server podporující asynchronní funkcionality (např. WebSockets, long polling, atd.) – verze 3.0. V další fázi plánují vývojáři podporu asynchronních middleware a views – verzi 3.1.
Poslední fáze by potom měla přinést asynchronní funkcionalitu do Django ORM (API pro komunikaci s databází) – verze 3.2/4.0. Dle hlavního vývojáře tohoto přechodu Andrew Godwina (tvůrce South, Django Channels, asgiref atp.) bude třetí fáze pravděpodobně nejsložitější.
Myslíme si, že pro budoucnost Djanga je velice důležitá podpora async, jelikož v tom vidíme budoucnost webového vývoje. Je tedy důležité, aby Django „neusnulo na vavřínech“ a stále se zlepšovalo. Což se briliatním lidem kolem tohoto frameworku určitě nestane a věříme, že Django bude relevantním frameworkem i nadále.