(Rev. 32, 20. listopad 2005, 00:56:46)
Obsah dnešní lekce
Jen tak namátkou Vám mohu vyjmenovat přinejmenším tři metody, jak na jakýkoli fyzický stroj dostat libovolný počet libovolných verzí PHP, z nichž metoda současného běhu více instancí HTTP serveru je ta nejprimitivnější a nejdéle používaná.
Tento návod měl původně vzniknout o prázdninách roku 2004, tenkrát jsem měl pár měsíců svůj první notebook a tou dobou také vyšla první stable verze PHP 5. Pochopitelně jsem chtěl na této nové verzi vyvíjet, protože přinesla mnoho novinek, vylepšení a oprav chyb a také snížila TCO a spousta lidí díky ní začala používat jméno Ten mladej, co nám naprogramuje ten náš GPRMPS systém přes noc. Rychlejší chladnutí kávy a rychlejší teplání piva jsou jedny z mála nevýhod a tak je ani raději nebudeme zmiňovat. Návod jsem tenkrát nabídl magaezínu Interval.cz. Stalo se, co se stalo a tak s menším zpožděním na četné žádosti (1+) vychází úplně někde jinde a v jiné (čti svobodné) podobě se spoustou sprostých slov a ASCII porna.
Víte, proč žena při menstruaci vaří na všech plotýnkách? Sakra a proč by prostě nemohla?!
Důvod, proč provozovat PHP 4 a zároveň PHP 5 je vskutku jednoduchý, prostě to tak chceme. Ať už kvůli tomu, že budeme ohýbat staré (čti dříve napsané) aplikace (čti skripty) a zároveň psát nové a ty staré prostě nechceme, nebo nemůžeme upravovat na nové verzi PHP a ty nové, ač můžeme, tak na staré verzi PHP psát nechceme.
Co je lepší než lesba v posteli? Dvě lesby v posteli.
Jeden fyzický server je levnější než dva a dva notebooky se nevejdou do jedné brašny. Toto pochopitelně platí pro vývojové stroje, production server snad nikdo na notebooku neprovozuje, na druhou stranu 23 taky není 9. Jeden fyzický stroj je také vhodný např. pro plynulý převod PHP 4 skriptů na server s PHP 5.
Nevýhoda je jasná už z principu, na jednom stroji běží více procesů, zabírají více paměti a ubírají trochu výkonu. Mě na notebooku běží dva servery Apache, dva MySQL servery a přibude PostgreSQL, takže dvou HTTP serverů bych se nebál. Koneckonců stejně všichni máme ty Intel® Káthmandú procesory s 3,14 GB DDR ECC THC pamětmi, takže to je zívačka.
This behavior is by design.
Tady nevím, čím bych začal, takže to vezmu od lesa. Na systému unixového typu snad každý administrátor dokáže rozjet Apache na jiném portu nebo jiné IP. Na woknech to není tak úplně jasný, proto je návod primárně pro wokna. Tím samozřejmě nevyjadřuji žádné svoje sympatie. Návod by se asi dal použít i pro nějaký unix, dejte mi vědět, jestli to někdo zkusíte a uspějete. Budu vděčný nejenom za zkrácení nebo prodloužení nadpisu. Koneckonců návod je pro wokna i proto, že níže uváděná záplata je zkrátka pro wokna.
It's not how good you are, it's how bad you want it.
Možností jak to celé postavit je pochopitelně několik, to už ostatně je nenásilnou formou naznačeno v úvodu. Některé jsou vhodné, některé nejsou vhodné a některé nejsou vůbec. Mé osobě jich je známých několik, postupně si je pochopitelně představíme. Pokud v budoucnu spatří světlo světa nějaké další způsoby, tento návod bude patřičně aktualizován. Samozřejmě se budeme chtít co nejvíc přiblížit ostrému produkčnímu prostředí, což s woknama zas nebude tak jednoduché, ale to je zanedbatelný detail. Proto ani nebudu uvádět metody typu "spusť tento soubor, když chceš používat PHP 4 a spusť jiný soubor, když PHP 5", s tím se v praxi v produkčním prostředí moc nesetkáte. Jako dodatek uvádím, že budeme instalovat z oficiálních distribucí, žádné takové ty 42-in-1 balíčky.
PHP je nejčastěji nainstalováno jako modul HTTP serveru.
Mohlo by se zdát, že ve chvíli, kdy chceme mít
do serveru zavedené dva PHP moduly, není nic
jednoduššího, než tyto PHP moduly prostě zavést
pomocí LoadModule
direktivy. Ostatně, moduly
takto zavést i jdou, resp. server při zavádění
neohlásí žádnou chybu, jenže vzhledem k tomu,
že oba dva moduly se registrují pod stejný MIME typ
application/x-httpd-php
je potom zcela jasné, že
to zkrátka nebude fungovat korektně. Dřívěji
zavedený modul je přebit zavedením jiného
modulu se stejným MIME typem. Takže když zavedeme nejdříve
PHP 4 modul a pak PHP 5 modul, všechny skripty se budou
zpracovávat PHP 5 modulem.
Ostatně, v tomto smyslu jsem už já sám jeden článek na Interval.cz kdysi publikoval (i když dnes už bych k publikaci takový text asi vůbec nepřijal ;-)
Jak jsme se dozvěděli, dva PHP moduly nejdou nainstalovat
zároveň. Ale dvě CGI verze nainstalovat jdou, mno. Dokonce
jde nainstalovat jeden PHP modul a zbytek PHP nainstalovat jako
CGI. Takže můžeme mít k dispozici v podstatě neomezený
počet PHP verzí. Až na to, že CGI se v ostrém
provozu moc nenosí, krom výkonnostního rozdílu
je zde také určitý rozdíl v dostupných
proměnných a to hlavně v poli $_SERVER
.
TODO UPDATE FIXME http://interval.cz/clanek.asp?article=1740
Svoboda jednoho končí tam, kde začíná svoboda druhého.
Pokud se tedy chceme přiblížit ostrému provozu, je
třeba provozovat dva HTTP servery a v každém mít
zaveden jeden modul PHP. Můj postup předpokládá
instalaci Apache 1.3 pro PHP 4 a Apache 2.0 pro PHP 5. Apache
standradně po instalaci naslouchá na všech dostupných
IP adresách a na portu 80 (direktiva Listen 80
).
Každý server však potřebuje běžet na unikátní
kombinaci IP adresy a portu a tak se nám dva
standardně nakonfigurované servery nespustí. Jeden ze
serverů tedy přesuneme na jiný port, např. na 81.
Přistupovat na něj pak budeme pomocí adresy
http://localhost:81/. Pokud bychom
port neuvedli, HTTP klient (prohlížeč) v tajnosti port
doplní na standardní 80, tak bychom vlastně
přistupovali na úplně jiný server, než bychom si
přáli. Sami jistě uznáte, že to není zrovna
nejpohodlnější, kdo si to má pamatovat, navíc
některé skripty nemusí vůbec počítat s tím,
že mohou být zpracovávány serverem, který
běží na jiném než standardním portu. Tento
postup je víceméně pro úplnost, nějak mě
nenapadá situace, kdy by jeden počítač měl k
dispozici pouze jednu IP adresu – každý počítač,
kde je k dispozici TCP/IP má tzv. lokální smyčku
(angl. loopback device), která může mít více
adres, standardně je dostupná pod IPv4 adresou 127.0.0.1
.
Nicméně vzhůru níže.
Nainstalujeme první Apache se standardní konfigurací. V nastavení služeb systému se přesvědčíme, že Apache neběží, případně jej vypneme, aby nedošlo k případné kolizi s instalací druhého serveru.
Spustíme instalaci druhého Apache, je vhodné
jej nainstalovat do jiného adresáře, než první
server. Opět necháme standardní konfiguraci a opět
se přesvědčíme, že Apache neběží. V konfiguračním
souboru (httpd.conf
) druhého serveru vyhledáme
direktivu Listen
a změníme její
hodnotu:
Listen 81
Tím dosáhneme toho, že Apache po startu bude
naslouchat na všech IP adresách na portu 81. Pokud
provozujeme HTTPS, je třeba adekvátně upravit i direktivy
Listen
pro server s podporou pro SSL – týká
se to portu 443.
Po dokončení konfigurace prověříme její úspěšnost. V nastavení služeb systému spustíme oba Apache servery a počkáme, jestli nenastane konec světa. Poznáme to podle toho, jestli se rozsvítí červený nápis "Všechno je v prdeli", když ne, tak se naše konfigurace povedla. Což si ještě potvrdíme zadáním http://localhost/ a http://localhost:81/ do prohlížeče. V podpisu serveru bychom měli vidět rozdílné verze.
Teď už stačí jen úspěšně nainstalovat PHP 4 do
prvního serveru a PHP 5 (nejlépe z jiného
adresáře) do druhého serveru. Soubor php.ini
pro PHP 4 umístíme do adresáře prvního
serveru tam, kde je soubor Apache.exe
, php.ini
pro PHP 5 do adresáře s konfigurací druhého
serveru tam, kde je httpd.conf
a v tomto souboru
patřičně upravíme direktivu PHPIniDir
:
PHPIniDir "C:/Program Files/Apache Group/Apache2/conf"
PEAR je možné nainstalovat společně do jednoho adresáře. Po restartu HTTP serverů by mělo PHP 4 a PHP 5 fungovat odděleně na dříve uvedených adresách.
Německy? Ani slovo, tak akorát "Ich fahre nach Amsterdam."
Tato možnost je v podstatě to stejné jako předchozí možnost, navíc je doplněna reverzním proxy serverem, který nám odstraní problém s dopisováním portu 81 do URL. Reverzní proxy je v podstatě normální proxy, akorát stojí na druhé straně barikády – tedy pokud možno co nejblíže serveru, dá se použít na spoustu úžasných věcí, jak je popsáno třeba na http://www.root.cz/clanky/reverzni-proxy/.
Zmíním to rovnou na úvodu, na konci to pak ještě zopakuji. Špatně nakonfigurovaný proxy server je nebezpečný jak pro naši vlastní síť, tak pro Internet, jako celek, z důvodů jako jsou XSS útoky, spam apod. Špatně nakonfigurovaný proxy server vyrobíme např. tak, že aktivujeme reverzní proxy, ale zapomeneme vypnout standardní (dopřednou) proxy. V tuto chvíli mlže v podstatě kdokoliv využívat našeho serveru k přístupu na jakékoliv jiné servery na Internetu. Na těchto serverech jsme pak vedeni my, jako ten, kdo na ně přistupoval, což není moc dobré, zvlášť pokud na nich byla vykonána nějaká nekalá činnost. Proto je dobré dopřednou proxy zakázat, viz dále.
Servery tedy nakonfigurujeme tak, jako v předchozím návodu
(tedy tak, aby fungovaly adresy http://localhost/
a http://localhost:81/). Nyní
"aktivujeme" adresu php5.localhost
v souboru hosts
,
který se nachází v adresáři
C:\WINDOWS\system32\drivers\etc
a to tak, že k
existujícím záznamům doplníme tento
řádek:
127.0.0.1 php5.localhost
Tím zajistíme, že první server bude dostupný
i pod adresou http://php5.localhost/,
což na první pohled nedává moc smysl. Na druhý
pohled po pěti pivech už to vypadá lépe, protože si
vzpomeneme, že Apache zvládá virtuální
servery a že tudy asi vede cesta z hospody domů. Takže po
vystřízlivění se pokusíme nastavit první
server tak, aby veškeré požadavky na php5.localhost
protlačoval na druhý server. Nejdříve je pochopitelně
nutné instruovat server, aby nahrál modul zajišťující
požadovanou funkcionalitu, to zajistíme odkomentováním
následujících řádků v konfiguračním
souboru httpd.conf
:
LoadModule proxy_module modules/mod_proxy.so
a učiníme jej aktivním pomocí:
AddModule mod_proxy.c
Dále je třeba povolit virtuální servery rozlišované podle jejich jmen direktivou:
NameVirtualHost *:80
Zjednodušeně řečeno, tím povolíme virtuální servery na portu 80 na všech IP adresách, na kterých Apache naslouchá. Na konec konfiguračního souboru, kde obvykle bývají definice virtuálních serverů, přidáme záznam pro naši reverzní proxy:
<VirtualHost *:80>
ServerName php5.localhost
ProxyPass / http://localhost:81/
ProxyPassReverse / http://localhost:81/
</VirtualHost>
ServerName
specifikuje jméno virtuálního
serveru, ProxyPass
pak aktivuje reverzní proxy –
veškeré požadavky (protože každý požadavek začíná
kořenem) budou "přeposílány" na server bežící
na adrese localhost na portu 81, tedy na server, kde běží
PHP 5. Požadavek na http://php5.localhost/foo/bar
bude prvním serverem vnitřně přesměrován na
http://localhost:81/foo/bar.
Adresa s portem 81 bude fungovat i při přímém zadání
do prohlížeče, pochopitelně. ProxyPassReverse
pak zajistí zpětný překlad těch HTTP hlaviček
Location, které v sobě nesou adresu druhé serveru na
portu 81.
Při provozování reverzního proxy serveru je
velice vhodné zakázat normální proxy, to
provedeme pomocí direktivy ProxyRequests
, kterou
umístíme do podmíněného bloku tak,
abychom mohli server nastartovat i bez zavedeného modulu pro
proxy servery:
<IfModule mod_proxy.c>
ProxyRequests Off
</IfModule>
Tento blok umístíme někam před začátek sekce
definující virtuální servery, tedy někam
před komentáře uvedené před direktivou
NameVirtualHost
.
Podobné funkcionality lze dosáhnout pomocí
modulu mod_rewrite, resp. speciálního příznaku
proxy
(nebo P
). Nicméně stále
tu platí podmínka, že musí být zaveden
modul pro proxy server mod_proxy, stejně jako v předchozím
případě, takže postup přes mod_rewrite v podstatě jen
umožňuje mocnější implementaci reverzního proxy
serveru, čehož my nevyužijeme. Je také třeba nezapomenout
na zakázání standardní proxy pomocí
ProxyRequests Off
. Pravidlo pro přepis URL pro
virtuální server php5.localhost
by pak
mohlo vypadat následovně:
RewriteRule ^/(.*) http://localhost:81/$1 [P]
Instalace PHP do obou serverů probíhá tak, jak je popsáno v návodu, kdy se používají dva porty.
Slunce se skládá se dvou rozsáhlých částí, z nichž ani jedna není za normálních okolností vidět. Ale ta vnější bude vidět 29. března 2006 v Turecku.
Jak jsem již uvedl, každý server musí běžet na
unikátní kombinaci IP adresy a portu. Pokud tedy
chceme provozovat dva HTTP servery (což musíme kvůli
instalaci dvou PHP modulů) a nechceme dopisovat do URL port
a nechceme ani provozovat reverzní proxy server, nezbývá
nám nic jiného, než spustit každý server na
jiné IP adrese. Na jakých, to záleží na
situaci, ve které jsme. Adresu 127.0.0.1
máme
k dispozici vždy, nevýhoda je ta, že je pouze lokální,
nelze na ni přistoupit z jiných počítačů. Pokud
máme do počítače zavedenu jednu veřejnou IP adresu,
pak máme možnost obsah jednoho serveru zobrazovat i ven
(pokud chceme ven obsah obou serverů, pak musíme použít
předchozí způsob s reverzní proxy). Pokud je do
počítače zavedeno více veřejných IP adres (a
to klidně i na jednu síťovou kartu), není problém
každý server spustit na jedné veřejné IP
adrese a můžeme bez problémů (a bez reverzní
proxy) zobrazovat obsah obou serverů celému světu. V
následujícím textu budeme předpokládat,
že nechceme světu nic ukazovat, nebo že počítač nemá
žádnou veřejnou adresu, nebo že veřejná adresa
počítače se mění v čase, ať už díky tomu,
že je počítač přenášen ze sítě do sítě,
nebo adresu mění poskytovatel připojení. Rozhodně
tedy situace bude vypadat tak, že jeden server bude spuštěn na
adrese 127.0.0.1
a druhý na 127.0.0.2
.
Windows XP se Service Pack 2 standardně povolí přístup
pouze na první zmiňovanou adresu, je tedy potřeba speciální
update, který povolí připojení i na ostatní
adresy v rozsahu lokální smyčky. Tento update má
číslo 884020 a lze jej stáhnout z
http://support.microsoft.com/kb/884020/.
Je potřeba jej nainstalovat před spuštěním druhého
serveru.
Nainstalujeme tedy první server, ve službách
systému se přesvědčíme, že není spuštěn,
případně službu zastavíme. Nainstalujeme druhý
server a opět zajistíme, aby nebyl spuštěn. Nyní
se vrhneme na konfiguraci prvního serveru, otevřeme tedy
soubor httpd.conf
, najdeme ten správný
řádek a nastavíme, aby server naslouchal na té
správné adrese:
Listen 127.0.0.1:80
To samé provedeme v konfiguračním souboru druhého serveru, jen řádek bude vypadat trochu jinak:
Listen 127.0.0.2:80
Poté ve službách systému oba dva servery
spustíme. Do prohlížeče zadáme zkušebně
http://127.0.0.1, měl by nám
odpovědět první server a http://127.0.0.2,
měl by odpovědět druhý server. Ty čísla nejsou
zrovna moc přívětivá a tak si je trochu
polidštíme. V souboru hosts
je již uveden
záznam pro první adresu (localhost
), takže
stačí přidat záznam pro tu druhou:
127.0.0.2 php5.localhost
Nyní by tedy servery měly být dostupné pod adresami http://localhost/ a http://php5.localhost/.
Instalace PHP do serverů probíhá stejně tak, jak je popsáno v návodu, kdy se používají dva porty.
Nejdůležitější nástroj hackera je vypalovačka.
Tato poslední možnost je určena pro experimentátory,
spočívá v úpravě zdrojových kódů
PHP, případně v úpravě binární
distribuce. Oficiálně jsem ji nikde neviděl uváděnou,
takže spíš pro zajímavost, je možné, že
změna má nějaké vedlejší účinky. Oba
dva moduly PHP si registrují stejný MIME typ
application/x-httpd-php
, takže je celkem problém
rozlišit jeden od druhého. úprava tedy spočívá
ve změně typu jednoho modulu na něco jiného a modul s
takto upravným typem pak bude zpracovávat soubory
určené např. pro PHP 4, zatímco modul s původním
typem pak soubory určené pro PHP 5. Přiřazení je
možné provést pomocí direktivy AddType
na úrovni přípon souborů, virtuálních
serverů nebo na úrovni adresářů.
TODO UPDATE FIXME http://forum.builder.cz/read.php?20,991619,994783#msg-994783