Kometa přináší web v reálném čase

Real-time web (nebo též česky „web v reálném čase“) je podle odhadů analytiků „buzzwordem zítřka“. Budete se s ním setkávat čím dál víc, jak se postupy R-T webu budou stávat běžnějšími. Pojďme se podívat na jednu technologii, která je s realtime webem často spojována, a která stála např. za Google Wave.
Nálepky:
Implementace realtime technik v současném webu naráží na problém, a to že současný web je projektován jednosměrně, tedy že „klient táhne“. Bohužel pro opravdový „web v reálném čase“ potřebujeme i to, aby měl server možnost poslat zprávu klientovi tehdy, když nastane nějaká událost hodná pozornosti.
Real-time web
Web v reálném čase je, podle definice, souhrnem metod, technik a postupů, které slouží k tomu, aby se informace dostala k příjemci v ten okamžik, kdy ji autor vydá, a to bez toho, aby musel příjemce (nebo jeho software) neustále kontrolovat, zda není něco nového. Wikipedie dále upozorňuje na rozdíly proti známému pojmu „real-time computing“ – v real-time webu jde často o posílání krátkých zpráv, odkazů, statusů či podobných společenských PINGů. Pro lepší představu si lze real-time web představit jako implementaci chování instant messengerů či IRC v prostředí WWW.
Do webu v reálném čase spadá např. i problematika vyhledávání v takových informacích, ovšem její podrobnější popis by přesáhl rámec tohoto článku.
Technické obtíže
Na tu základní technickou obtíž přišel každý, kdo se zabýval myšlenkou napsat si nad webovými technologiemi (přesněji řečeno nad HTTP) vlastní implementaci instant messengeru či chatu. Poslat zprávu na server a tam ji uložit není problém, to dokážeme obyčejným formulářem, ale co dál? Jak zprávu poslat ostatním účastníkům chatu?

Heartbeat
Nakonec většina skončila u postupu, pro který se vžil název „heartbeat“, tedy pravidelné dotazování serveru, jestli není něco nového. Vyvážit rychlost opakování a „iluzi realtime“ je docela potíž, ale v určitých případech jde o dostačující techniku. Ovšem co pro náročnější aplikace?
Nechme stranou vlastní implementace a protokoly, a zůstaňme stále u možností, které dává HTTP. Může server poslat nějak HTTP požadavek klientovi? Jeho IP adresu má; problém ale přinášejí nejrůznější proxy, NATy, firewally a podobné věci, co stojí takovému spojení v cestě. Samosebou, pokud má klient veřejnou IP adresu a povolí ve firewallu příchozí spojení na dohodnutém portu, tak takové zpětné spojení možné je. Ovšem za současné situace je možnost, že všichni účastníci podobného (webového!) chatu budou mít veřejnou IP, čistě hypotetická. Určitou pomoc by mohl představovat protokol IPv6, ovšem i pokud odpadne nutnost používat NAT, budou firewally a proxy servery existovat dál a úspěšně bránit podobným kouskům.
Různě se s těmito problémy potýkají všelijaké P2P služby, ať už pro sdílení souborů nebo třeba pro VoIP (Skype) – ve většině případů implementují techniku podobnou technice „heartbeat“, kdy se pasivní uživatel (ten s neveřejnou IP, za NATem,… – zkrátka v naší terminologii „klient“) dotazuje aktivního, a ten mu posílá data. Existují pak různé triky, jako UDP hole punching, které usnadňují připojení ke klientovi za NATem, ale pokud chceme zůstat ve světě HTTP, tak bohužel nic z toho použít nemůžeme.
Což je škoda, protože existuje spousta služeb, postavených na webových technologiích, kterým by nějaká realtimová funkce prospěla a slušela – nemusí to být zrovna chat, mohou to být nejrůznější kolaborativní nástroje. Pravděpodobně nejzajímavější ukázku možností real-time webu přinesl projekt Google Wave (a jak se dnes ukázalo, nedokázal překročit stín technologického dema) nebo Google Docs, kde mohou jeden dokument upravovat v tutéž chvíli různí lidé (první setkání se situací, kdy se mění slova v dokumentu, který právě píšete, zanechá silný dojem).
Své vlastní P2P techniky nabízí nový Flash Player. Samosebou – není to postavené nad HTTP a používá vlastní protokol, ale je to krok, jak je možné do HTML stránek vložit elementy, které přijímají a v reálném čase zpracovávají zprávy od jiných strojů, aniž by si o ně musely explicitně říct.
Velmi výrazným krokem k real-time webovým aplikacím je návrh technologie WebSocket, implementované zatím v novém Chrome, která standardizuje otvírání komunikačních kanálů se serverem, po kterých může server zasílat klientům zprávy.
Kometa

