About :: Projects :: Articles :: JBlog.getInstance()

Запуск Movable Type через Fast CGI под Apache

[an error occurred while processing this directive]

Запуск Movable Type через Fast CGI под Apache @ 11.01.2006 18:34

Введение

Итак, здесь я расскажу, как запускать backend Movable Type'а в режиме FastCGI, вместо просто CGI. Для начала — различия между CGI и FastCGI. Предположим, что у вас работает форум на Perl через обычный CGI. Посетитель заходит к вам по адресу viewtopic.cgi?id=666. Что при этом происходит:

  1. Создается процесс для обработки viewtopic.cgi
  2. perl-интерпритатор читает viewtopic.cgi и парсит его в некоторую структуру, затем начинает исполнять
  3. viewtopic.cgi читает конфигурационный файл форума
  4. viewtopic.cgi подсоединяется к БД
  5. viewtopic.cgi делает SELECT * FROM messages WHERE topic_id=$GET{id}
  6. viewtopic.cgi закрывает соединение с БД

Много, не правда ли, учитывая то, что шаги 1-4 абсолютно идентичны у всех запросов вида viewtopic.cgi?id=*. Как раз эту проблему и решает Fast CGI: viewtopic.fcgi будет запускаться один раз и висеть в памяти отдельным процессом, делать шаги 1-3 при запуске, а далее обрабатывать запросы по мере необходимости. Пример простейшего fcgi скрипта:

#!/usr/bin/perl -w
   use FCGI;
   my $req_count = 0;
   my $request = FCGI::Request();
   while($request->Accept() >= 0) 
   {
      print("Content-type: text/html\r\n\r\n", ++$req_count);
   }

Ясно, что использование fast CGI может существенно ускорить выполнение приложения.

Запуск MT через FastCGI

А теперь, про то, как запустить MovableType через FastCGI под Apache. Сразу отмечу, что данный способ работает только для MT 3.2 и выше.

Для начала проверьте, поддерживается ли у вас FastCGI. Если у вас виртуальный хостинг — то скорее всего нет, хотя есть и исключения (в первую очередь, хостинги, где поддерживается Ruby On Rails, например Dreamhost или Textdrive). Если у вас свой сервер, то все в ваших руках — надо просто установить mod_fcgi.

Затем создаете .htaccess в домашней директории MT (если его там еще нет) и впишите туда следующие строки:

AddHandler fastcgi-script .fcgi
FastCGIConfig -autoUpdate -idle-timeout 120 -killInterval 3600 -maxClassProcesses 3 -maxProcesses 15

Далее создайте mt.fcgi в, опять же, домашней директории MT и поместите туда следующий код:

#!/usr/bin/perl -w
use lib "lib";
$ENV{"PERL5LIB"} = "/PATH_TO_MT/lib";
$ENV{"MTHOME"} = "/PATH_TO_MT";
$ENV{"MTCONFIG"} = "/PATH_TO_MT/mt-config.cgi";

use strict;
use MT::Bootstrap;
use CGI::Fast;

# preload app packages
use MT::App::CMS;
use MT::App::Comments;
use MT::App::Trackback;
use MT::App::Search;
## расскомментируйте эти строки если вы только используете 
## AtomAPI. Данный модуль жрет много памяти т.к. загружает
## LibXML
##use MT::AtomServer;


my $handlers = {
    'mt.fcgi' => { class => 'MT::App::CMS', name => 'AdminScript' },
    'mt-comments.fcgi' => { class => 'MT::App::Comments', name => 'CommentScript' },
    'mt-tb.fcgi' => { class => 'MT::App::Trackback', name => 'TrackbackScript' },
    'mt-search.fcgi' => { class => 'MT::App::Search', name => 'SearchScript' },
##  См. комментарий выше
##    'mt-atom.fcgi' => { class => 'MT::AtomServer', name => 'AtomScript' },
};

eval {
    while (my $q = new CGI::Fast) {
        my $cgi = $q->script_name;
        $cgi =~ s!.*/!!;
        my $pkg = $handlers->{$cgi}{class};
        die "Invalid handler for $cgi" unless $pkg;
        my $app = $pkg->new(CGIObject => $q) or die $pkg->errstr;
        local $SIG{__WARN__} = sub { $app->trace($_[0]) };
        $app->init_request(CGIObject => $q) unless $app->{init_request};
        fixup_script_names($app);
        $app->run;
        my $mode = $app->mode || '';
        if ("$pkg->$mode" eq 'MT::App::CMS->plugin_control') {
            exit; # allows server to recycle after changing plugin switches
        }
    }
};
if ($@) {
    print "Content-Type: text/html\n\n";
    print "Got an error: $@";
}

sub fixup_script_names {
    my ($app) = @_;
    $app->config($handlers->{$_}{name}, $_) foreach keys %$handlers;
}

Замените /PATH_TO_MT на абсолютный путь к вашему MT.

Сделайте

chmod a+x mt.fcgi 
ln mt.fcgi mt-comments.fcgi
ln mt.fcgi mt-tb.fcgi
ln mt.fcgi mt-search.fcgi
ln mt.fcgi mt-view.fcgi
ln mt.fcgi mt-atom.fcgi

Зайдите в mt-config.cgi и впишите туда следующие строки

AdminScript mt.fcgi
CommentScript mt-comments.fcgi
TrackbackScript mt-tb.fcgi
SearchScript mt-search.fcgi
XMLRPCScript mt-xmlrpc.fcgi
ViewScript mt-view.fcgi
AtomScript mt-atom.fcgi
UpgradeScript mt-upgrade.fcgi

В принципе все должно заработать. Однако, это Perl и скорее всего будет не хватать каких-нибудь модулей. Проверить это, можно зайдя на сервер по SSH и сказав perl mt.fcgi. Если на экран выпадет html, то все модули у вас установлены и вы можете дальше не читать, если же будут ошибки, то добро пожаловать в CPAN

Установка дополнительных модулей

mt.fcgi требует CGI::Fast, который, в свою очередь, требует FCGI. CGI::Fast входит в дистрибутив MT (лежит в extlib), а вот FCGI нет. К тому же, FCGI требует компиляции. Короче, засада полная. Делать надо так:

  • Качать FCGI, распоковывать
  • Зайти в директорию с дистрибутивом, сказать:
    mkdir ~/perllib
    perl Makefile.PL prefix=~/perllib
    make
    make install
    Далее в недрах ~/perllib надо найти FCGI.pm и FCGI.so (у меня они лежали по адресу ~/perllibs/lib/perl/5.8.4/FCGI.pm и ~/perllibs/lib/perl/5.8.4/auto/FCGI/FCGI.so) и скопировать их в PATH_TO_MT/extlib. (Если кто из читателей подскажет более правильный алгоритм сборки, т.е такой, который создасть FCGI.pm и FCGI.so сразу в extlib, буду благодарен, а то в Perl'е я совсем не разбираюсь)

В принципе все, после этих действий MT через Fast CGI у меня заработал. Если у вас что не так — пишите в комментарии, постараюсь разобраться

Ccылки

Не думайте, что это я такой умный. Более половины данного текста это сборный перевод трех англоязычных статей на тему:
[ Permalink ]
<< JavaScript Obfuscate It >>
  © Vladimir Klimontovich; modified: Tuesday, 30-May-2006 23:27:39 PDT