neděle 26. listopadu 2006

Java trpí nedostatkem hostingů

Ze všech stran se na nás valí připravované novinky v JDK6 a JDK7, které by měly zvýšit efektivitu, zkvalitnit a zjednodušit vývoj v Jave. Jenže problém Javy leží trochu někde jinde než ve vývojové fázi. Problematickou fází, alespoň pro určitou část vývojářů, je hosting Java aplikací. Jedním z mýtů o Jave je, že není tak efektivní jako PHP. K šíření tohoto nesmyslu nezanedbatelnou měrou pomáhá fakt, že není jednoduše možné hostovat webové aplikace v Jave takřka kdekoliv jako v případě PHP.

Jenom v České republice existuje velké množství freehostingu pro PHP aplikace a ještě větší množství placených hostingu a ve světě je tomu stejně. Oproti tomu freehostingy Javy by se v celosvětovém měřítku dali spočítat na prstech jedné ruky. V placeném hostingu je sice situace lepší, ale to k popularizace Javy pro web samozřejmě nestačí.

K čemu je Jave skvělá variabilita middleware produktů, když to základní, tedy aplikaci někde hostovat (pokud možno zdarma) chybí. Samozřejmě je pro vývojáře mnohem lepší, když může svou aplikaci nasadit takřka kdekoliv, než přemýšlet kde by to vlastně vůbec šlo a za kolik. V PHP i v Jave si doma uplácáte na koleně aplikaci za pár dní, jenže narozdíl od té v PHP můžete tu v Jave strčit do šuplíku pokud si nezaplatíte hosting a nebo si nerozjedete vlastni server.

Jenže ono se to lehce řekne udělat hosting Java aplikací, ale hůře se to provádí. Java jako platforma pro web je v současném modelu, alespoň podle mého názoru, velice obtížně hostovatelná. Největší problém je izolace jednotlivých web aplikací uvnitř JVM. Ač je snadné zamezit naschválnému kódu alá System.exit(0) díky SecurityManageru, zůstává několik dost závažných problémů.

sdílený paměťový prostor
paměťová náročnost či případně memory leak jedné webové aplikace složí všechny zbylé uvnitř VM. Paměťový prostor VM je shora striktně omezen maximální hodnotou, která je zadaná při startu VM a která nemůže být při běhu přesáhnutá.
velká paměťová náročnost
díky paměťovému modelu a jeho správě Garbage Collectorem (uklízeč, sběrač neplatných objektů) je Java server mnohem více paměťově náročnější než klický http server. S každým HTTP požadavkem vzniká velké množství nových objektů, kterou jsou po jeho skončení k ničemu a čekají až je GC odstraní. To samo o sobě není problém, ale GC musí být velice citlivě nastaven tak, aby nepracoval na hranici zaplnění celého heapu a nedocházelo k jeho častému volání, které by vyústilo ve značné zpomalení běhu serveru.

Od verze 1.4 je možné významně ovlivnit chování GC. Paměťová náročnost není z hlediska správy jedné aplikace, kterou máme pevně v ruce problém. Jenže v případě veřejného serveru máme množství paralelně bežících aplikací uvnitř jedné VM, které se mohou velice nepříjemně ovlivňovat.
DOS náchylnost
Je možné snadno dosáhnout DOS (Denial of Service) útoku relativně nezávadným kódem. Dva příklady. Prvním z nich je nekonečný cyklus způsobí plné vytížení procesoru po dobu do vypršení timeoutu HTTP požadavku. Druhý příklad představuje vytvoření nového HTTP požadavku na sebe zevnitř bežícího vlákna zpracovávajícího HTTP požadavek. To vede k vyčerpání vnitřních vláken určených k obsloužení požadavků. Výsledkem je, že server je schopen akceptovat HTTP požadavky, ale není schopen je vnitřně obsloužit - vzniká deadlock. Vytváření nových vláken je limitované zdroji operačního systému např. na OS Linux je každé Java vlákno mapováno jedna ku jedné na vlákno operačního systému.

Pozn: Některé aplikační servery nabízejí možnost nastavení dedikovaných thread poolu (jak se to řekne česky?) per aplikace.
nešetrnost hot deploymentu
Pokud dojde ke změně JSP aplikační server může snadno nové JSP zkompilovat a použít. V případě tříd to tak snadno nejde. Za nahrávání tříd je v Jave zodpovědný classloader, ale ten neumožňuje prostou výměnu staré třídy za novou. Naštěstí každá webová aplikace má uvnitř serveru vlastní classloader. Pokud je detekovaná (sledováním souborového systému) nová verze některé třídy, zahodí se celý classloader dané aplikace a aplikace resp. její třídy se nahrají znovu novým classloaderem - tomu se říká hot deployment.

Nahrávání celé aplikace při změně každé třídy je v produkčním prostředí systémově drahé. To znamená, že infrastruktura hostingu musí počítat vždy s dvojicí serverů - produkční a testovací. Na testovacím, kde je hot deployment zapnutý, se aplikace vyladí a poté se propaguje na produkční server. To je mnohem náročnější na vývoj než prosté nakopírování nového PHP souboru na server.

Pozn: Při hot deploymentu dochází například na serveru Tomcat k nepříjemnému memory leaku, který vzniká díky tomu, že GC nemůže uvolnit speciální oblast heapu, která slouží k definici tříd.

Ano i tyto problémy jako každé lze nějak řešit nebo omezit jejich dopad. Otázka je proč Sunu tato situace nevadí. Kdyby se totiž podařilo tyto problémy vyřešit, rozšířenost Javy by se nepochybně mnohonásobně zvýšila. Dokonce existuje JSR 121 (Isolation API, Resource management API viz A Resource Management Interface for the Java Platform(PDF)), které bylo úspěšně použito v prototypu takzvané MVN (Multitasking Virtual Machine) a tyto problémy může významnou měrou pomoci redukovat.

Ještě více je zarážející, že koncept MVN a nebo jeho aspekty Sun aplikoval pro oblast mobilních zařízení kde bylo nutné brát zřetel na omezené zdroje. Korunu všemu dává Sun tím, že pro vlastní stránky používá PHP. Ať už je to z jakéhokoliv důvodu, člověka hned napadne že nepojídají jídlo, které sami produkují.

Ač to bude možná znít zvláštně, tak právě nyní je největší možnost s tím něco dělat. Díky otevření Javy jako open source je nyní možné prosadit koncept JSR 121 mnohem snáze. Přenositelná implementace MVM a aplikační server využívající isolation API a resource management by mohla znamenat zlom. V této souvislosti je velice zajímavé, že ať už BEA Weblogic či IBM WebSphere měli vlastní implementace JVM a nešáhli po něčem podobném.

Kdybych si měl vybrat mezi tím, jestli tu bude široce dostupný Java web hosting díky forku JVM na MVN a nebo ideovou čistotou JVM, tak volím raději potenciálně nebezpečnější fork...