Staré dobré CGI

Vůbec první možností, jak generovat dynamické webové stránky, bylo rozhraní CGI aneb Common Gateway Interface. Ve skut...


Vůbec první možností, jak generovat dynamické webové stránky, bylo rozhraní CGI
aneb Common Gateway Interface. Ve skutečnosti se jedná o program napsaný v
libovolném programovacím jazyce (nejen skriptovacím; název skript je zažitý,
ale poněkud zavádějící). Přesnější by bylo CGI aplikace.
Aby mohl být program použit jako CGI skript, musí splňovat jedinou podmínku: po
spuštění musí na výstup vygenerovat HTTP hlavičku Content-Type (když chce, může
i další) následovanou prázdným řádkem, a pak vlastní obsah dokumentu (typicky
HTML stránku, ale může se jednat o libovolný typ plain text, obrázek... jen je
potřeba nastavit hlavičku Content-Type na odpovídající hodnotu). Když
požadované URL ukazuje na CGI skript, server nevrátí klientovi jeho kód;
namísto toho připraví prostředí (nastaví speciální proměnné) a v něm pak
program spustí. CGI skript má při svém běhu tyto proměnné k dispozici a může z
nich získat různé informace o serveru i klientovi (včetně např. jeho IP
adresy). Klient má možnost v požadavku poslat CGI skriptu vstupní informace ke
zpracování. Po skončení programu server převezme jeho výstup, doplní další
potřebné hlavičky a odešle klientovi. Podpora CGI skriptů je dnes součástí snad
každého HTTP serveru. Ze samotného principu fungování CGI je ale vidět hlavní
nedostatek pomalá odezva aplikací při každém požadavku musí být totiž program
spuštěn znovu. U aplikací napsaných ve skriptovacím jazyce je zpoždění obzvlášť
znatelné. Například při požadavku na CGI skript napsaný v Perlu se musí nejprve
spustit interpret, který načte skript, poté nahraje dodatečné moduly (jsou-li
vyžadovány) a nakonec skript přeloží a spustí. Větší aplikace se navíc
inicializují čtením různých konfiguračních souborů, vytvářením spojení do
databází... a toto vše je po vyřízení jednoho požadavku zase ztraceno. Navíc,
data od klienta předává server CGI skriptu pomocí služeb OS (např. přes rouru),
což rychlosti také nepřidá. Pokud od aplikace požadujeme vyšší výkon, musíme od
CGI přejít k pokročilejším technologiím.

Přidejte rychlost s Fast-CGI
Jan Holec
Fast-CGI skripty byly vymyšleny s cílem odstranit některé výkonnostní
nedostatky klasických CGI skriptů. Výhodou takového řešení by mělo být hlavně
zvýšení rychlosti ovšem při zachování téměř stejné jednoduchosti jako u starého
CGI.
Běh Fast-CGI skriptu není vázán na jeden konkrétní požadavek, program se spustí
pouze jednou (např. automaticky po startu HTTP serveru, nebo když na něj přijde
první požadavek), provede inicializační část (načtení konfiguračních souborů,
atd...), a potom čeká a v cyklu vyřizuje příchozí požadavky. Fast-CGI skript má
tedy zhruba takovouto strukturu: <inicializace, kterou stačí provést jenom
jednou>
while (FCGI_Accept() >= 0) { <vyřízení požadavku>
}
Je tedy vhodné přesunout co nejvíce činností do úvodní inicializační části.
Jakmile přijde požadavek, HTTP server nastaví proměnné prostředí (stejně jako u
obyčejného CGI skriptu) a nastaví proudy stdin, stdout a stderr, aby fungovaly
obvyklým způsobem (na standardním vstupu jsou data dodaná klientem metodou POST
a výstupními proudy se předávají data zpět serveru). Funkce FCGI_Accept() pak
vrátí nezápornou hodnotu, a umožní tím aplikaci požadavek vyřídit. Záporná
hodnota v tomto případě znamená žádost (od serveru) na ukončení skriptu, např.
chystá-li se HTTP server sám skončit. Program ovšem může skončit kdykoli sám
chce v takovém případě je obvykle serverem automaticky spuštěn znovu.

