Słowem wstępu, moja historia z PHP pod Windows jest długa i dość kręta. Jej podstawą są wieloletnie doświadczenia z hostowaniem pod Windows Server serwisu dobreprogramy, który obecnie znajduje się w zestawieniu dwudziestu największych witryn w Polsce. Nie chodzi o to, by się chwalić, ile by zilustrować skalę problemu - ponad 5 milionów użytkowników miesięcznie i niemal 40 mln odsłon stron to niebagatelny ruch. Generowany przez wywołania do aplikacji napisanych w PHP i hostowanych pod Windows Server 2003 oraz 2008. Chcecie posłuchać?
Początki nie były łatwe i dopiero z czasem wypracowaliśmy konfigurację, która jest zarówno wydajna, jak i niezawodna. Możliwości obsługi PHP pod IISem (czy to 6, czy to 7) jest bowiem kilka.
Podstawowa, najprostsza, to wykonanie dla każdego wywołania GET do pliku z rozszerzeniem .php interpretera PHP-CGI.exe. Genialne w swojej prostocie, nadaje się niestety tylko do wywołania phpinfo() i niewiele więcej - obciążenie generowane przez taki model nawet przy niewielkich aplikacjach jest w stanie zabić całkiem niezłą maszynę i nikt przy zdrowych zmysłach czegoś takiego nie używa.
Druga opcja to wtyczka ISAPI (php5isapi.dll), która działa znacznie, znacznie wydajniej, ma jednak dość poważną wadę. Środowisko PHP nie było projektowane z myślą o pracy z wielowątkowym serwerem WWW - takim, którego jeden proces roboczy w ramach jednej przestrzeni wykonywania uruchamia wiele skryptów. Wtyczka ISAPI jednak się pojawiła, a nieco później autorzy PHP wydając wersję 5.2.0 ogłosili, że wbudowali dla niej odpowiednie zabezpieczenia - owocem czego PHP dla Windows zaczęło być dostępne w dwóch kompilacjach, NTS (non-thread-safe) oraz drugiej teoretycznie przeznaczonej do pracy wielowątkowej. Teoretycznie, bowiem można to było między bajki włożyć - przy większym obciążeniu na wielu wątkach całość malowniczo demolowała pulę aplikacji zwracając komunikat PHP has encountered an access violation at.... Niektórych użytkowników tak poirytowała ta sytuacja, że zaczęli ostrzegać - nie wierzcie w kłamstwa, PHP nie jest jeszcze wielowątkowe.
Efektem problemów z wydawałoby się najlepszym modelem ISAPI był powrót do korzeni i opracowanie mechanizmu FastCGI. To koncepcja stara jak świat, która pozwala buforować wywołania PHP-CGI.exe - proces roboczy IISa uruchamia i trzyma w gotowości wiele jednowątkowych procesów PHP-CGI.exe, po czym kieruje do nich przychodzące wywołania plików .php. Działa lepiej, bo nie trzeba uruchamiać co chwilę PHP-CGI.exe i trzeba przyznać, że działa nawet całkiem nieźle. Nieźle, czytaj stabilnie - bo wydajność, mimo że o niebo lepsza niż zwykłego modelu CGI, nie jest wcale imponująca. Model ze względu na swoją stabilność doczekał się implementacji w bezpłatnym rozwiązaniu Zend Core - gotowym pakiecie instalującym niezawodne i wydajne PHP pod Windows, w którego przygotowaniu i dostrojeniu maczał ostatnio palce także i Microsoft.
Model FastCGI okazał się na tyle obiecujący, że postawił na niego nie tylko Zend, ale i ostatecznie sam Microsoft wydając wtyczkę FastCGI własnej produkcji. Wtyczka, dostępna początkowo jako rozszerzenie dla IIS 6 oraz 7, trafiła ostatecznie do systemu jako bazowy komponent Service Packa 1 do Visty oraz Windows Server 2008. Pozwoliła firmie w duchu modnej ostatnio interoperacyjności ogłosić, że w pełni wspiera ona PHP pod Windows Server. Tada! Problem w tym, że sprawdziliśmy to przy ostatnich aktualizacjach Windows Server 2003 do 2008 - jedna wielka lipa, proszę państwa. Bo owszem, niby chodzi, mamy nawet ładną instrukcję autorstwa pracowników Microsoft jak to poprawnie skonfigurować (w oparciu o PHP w kompilacji NTS), tylko że są z tym same problemy. Pod 64-bitowym Windows Serverem każdy proces recyclingu puli kończy się serią awarii procesów IISa, a przy włączonym module xcache (niezbędnym w większych instalacjach prekompilatorze skryptów PHP znacznie podnoszącym ich wydajność) całkowitą destabilizacją puli obsługującej aplikację PHP. Dobre to zatem najwyżej do hostowania strony domowej ze zdjęciami z imprez rodzinnych i to pod warunkiem, że rodzinę mamy małą co obciążenia dużego nam nie wygeneruje.
Mimo tych problemów - w szczególności z destabilizacją puli aplikacji w 64-bitowych edycjach Windows Server - Microsoft brnie w ten model dalej wprowadzając poprawki do FastCGI, które zadebiutują wraz z IIS 7.5 w Windows Server 2008 R2. Osobiście nie podchodzę do tego z wielkim entuzjazmem.
W między czasie, cichaczem, twórcy PHP robili dalej swoje - poprawiali zabezpieczenia PHP pozwalające mu na pracę wielowątkową. Poprawiali, poprawiali, aż w końcu.. udało się - w moim przekonaniu mniej więcej w okolicy wersji 5.2.6. W chwili obecnej uważam, że najbardziej wydajny i niezawodny model obsługi PHP pod Windows Server to wcale nie FastCGI, jak zapewnia Microsoft, a pobranie najnowszej kompilacji thread-safe i podpięcie jej uznanym za mało stabilny modelem ISAPI - uruchamiamy konsolkę zarządzania IIS, wchodzimy w opcję Handler Mappings, uruchamiamy opcję Add Script Map, wskazujemy dla rozszerzenia *.php wtyczkę php5isapi.dll i po krzyku. No, prawie po krzyku, bo w praktyce warto jeszcze zajrzeć do PHP.ini i dostroić kilka rzeczy, warto też podpiąć jeden z tzw. akceleratorów prekompilujących jak np. wspomniany xcache. To naprawdę działa wydajnie i niezawodnie - i to nie tylko na testowych wywołaniach phpinfo(), a obsługuje nam obecnie bez większych problemów węzły klastra NLB hostujące dobreprogramy pod IISami 6 oraz pod IISami 7 oprogramowanie adserwerowe.
Szkoda, że nie można powiedzieć tego samego o Microsoftowej implementacji FastCGI...