Dialog s Comet serverem
Moc možností, jak server může poslat zprávu klientovi, není, jak je vidno. Přesto existuje postup, který do jisté míry jako „server push“ funguje, a nazývá se Comet server. Jeho princip je velmi prostý: Klient naváže spojení se serverem standardním způsobem jako při běžném HTTP dotazu, a server odpoví, ale spojení neuzavře a ponechá ho otevřené. Má tak k dispozici legálně otevřený komunikační kanál, po němž může v případě potřeby poslat svou zprávu. Server tak, s trochou obrazotvornosti, vypadá jako kometa: jádro, od něhož se táhnou dlouhé šlahouny neuzavřených spojení…
Nevýhody jsou evidentní a jasné na první pohled: Server si musí udržovat všechna spojení stále živá a blokuje si tím volné prostředky. Počet uživatelů, který jeden takový server obslouží, je tedy omezený. Toto omezení by šlo obejít pomocí dalších „comet hubů“, např. ve spojení s protokolem PubSub, který je zaměřen rovněž na šíření informací v reálném čase. Budete potřebovat Comet server, který taková spojení umí udržet, s běžným Apačem si nevystačíte. Klient nesmí visící spojení uzavřít s timeoutem. A v neposlední řadě nesmí takové spojení uzavřít nějaký jiný pilný síťový prvek na cestě, který usoudí, že třeba hodinu otevřené HTTP spojení, přes které prošlo pět paketů, zaslouží zavřít.
Výhoda je pravděpodobně jediná, zato podstatná: Na straně klienta si vystačíte s běžným webovým prohlížečem, bez jakýchkoli pluginů, doplňků, knihoven…
Jak to klient dělá?
Klient – tedy běžný prohlížeč (míněno na úrovni roku 2010) má několik možností, co s dlouho otevřeným spojením dělat. Jedna z nejběžnějších metod je použít toto spojení jako atribut src neviditelného elementu iframe – když server potřebuje poslat nějakou zprávu, pošle tímto spojením nějaký <script>. Jakmile dorazí prohlížeči nějaký skript, tak jej provede, protože prohlížeče zpracovávají přicházející data postupně, nečekají až na uzavření spojení (to by se leckdy načekaly). Druhá metoda používá AJAX, tedy přesněji řečeno XHR (XMLHttpRequest).
Protože opravdu dlouho udržované spojení by mohlo přinášet řadu nevýhod, používá se do jisté míry kompromisní technika, kdy se klient dotáže serveru, zda jsou nějaké nové zprávy. Server potvrdí navázání spojení, ale nepošle žádná data a spojení nechá otevřené až do doby, dokud nebude mít nějakou zprávu pro daného klienta. Jakmile zprávu má, pošle ji a spojení uzavře. Klient obdrží zprávu, zpracuje ji a položí další dlouhodobý dotaz.
Na straně klienta si tedy vystačíme s běžně používanými a známými postupy – iframe, JSONP, AJAX – a s trochou fantazie. Co na serveru?
Comet server
Jak jsme si už řekli, vyžaduje tento postup server, schopný udržovat dlouhodobá HTTP spojení (což je v přímém protikladu k základnímu požadavku, kladenému na HTTP servery, tedy rychle obsloužit klienta a uvolnit zdroje pro dalšího). S běžným serverem tedy nevystačíme. Naštěstí existuje poměrně dost serverů, které lze pro Comet použít. Mezi ně patří Jetty6 s technikou Continuations (nový Jetty implementuje i WebSockets), Faye, HTTP Push modul pro NGiNX, WebSync pro IIS, StreamHub, Orbited, Jabbify či snadno instalovatelný a komplexní Ajax Push Engine (APE).
Zajímavou alternativou je i Hookbox, který umožňuje pro testovací účely vytvořit vlastní hostovaný Comet server – můžete si tedy (s určitými omezeními) vyzkoušet práci s takovým serverem bez nutnosti cokoli instalovat.
Příklad: Chat s APE

