Ostatnio natknąłem się na coś zwane spawn-fcgi, w skrócie jest to programik który odpowiada za uruchomienie serwera fcgi (pierwszy z brzego przykład: PHP) z zadanym userem, grupą, ew. chroot na danym ip/porcie, lub sockecie unixowym. W swojej idei pomyślany był jako sposób żeby lighttpd mógł uruchamiać PHPa z innym userem niż ten na którym sam pracuje (trochę tak jak apache + mod_fastcgi + suexec), ale bez żadnych SUIDów (którego admini jednak unikają z dobrych powodów) i skomplikowaniej konfiguracji (bo podłączenie się do niego z lightego to jedna linijka configa).

I jakby nie spojrzeć spisuje się świetnie, ale że jest napisany jako uniwersalny “klocek” to nie jest jedyne jego zastosowanie. Po podłączeniu go do apacha i odpalenia prostego benchmarku (ab -c 32 -n 200000 na malutkim phpie zeby sprawdzic szybkosc “wchodzenia i wychodzenia” z phpa) rezultaty były ciekawe, ponieważ apache + spawn-fcgi był szybszy od lightego (zarowno z “wbudowanym fcgi jak i z spawn-fcgi) i apacha z mod_php o jakies 15-20% (YMMV, testowany był tylko na malutkim skrypcie więc im dłużej wykonuje się wasza aplikacja PHPowa tym różnica będzie mniejsza, w RL pewnie z 2, góra 5%), więc pomyślałem że warto byłoby opisać instalację tego, zwłaszcza że jest jeden niemiły “bug” z którym poradzenie sobie zajęło mi chwilę.

1.Instalacja:

  • Ściągamy i kompilujemy spawn-fcgi (starsza wersja jest w pakiecie lighttpd w debianie, ale nowsza potrafi zmieniać uprawnienia socketu a to jest coś czego potrzebujemy)
  • Podstawowa instalka apacha + daemontools (do startowania spawn-fcgid

    aptitude install apache2-mpm-worker php5-cgi daemontools daemontools-run

  • Tworzymy katalog na sockety, ja wybrałem /var/run/apache2/php

  • Czas odpalić spawn-fcgid, tworzymy katalog /etc/service/php-user1 a potem plik /etc/service/pgp/user1/run :

    #!/bin/sh
    USER=app01
    PROC=16 #liczta phpow do spawniecia
    rm -f /var/run/apache2/php/$USER-php5.fcgi
    exec /usr/local/bin/spawn-fcgi -n -U www-data -M 0600 -u app01 -g www-data -C $PROC -s /var/run/apache2/php/$USER-php5.fcgi -f /usr/bin/php5-cgi

  • ps aux i szukamy czy nasze phpiki się odpaliły ;] Co do opcji powyżej, -u i -g to user i grupa do odpalenia serwera fcgi,  -U i -G to user i grupa socketu -M to uprawnienia socketu. Soft obsługuje też tryb tcp, oszczędza trochę roboty (nie trzeba sprzątać ;]) ale jeżeli php jest lokalnie to tcp jest marnotrawstwem procka ;]

  • Czas na apacha, uruchamiamy mod_fastcgi (nie wiem jak gdzie indziej, w debie a2enmod fastcgi ), wchodzimy do naszego vhosta i dodajemy:

    AddHandler php5-script .php
    AddType application/x-httpd-fastphp5 .php
    Action application/x-httpd-fastphp5 /jakies-nieistniejace-cos
    Action php5-script /jakies-nieistniejace-cos
    FastCgiExternalServer /var/www/nasz_app/jakies-nieistniejace-cos -socket /var/run/apache2/php/app01-php5.fcgi -pass-header HTTP_AUTHORIZATION

I teraz pewnie co niektórzy będą się zastanawiać wtf is*** jakies-nieistniejace-cos ***(i slusznie). Otóż, autorzy mod_fastcgi zrobili coś źle i gdy użyjesz “FastCgiExternalServer /var/www/app” fastcgi wysle wszystkie żądania kierujace na /var/ww/app do serwera fastcgi, kompletnie olewając wszelkie inne opcje Apacha (czyli np gify będą szły do php-cgi a puste stony beda zwracane komunikatem interpretera phpa ze nie znalazl pliku), czego raczej nie chcemy.

Więc ten kawałek kodu mówi fastcgi ze scieżka na której ma “działać” jest /nasz/app/wyimagionwane-cuś a potem każe plikom php działać przez */nasz/app/wyimaginowane-cuś.* Grzebanie w necie i apachu zajęło mi trochę zanim do tego doszedłem ale w końcu działa całkiem ładnie ;]. Chociaż rozwiązanie od strony apacha trochę “brzydkie” ale konkurencja (mod_fcgid) nie potrafi podłączać się do “zdalnego” fcgi wcale więc dużego wyboru nie ma ;]

Zalety:

  • Separacja uprawnień
  • Możliwośc restartu/upgrade Apacha bez restartu PHPa (czyszczenia opcode cache itd.)
  • Szybkość (separacja uprawnień przez “standardowy” suexec jest wolna a suexec + fastcgi jest jeszcze bardziej skomplikowany w konfiguracji), przynajmniej u mnie był szybszy od mod_php i od lighttpd

Wady

  • Trochę roboty w ustawianiu wszystkiego na początku
  • Każdy nowy “user” wymaga oddzielnego spawn-fcgi (ale przy odpowiednim skrypcie startowym jest to prawie “copy-paste”)