Я давно пользуюсь веб-сервером Lighttpd и часто замечаю, что этот веб-сервер часто незаслуженно обходят стороной, отдавая предпочтение его более популярным коллегам nginx и Apache. У меня он давно заменил собой Apache, а об использовании nginx я даже не особо задумывался, потому что по принципу работы он похож на Lighttpd, а по возможностям, кажется, ни в чём ему не уступает.
Хочу показать некоторые из его возможностей, которыми я пользуюсь уже более четырёх лет. Возможно этот пост поможет кому-то посмотреть на Lighttpd как на альтернативу вышеозначенным серверам и предоставит начальные сведения, необходимые для того, чтобы начать им пользоваться.
Настройка псевдонимов каталогов. Часто веб-приложения устанавливаются в каталог, отличный от корня документов веб-сервера. Чтобы такие веб-приложения заработали, нужно включить и настроить модуль mod_alias:
server.modules += ( "mod_alias" ) alias.url += ( "/munin/" => "/var/cache/munin/www/", "/cacti/" => "/usr/share/cacti/site/", "/dokuwiki/" => "/usr/share/dokuwiki/", "/wordpress/" => "/usr/share/wordpress/", "/awstats/cgi-bin/" => "/usr/lib/cgi-bin/", "/awstats/docs/" => "/usr/share/doc/awstats/html/", "/awstats/icon/" => "/usr/share/awstats/icon/", "/awstats/css/" => "/usr/share/awstats/css/", "/awstats/classes/" => "/usr/share/awstats/classes/", "/postfixadmin/" => "/usr/share/postfixadmin/", "/mail/" => "/usr/share/squirrelmail/" )
Чтобы выдавать пользователям с разными IP-адресами разное содержимое, можно воспользоваться условными блоками:
$HTTP["remoteip"] =~ "10.0.0." { alias.url += ( "/wpad.dat" => "/var/www/wpad-office.dat" ) } $HTTP["remoteip"] =~ "10.0.1." { alias.url += ( "/wpad.dat" => "/var/www/wpad-agency.dat" ) }
Чтобы защитить некоторые каталоги сайта паролем, можно воспользоваться модулем mod_auth (я обычно использую бэкенд htdigest):
server.modules += ( "mod_auth" ) auth.backend = "htdigest" auth.backend.htdigest.userfile = "/etc/lighttpd/htdigest" auth.require = ( "/RPC2" => ( "method" => "digest", "realm" => "rTorrent RPC", "require" => "user=rtorrent" ), "/stat/" => ( "method" => "digest", "realm" => "lightsquid statistics", "require" => "valid-user" ), "/postadmin/" => ( "method" => "digest", "realm" => "postadmin", "require" => "valid-user" ) )
Для управления файлом паролей в Debian можно установить пакет apache2-utils, в нём есть программы htpasswd для управления файлом паролей для бэкенда plain и htdigest для управления файлом паролей бэкенда htdigest.
Почитайте документацию - модуль mod_auth позволяет брать пользователей из каталога LDAP (в том числе Active Directory).
К примеру, вот так создаётся файл паролей с одним новым пользователем:
$ htdigest -c /etc/lighttpd/htdigest "realm text" user
Для добавления новых пользователей в уже существующий файл нужно воспользоваться той же командой, но без опции -c:
$ htdigest /etc/lighttpd/htdigest "realm text" user
Для запуска классических CGI-скриптов можно воспользоваться модулем mod_cgi:
server.modules += ( "mod_cgi" ) $HTTP["url"] =~ "^/cgi-bin/" { cgi.assign = ( "" => "" ) } cgi.assign = ( ".py" => "/usr/bin/python", )
В этом примере опять используется условный блок, однако на сей раз условие зависит от URL запрошенного файла. В этом примере для всех файлов, находящихся в каталоге /cgi-bin/ веб-сервера, осуществляется их запуск. Выбор интерпретатора для скриптов осуществляется по первой строчке скрипта, она должна начинаться с символов #! (she-bang) с последующим полным путём к интерпретатору. Для остальных файлов с расширением .py осуществляется их запуск в интерпретаторе языка Python.
Протокол FastCGI является логическим продолжением идеи CGI. Процесс, работающий по этому протоколу, запускается однажды и обрабатывает несколько последовательных запросов без перезапуска. Этот подход позволяет сэкономить ресурсы на чтение сценария, его трансляцию во внутренне представление интерпретатора, на инициализацию структур данных, необходимых для обработки каждого запроса - все эти этапы выполняются только один раз - при запуске процесса.
server.modules += ( "mod_fastcgi" ) fastcgi.server = ( ".php" => ( ( "host" => "10.0.0.1", "port" => 8080, ), ( "bin-path" => "/usr/bin/php5-cgi", "socket" => "/tmp/php.socket", "max-procs" => 2, "idle-timeout" => 20, "bin-environment" => ( "PHP_FCGI_CHILDREN" => "4", "PHP_FCGI_MAX_REQUESTS" => "10000" ), "bin-copy-environment" => ( "PATH", "SHELL", "USER" ), "broken-scriptfilename" => "enable" ) ), "/fcgi.pl" => ( ( "bin-path" => "/var/www/fcgi.pl", "socket" => "/tmp/fcgi-pl.socket", "max-procs" => 2, "idle-timeout" => 20, "bin-copy-environment" => ( "PATH", "SHELL", "USER" ), "broken-scriptfilename" => "enable" ) ) )
В этом примере обработкой файлов с расширением .php занимаются два бэкенда. Один бэкенд автономный, расположен на удалённом компьютере с IP-адресом 10.0.0.1 на порту 8080. Второй бэкенд управляется самим сервером Lighttpd, который порождает новые процессы FastCGI, когда они нужны, перезапускает их, когда они отработают заданные 10000 запросов и уничтожает их избыточное количество по истечении установленного времени простоя. Доступ к порождаемым процессам осуществляется через UNIX-сокеты.
Ещё один бэкенд является полноценным FastCGI-приложением на Perl. Он тоже управляется Lighttpd, доступ тоже осуществляется через UNIX-сокеты.
Для управления автономными FastCGI-серверами можно воспользоваться менеджером процессов из пакета spawn-fcgi, который умеет порождать, перезапускать и убивать процессы FastCGI. Для запуска этого менеджера процессов можно воспользоваться следующим сценарием инициализации:
#!/bin/sh ### BEGIN INIT INFO # Provides: spawn-fcgi-php # Required-Start: $all # Required-Stop: $all # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: starts FastCGI for PHP # Description: starts FastCGI for PHP using start-stop-daemon ### END INIT INFO PATH=/sbin:/bin:/usr/sbin:/usr/bin NAME=spawn-fcgi-php-user1 PID=/var/run/spawn-fcgi-php-user1.pid DAEMON=/usr/bin/spawn-fcgi DAEMON_OPTS="-f /usr/bin/php-cgi -a 10.0.0.1 -p 8080 -u user1 -g user1 -P $PID" test -x $DAEMON || exit 0 set -e case "$1" in start) echo "Starting $NAME: " start-stop-daemon --start --pidfile $PID --exec $DAEMON -- $DAEMON_OPTS echo "done." ;; stop) echo "Stopping $NAME: " start-stop-daemon --stop --pidfile $PID --retry 5 rm -f $PID echo "done." ;; restart) echo "Stopping $NAME: " start-stop-daemon --stop --pidfile $PID --retry 5 rm -f $PID echo "done..." sleep 1 echo "Starting $NAME: " start-stop-daemon --start --pidfile $PID --exec $DAEMON -- $DAEMON_OPTS echo "done." ;; *) echo "Usage: /etc/init.d/$NAME {start|stop|restart}" >&2 exit 1 ;; esac exit 0
Этот сценарий породит менеджер процессов для запуска файлов PHP от имени пользователя user1. FastCGI-бэкенд будет доступен на IP-адресе 10.0.0.1, на порту 8080.
Я предпочитаю использовать именно spawn-fcgi, а не php-fpm, т.к. первый является, на мой взгляд более надёжным, потому что в полной мере проповедует модульный подход к построению программного обеспечения. Похоже, я не одинок, и разработчики Debian придерживаются точно такого-же мнения, избегая включать php-fpm в стабильный дистрибутив Debian.
Хочу отметить, что выполнение сценариев PHP в режиме FastCGI не столь эффективно, каким могло бы быть. Это связано с тем, что файл PHP, хоть и не требует повторного запуска интерпретатора и трансляции кода выполняемого скрипта, но выполняется каждый раз от начала и до конца, включая код инициализации и деинициализации. При обработке каждого нового запроса заново открываются подключения к базам данных, осуществляется чтение файлов конфигурации, загрузка шаблонов HTML-страниц.
Чтобы проиллюстрировать сказанное, а заодно и закончить рассмотрение модуля mod_fastcgi, приведу пример простейшего FastCGI-приложения на Perl с использованием модуля CGI::Fast:
#!/usr/bin/perl -w use strict; use CGI::Fast; # Инициализация: загрузка ресурсов, # установка подключения к БД my $counter = 0; while(my $q = CGI::Fast->new) { $counter++; print "Content-Type: text/html\n\n"; print "Я обработал $counter запросов!\n"; my %params = $q->Vars; while (my ($k, $v) = each %params) { print "$k = $v\n"; } } # Закрытие ресурсов / подключений
Запросы обрабатываются строго поочерёдно. Для ускорения обработки запросов и нужен менеджер процессов, который породит оптимальное количество FastCGI-процессов и распределит между ними нагрузку. Он же должен убивать простаивающие процессы или перезапускать процессы, обработавшие определённое максимальное количество запросов - во избежание утечки памяти.
Пример на Perl взят отсюда: Связка Nginx + Пускач + FastCGI на Perl. На том же сайте можно почитать подробнее о том, что собой представляет FastCGI изнутри.
SCGI похож на FastCGI и хотя менее популярен, всё же используется в некоторых приложениях. Например, программа rtorrent работает как сервер SCGI, позволяя управлять собой с использованием этого протокола. Этим пользуется, например, веб-интерфейс rutorrent. Пример их настройки можно посмотреть здесь: rtorrent + rutorrent. Краткий пример настройки модуля mod_scgi именно для этого случая приведён ниже:
server.modules += ( "mod_scgi" ) scgi.server = ( "/RPC2" => ( "127.0.0.1" => ( "host" => "127.0.0.1", "port" => 5000, "check-local" => "disable", "disable-time" => 0 # don't disable scgi if connection fails ) ) )
У веб-сервера Lighttpd имеется много других модулей, среди которых есть, например mod_rewrite, mod_proxy, о которых можно прочитать в документации, поставляемой в комплекте с самим веб-сервером или на вики-странице разработчиков: http://redmine.lighttpd.net/projects/lighttpd/wiki.