Maskot projektu APE
Problematika Comet serverů nemůže být v jednom informativním článku probrána do hloubky, a tak záměrně upustíme od dalších a hlubších informací (Bayeux protokol v Dojo) a namísto toho si ukážeme praktické použití takového serveru, a to v roli už několikrát zmíněného chatu. Příklad bude poháněn právě serverem APE.
APE je napsaný v jazyce C a není problém jej nainstalovat na jakýkoli POSIX server. Jeho instalace není nijak obtížná, pro nejčastější linuxové distribuce je dokonce k dispozici v podobě balíčků. Po instalaci a nezbytném nastavení, popsaném v dokumentaci, můžeme rovnou vyzkoušet některé z dodaných ukázkových příkladů, projít si tutoriály nebo pročíst informace o tom, co to vlastně Comet server a technologie AJAX Push je.
Server APE obsahuje nejen vlastní výkonné jádro, ale i JSF, tedy JavaScript Framework, který zapouzdřuje práci s Comet serverem do snadno použitelné a pochopitelné podoby. Je navržený tak, aby dokázal spolupracovat s běžným HTTP serverem (Apache, Lighttpd, IIS, …) a pro běžné použití jej pravděpodobně budete instalovat právě k běžícímu HTTP serveru.
Instalace z balíčků je přímočará. Budete potřebovat mysql-common balíček, pokud jej v systému nemáte. Samozřejmě můžete použít i cestu překladu zdrojových kódů, je-li pro vás schůdnější.
Před testem budete muset nastavit HTTP server tak, aby byl JSF přístupný standardním způsobem (např. http://example.com/ape-jsf/…) a povolit port – standardně je nastaven 6969. V souboru ape-jsf/Demos/config.js je třeba upravit cesty k souborům, a pak už nic nebrání vyzkoušet dodané příklady.
Pro čtenáře Zdrojáku jsem připravil zkušební APE server, na kterém mohou vyzkoušet fungování APE. Zkušební server je k dispozici jako šablona u hostingu Virtualmaster.
Odkazy
- Články o Comet na serveru Ajaxian
- Comet na Wikipedii
- Choosing Comet server
- Google – klíčová slova „Comet server“
Odkazy k APE:
Upřesnil bych, že odkazovaná technika P2P ve Flashi s tématem tohoto článku moc nesouvisí. Tam už nejde vůbec o komunikaci klient-server, ale klient-klient (a dokonce to už ani není nad TCP, ale nad UDP). Chcete-li uvést flashovou alternativu k webovým „push“ technologiím (tj. k web sockets či cometu), tak to je jednoduše obecná socketová TCP komunikace (založená na libovolném protokolu – XML, binární data, nebo třeba POP3, zkrátka cokoliv, co umí server servírovat). Ta byla k dispozici ve Flashi mnohem dříve než P2P.
Do přehledu dostupných řešení bych přidal lightstreamer.com, k dispozici je i free edition.
Takova technologie tu je davno: http://en.wikipedia.org/wiki/MIME#Mixed-Replace_.28Experimental.29 Bohuzel diky MSIE se neda nasadit ve velkem.
MIME typ, zacinajici x-, rozhodne NENI zadny standard, je to napsane i na wiki – vendor-specific rozsireni, ktere se lehce rozsirilo. Aneb, kdo chce psa bit, hul si vzdy najde, ze?
Nechápu, proč se dává takové absolutní rovnítko mezi TCP/HTTP a internet. A to i u lidí u kterých by jeden čekal větší znalosti. TCP/HTTP je přece protokol navržený k nějakému účelu. Tímto účelem je jednorázové jednosměrné doručení většího nepoškozeného objemu dat primárně ve struktuře HTML na základě krátkého požadavku klienta. Na jiné úlohy tu jsou jiné protokoly.
Jestliže dnešní uživatelé mají čím dál silnější požadavek mít jediné uživatelské rozhraní (prohlížeč) pro velkou skupinu internetových služeb, pak je asi na čase se začít zamýšlet nad novým protokolem + strukturou dat a z toho vyplynou nové implementace serveru/ů a prohlížečů které nám nebudou házet tolik klacky pod nohy a budou tu s námi snad zase nějakou dobu. Přijde mi to mnohem správnější a smysluplnější cesta než postupně a nekoncepčně znásilňovat jeden konec řetězce TCP/HTTP/HTML jen pro to aby se na jednom místě doplnila funkcionalita, kterou by mělo zajišťovat zcela jiné místo. Je to typické lepení bez pořádného rozmyslu.
Nebo udělat primárně revizi HTTP protokolu (na tom to asi v tuto chvíli stojí) a zamyslet se jestli je tak nutné ho stále přenášet po TCP, nebo jestli to nerozšířit i pro UDP, samozřejmě s dořešením následujících důsledků. Ale to je zase v podstatě vypracování nového protokolu, jen jinak maskovaného ale možná politicky snadněji prostaditelného u uživatelů. Viz jaké je třeba teď hype kolem HTML5.0.
Ano, to co píšete je logické a já s tím naprosto souhlasím. Ale co naděláte – realita je taková, že klientem je prohlížeč, a jakékoli pokusy o standardizaci aplikační platformy (co třeba AIR?) zatím naráží na argument „… ale prohlížeč je všude!“ Doba je zkrátka taková, že pokud se přijde na to, že by lidem v prohlížeči víc vyhovovalo UDP, tak se vymyslí, jak jej nasimulovat přes TCP, protože je to jednodušší, rychlejší a levnější (!) než všem říkat, že mají používat něco jiného. Může se nám to nelíbit (a nelíbí se nám to), ale je třeba o tom informovat, protože tudy jde, ať chceme nebo nechceme, vývoj, a chceme-li být praktickým magazínem, nemůžeme říct „toto je ideově pochybené, o tom psát nebudeme, to pro nás neexistuje“.
Jasně že by bylo skvělé, kdyby tu byl Univerzální Síťový Klient, uměl plnohodnotný jazyk pro návrh UI a chovat se jako klient/server/P2P/atd. A taky by bylo skvělé, kdyby se lidi měli rádi a nikde se neválčilo.
Není třeba vymýšlet novinky jako AIR (jeho význam pro offline aplikace rychle slábne s příchodem moderních browserů). Stačí nedémonizovat pluginové technologie, které zrovna v této komunikační oblasti doplňují to, co browserům chybí. Málokdo ví, že může v HTML udělat aplikaci bez HTTP, na bázi TCP nebo UDP, prostě přesně podle akademických představ. Při zachování všeho toho, na co jsou uživatelé zvyklí – běh v browseru, bezpečnost sandboxu, GUI v HTML (pokud nevyhovuje GUI ve Flashi, Silverlightu, apod.).
Hlavní žába na prameni je jinde – u administrátorů firewallů. Což je důvod, proč i multiplayer flashové hry děláme s tou zatracenou kometou. :)
:-), Bohužel.
Strašná představa.. Bohužel asi pravdivá :(
Teda nevim, ale kdyz chci, aby mi server porad neco posilal, tak ho proste nenecham zavrit spojeni a pokud spojeni spadne, tak ho obnovim. Proc kolem toho delat takovou vedu?
Kolik takových otevřených spojení dokáže váš server držet?
Tenhle argument sem moc nepochopil. Pro server je mnohem mensi zatez drzet otevrena neaktivni spojeni, nez neustale otevirat a zavirat spojeni kvuli heartbeatu…
Tak zkuste odpovědět na otázku: „Kolik otevřených spojení dokáže Váš webserver držet?“
Běžný Apache blahé paměti na každé spojení potřeboval jednoho potomka a ten potřeboval nějaké megabajty paměti (odhadněme třeba 8 MB, a to při několika zapnutém PHP spíš podceňuju). Pokud máte server, který má 1024 MB RAM, tak mi to vychází na 128 otevřených spojení, což může být proklatě málo i pro lokální intranet.
Jaká je situace s Apachem dnes, tak to netuším.
Stačí tak?
Nevim, kolik otevrenych spojeni dokaze muj webserver drzet. Nikdy sem na ten limit nenarazil…
Proc se bavime o pametove nenazranosti Apache? Ostatne pokud nekdo chce vykon nepouzije PHP, ale aplikacni server bud samostatnej nebo komunikujici pres fcgi…
A co shared memory? Apache nikdy nebyl takhle nenazrany.
IMHO je to právě naopak.
V pripade vysokych narokov na pocet pripojeni nebude clovek predsa pouzivat apache alebo nginx, ktore na nieco take proste nie su stavane.
Osobne by som pouzil erlang, ktory nema problem spawnnut 300k threadov za sekundu s minimom pamate. Vid napr
http://www.metabrew.com/article/a-million-user-comet-application-with-mochiweb-part-1/
To nemá, ale s otevřením 300k socketů už má problém na úrovni OS. Jak s množstvím, portů, tak s množstvím otevřených „souborů“.
Pri takovym poctu aktivnich uzivatelu, ale uz nikdo nebude pouzivat pouze jeden server. Ostatne typickym prikladem servisu s milionama otevrenych spojeni jsou IM servery jako ICQ, ktery sou tu uz pres deset let…
Nic ve zlém, ale proč s tím nepřišls dřív, že je to tak jednoduché. klukům v americe by to ušetřilo dost práce. Teď, když tím zabili tolik času, tak asi budou mrzutí.
A to se jich tím zabývá dost (třeba vývojáři glassfishu) a žádného to nenapadlo :-))
Na to má odpověď Vladimír Renčín
Ehm, co z toho, ze tohle pouziva ICQ uz 14 let si nepochopil? :)
Nepoužívá, resp ne erlang. Clustery samozřejmě ano. Na počet obsloužitelných spojení v ejabberd se můžete zeptat Pinkyho, má s tím na jabbim celkem zajímavé zkušenosti :)
Ale článek je o Comet a tam je to malinko o něčem jiném, protože klient neudržuje pořád jediné TCP spojení jako u IM. Posílá na rozdíl od IM mnoho požadavků a potřebuje hodně pomocných Comet spojení s tím, že bude zachovaný session tracking.
První (a jediný) mně známý web framework (a zrovna postavený na erlangu), který umí pracovat plně distribuovaně bez inteligence v load balanceru, je Nitrogen (nitrogenproject.com) a bez hacků to umí až od verze 2, která je stará maximálně pár měsíců. A interně používá právě již zmíněný mochiweb nebo Yaws.
Každopádně se celkem těším na web sockets, už se objevují první vlaštovky.. bude snad konec kometám.
Ja mluvil obecne o velkym mnozstvi dlouho otevrenych TCP spojeni. Jedinej rozdil mezi „RT webem“ jak je popsanej v clanku a mezi ICQ je, ze komunikace ICQ je obousmerna po tom jednom spojeni, kdezto u „RT webu“ je komunikace po dlouhodobym spojeni pouze od serveru ke klientu a na opacnej smer se pouzivaj klasicky kratky HTTP requesty.
Jedna poznamka, je rozmune alebo spravne nazyvat tuto temu zrovna web v realnom case ? OS aj aplikacie v realnom case su vecsinou o niecom inom a aj inak zamerane, tak predpokladam ze aj „real time web“ by malo byt nieco ine ako v podstate web kde klient-server si drzi spojenie, lebo v podste sa tu o to jedna.
Viz text: „Wikipedie dále upozorňuje na rozdíly proti známému pojmu „real-time computing“ – v real-time webu jde často o posílání krátkých zpráv, odkazů, statusů či podobných společenských PINGů. Pro lepší představu si lze real-time web představit jako implementaci chování instant messengerů či IRC v prostředí http://WWW.“ – ano, je to něco jiného, ale říká se tomu zkrátka real-time web. Můžeme tomu říkat třeba „web s instantním upozorněním“, ale nebudeme si rozumět.
hm, a proč to olízávání servrovejch služeb nenechat na klientovi.
As Is.
Že by opět vítězila snaha o centralizaci všeho v Praze?
A to že sa nechodíš pýtať na centrálu pošty či mas niečo nové, ale nová pošta príde vždy za tebou sama do schránky je tiež dôsledok „snahy o centralizaci všeho v Praze“?
Ta analogia je možno ironická, kritická a zabavná, ale aj úplne nepresná.
Dôvodov je mnoho. Stačí sa pozreť na trendy moderných webov a požiadavky ktoré sa na ne kladú.
Fungují výborně. Zatím v Chrome, Safari a FF 4 beta.
Pro ostatní prohlížeče je umí nahradit kousek Flashe – http://github.com/gimite/web-socket-js