Temné pozadí webových serverů
V dnešní nastupující době e-commerce stále více roste důležitost opravdu
funkčních webových stránek. Pokud chcete na dnešním globálním trhu uspět, pak
musíte zapomenout na staré statické stránky s byť sebelepší grafikou. Svět je
dnes dynamický více než kdy jindy a stejný "pohyb" očekává i od vašich webových
stránek. Ale jaký nástroj je ten pravý?
Srovnání aplikačních rozhraní pro WWW
Variant, jak oživit webové stránky, jak zpracovávat data od zákazníků on-line
či jak rozchodit webový obchod, existuje velké množství a není jednoduché mezi
nimi vybrat správnou.
Jan Holec
Podobně jako velké množství možností existuje i celá řada postupů, jak zvolit
nejvhodnější aplikační rozhraní pro vaše potřeby. My se zaměříme na dvě
nejdůležitější kritéria na vlastní jazyk a na rychlost probíraných řešení. V
prvním případě se jedná hlavně o subjektivní názor, který záleží zejména na
vašich zkušenostech a znalostech tedy jak se vám ten který jazyk líbí. Druhé
kritérium je pak již jasné. Rychlost je klíčová vlastnost vaši návštěvníci
nemají čas čekat, chtějí své informace nebo zboží hned teď a ne až se vašemu
serveru zlíbí. K tomu se však dostaneme až v příštím čísle.
Nyní se podíváme trochu podrobněji na našich 5 kandidátů pro "temná zákoutí"
webových serverů na CGI, Fast-CGI, PHP, Java Servlety a JSP. První dvě řešení
jsou více než dobře známá a více informací o nich najdete v krátkých článcích
na předchozí straně, další varianty jsou pak popsány na následujících řádcích.
PHP skript
PHP je skriptovací jazyk, který vkládáme přímo do HTML kódu. Pod názvem PHP
skript tedy rozumíme běžnou HTML stránku, která obsahuje sekvence PHP kódu
uvozené speciálními značkami <? kód ?> (v souladu s SGML), případně <?php
kód ?> (XML styl), lze však použít i klasické uvození <SCRIPT
language="php">...</SCRIPT>. PHP skripty server pozná podle přípony
(nejčastěji .php, .php3) a předá je ke zpracování subsystému PHP. Ten nahradí
fragmenty kódu uvnitř HTML tím, co je provedením tohoto kódu vygenerováno, a
výsledek je předán klientovi. Aby bylo PHP co nejvíce prakticky použitelné,
obsahuje velké množství vestavěných funkcí, lze např. za běhu generovat
obrázky, dokumenty ve formátu PDF, pracovat s internetovými protokoly HTTP,
FTP, SNMP, POP3, IMAP, LDAP, apod. Jednou ze silných stránek PHP je spolupráce
s databázemi. Na rozvoji PHP se i nadále intenzivně pracuje. V současné době
nejnovější verze, PHP 4.0, je údajně 2 až 10krát rychlejší než předchozí verze
3.0. K dispozici je rovněž Zend Optimizer, který podle autorů urychlí běh PHP
skriptu o dalších 40-100 %. Java Servlet
Java Servlet je aplikace pracující na straně serveru (na rozdíl od známých
appletů) napsaná s využitím Java Servlet API, která akceptuje a vyřizuje
klientské požadavky. HTTP server je povinen udržovat v běhu JVM (Java Virtual
Machine), pod kterým jsou všechny servlety spouštěny. Je-li server realizován
jediným procesem, může být JVM jeho součástí. Pokud server k vyřizování
požadavků používá více současně běžících procesů (např. Apache), funguje JVM
jako externí proces, a přístup k servletu tedy vyžaduje přepnutí kontextu
procesu. Je možný i opačný přístup: HTTP server je sám napsán v Javě (např.
Java Web Server) a běží pod JVM spolu se všemi servlety. Java Servlet není nic
jiného než kód třídy. Životní cyklus servletu vypadá zhruba takto: Servlet
(instance objektu) je vytvořen a inicializován (metoda init()). Toto může být
provedeno buď při prvním požadavku na servlet, anebo můžeme v konfiguračních
souborech přímo vyjmenovat servlety, které se mají vytvořit hned při startu
serveru.
Vytvořená instance vyřizuje požadavky od klientů pokaždé, když přijde
požadavek, je aktivována metoda service() třídy. Všechny požadavky na servlet
daného jména vyřizuje tato jediná instance, další se už nevytvářejí. Ukončení
servletu a odstranění objektu z paměti má pak na starosti garbage collector. To
se může stát např. i tehdy, přeložíme-li novou verzi servletové třídy. Za
servlet lze považovat takovou třídu, která implementuje rozhraní
javax.servlet.Servlet. Toto rozhraní můžeme implementovat sami, častěji se však
využívá třída javax.servlet.GenericServlet a její potomek, javax.servlet.http.
HttpServlet. Obě tyto třídy zmíněné rozhraní implementují, jsou však
abstraktní; nemůžeme přímo vytvářet jejich instance. To by ostatně ani nemělo
smysl, protože některé klíčové metody v nich jsou abstraktní (nedefinované).
Pokud nechceme pracovat s protokolem HTTP, musíme vytvořit potomka třídy
GenericServlet a předefinovat v něm (alespoň) metodu service(). U třídy
HttpServlet je to jiné metoda service() je už napsaná tak, že rozezná druh
požadavku (GET, HEAD, POST...) a podle toho přenechá jeho zpracování některé z
konkrétně zaměřených metod: doGet(), doPost() atd. Předefinujeme tedy některou
z nich (všechny jsou implementované tak, aby vracely chybu HTTP BAD_ REQUEST).
Mezi výhody servletů patří naprostá přenositelnost bytekódu mezi platformami a
možnost využití standardního API Javy. Java Server Page (JSP)
Na rozdíl od servletu, který musí sám obstarat vygenerování celého výstupu pro
klienta (např. HTML dokumentu), Java Server Pages fungují opačně většina HTML
kódu je zapsána v souboru staticky, pouze obsahuje fragmenty kódu v Javě,
kterými se určitá část výstupu dogeneruje. Na zdánlivě podobném principu
pracuje PHP, ale JSP nejsou interpretovány při každém požadavku (ani nemohou
být, protože obsahují zdrojový kód v Javě). Při prvním použití je JSP
automaticky transformována na zdrojový kód servletu (okolní "statický" HTML
text je převeden do příkazů print v metodě service()). Tento servlet je poté
přeložen (vznikne soubor .class obsahující bytekód), a všechny požadavky
směřující na JSP jsou tímto servletem vyřizovány. JSP a servlety tedy k sobě
mají velmi blízko a dá se očekávat, že i z hlediska výkonu budou srovnatelné. V
JSP se pro oddělení "výkonných elementů" od okolního HTML kódu používají
speciální značky tvaru <% ... %>. Tyto značky mají několik variant podle druhu
jejich obsahu, například: <%@ ... %> se používá pro direktivy, které mají vliv
na další zpracování JSP. Příkladem takové direktivy je <%@ page
isThreadSafe="false" %>. Touto direktivou způsobíme, že vzniklý servlet bude
implementovat rozhraní SingleThreadModel (tj. nebude využívat multithreadingu).
<%= ... %> pro výrazy, jejichž hodnota bude přímo dosazena do výsledného
dokumentu (vložený výraz je použit jako argument příkazu print). <% ... %>
uvozuje fragmenty kódu (tzv. scriptlety). Tento kód bude během generování
servletu vložen do těla metody service(). JSP deklarace jsou části kódu, které
budou vloženy do těla třídy servletu (ale mimo metodu service()). Takto můžeme
např. předefinovat některou metodu nebo vytvořit globální proměnné třídy, které
budou společné všem vláknům metody service(). Deklarace se uvozují značkami <%!
... %>. Ke všem značkám existují i XML-kompatibilní ekvivalenty. Fakt, že JSP
je v podstatě budoucí servlet, má bezprostřední vliv na její programování,
zejména na způsob získávání parametrů od klienta a generování výstupu. Uvnitř
kódu každé JSP má programátor přístup k několika předdefinovaným proměnným,
tzv. implicitním objektům. Mezi nejdůležitější z nich patří request (instance
třídy HttpServletRequest; pomocí této proměnné lze především číst parametry
požadavku, response (instance HttpServletResponse), a out (výstupní proud,
kterým posíláme data klientovi). Při vytváření JSP se v hojné míře používají
tzv. JavaBeans. Při jejich vhodném použití bude kód uvnitř JSP kratší,
přehlednější a snáze udržovatelný. JavaBeans umožňují oddělit obsah od
konkrétní implementace, která se může později změnit bez nutnosti zásahu do
JSP. Více o rychlosti
Základní informace o jednotlivých aplikačních rozhraních jsou tedy již jasné,
ale jak je to s jejich rychlostí? To se dovíte v dalším čísle, jako vždy v
sekci Technology.
0 2778 / alsn

Příklad typického servletu
import javax.servlet.*;
import javax.servlet.http.*;
public class MyServlet extends HttpServlet
{
public void init() throws ServletException { .... }
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException
{ /* vyřízení požadavků typu GET, resp. HEAD... */ }
public void destroy() { .... }
}
Uvedené metody tvoří skutečné jádro servletu. V metodě init() můžeme otevírat
pracovní soubory, spojení do databází, inicializovat různé datové struktury...
Tato metoda se provede pouze jednou při vytváření servletu, což je dobré z
hlediska výkonu. V metodě destroy() potom všechny soubory/spojení uzavřeme.
Musíme ale dát pozor na to, aby už bylo ukončeno zpracování požadavků ve všech
vláknech. Objekt HttpServletRequest slouží k získání dat zaslaných klientem
(jména a hodnoty parametrů, cookies), prostřednictvím metod objektu
HttpServletResponse pak nastavíme HTTP hlavičky (Content-Type) a vygenerujeme
výstup pro odeslání zpět klientovi.

Příklad použití JSP
Uvažujme třídu Employee s vlastností (property) salary typu int, pak
odpovídající metody pro práci s touto read/write vlastností budou:
public int getSalary()
public void setSalary(int newSalary)
Uvnitř JSP pak můžeme použít konstrukci:
<jsp:useBean id="prom" class="Employee" />
<jsp:setProperty name="prom" property="salary" value="10000" />
<jsp:getProperty name="prom" property="salary" />
První řádek je akce, která způsobí vytvoření instance objektu Employee v
proměnné prom. Druhý bychom mohli ekvivalentně zapsat jako
prom.setSalary(10000) uvnitř scriptletu. Akce getProperty přečte hodnotu
vlastnosti v dané instanci a vloží ji do výstupního proudu out.









Komentáře
K tomuto článku není připojena žádná diskuze, nebo byla zakázána.