тел/факс (473) 2000-257 Интересные ресурсы чехия недвижимость .
|
|

Главная
Разработка сайта
Создание больших проектов 
Создание больших проектов |
|
У любого успешного web-проекта рано или поздно возникает проблема роста. Существующие программно-аппаратные ресурсы перестают справляться с растущей нагрузкой. Универсальных рецептов, к сожалению не существует. В каждом проекте хороший программист будет программировать по-разному. Тем не менее, в этой статье я попробую дать несколько типичных рекомендаций по созданию больших web-проектов. Такие проекты в процессе создания и развития сталкиваются, как правило, с двумя почти противоположными по способам решения проблемами - большими скоростями и большими объемами данных. Большие скорости В качестве идеального примера сайта, для которого жизненно важна скорость, можно взять баннерную сеть. Итак, несколько приемов для ускорения работы баннерных сетей и других серверов, критичных к скорости работы. Создание модулей Смысл этого приема - вкомпилировать наиболее важные функции в сервер. Идея очень проста. Если мы посмотрим на соотношение времени, которое тратится на различные стадии выполнения запроса, то увидим интересную картину. Например, при выполнении простейшего perl-скрипта последовательно происходит следующее: 1) сервер Apache определяет perl-скрипт для запуска, подготавливает и запускает его; 2) запуск скрипта фактически начинается с запуска perl-интерпретатора (это файл, размером около полумегабайта). Perl-интерпретатор, запустившись, размещается на 2-х мегабайтах в памяти машины, и только после этого приступает к работе с пользовательским скриптом; 3) эта работа начинается с компиляции программы. Компиляция программы - это, как правило, один из самых длительных этапов обработки программы; 4) только после предварительной компиляции (в байткод) скрипт начнет выполняться. Статистика удручает: время, которое тратится на запуск perl-интерпретатора и компиляцию скрипта, как правило, на порядок больше времени, за которое он выполняется. На каждом сайте существуют узкие места - программы, которые вызываются очень часто. Например, баннерный движок. Как правило, на один просмотр страницы приходится два-три баннера, а значит и вызова программы. Понятно, что если избавиться от накладных расходов (пункты 2 и 3), работа сервера значительно ускорится. Это можно сделать двумя похожими способами. Первый - написать модуль к Apache и вкомпилировать его в сервер. Именно так в баннерной сети Фламинго-2 (http://www.f2.ru), в создании которой я принимал участие, была реализована часть системы, которая раздавала баннеры пользователям. Это был модуль, написанный на языке C, который функционировал как часть сервера Apache и поэтому работал очень быстро. Второй способ - использовать технологии предкомпиляции программ. Таких технологий достаточно много. Например, для perl-скриптов это могут быть FastCGI и mod_perl. Расскажу подробней о mod_perl. Это вкомпилированный (опять же в виде модуля) в Apache perl-компилятор. Во-первых, даже для простых скриптов (при надлежащей настройке) это исключает вторую стадию выполнения. Но кроме этого mod_perl дает возможность писать хэндлеры - обработчики определенных стадий выполнения запроса. Это очень мощная технология, поэтому рассмотрим ее подробнее. Можно, например, написать хэндлер, который будет вызываться при запросе определенного URL. Делается это так. В файл httpd.conf вы прописываете следующие строки: <Perl> unshift(@INC, 'Путь к Вашему модулю'); @PerlModule = qw(MyHandler); %Location = ( '/myhandler' => { 'PerlHandler' => 'MyHandler::view', 'SetHandler' => 'perl-script', 'PerlSendHeader' => 'on' }, ); </Perl> Тем самым вы указываете Apache и модулю mod_perl, что если пользователь запросит URL /myhandler, то для его обработки должен запуститься модуль MyHandler, а в нем процедура view. После изменения httpd.conf надо перезагрузить Apache. Кстати, все указанные в конфигурационном модуле файлы будут компилироваться при загрузке сервера, а не при первом запросе. Это в несколько раз увеличит скорость работы сервера. Модуль MyHandler.pm может выглядеть, например, так: package MyHandler; use strict; # Процедура view sub view { print "<HTML>\n<BODY>\nУра! Это отработал наш хэндлер!</BODY>\n</HTML>\n"; } 1; Механизм хэндлеров обладает мощными возможностями. Фактически вы можете заменить любую стадию обработки запросов. Рассмотрим для примера создание собственного механизма проверки пароля: package MyAuthorization; use strict; # Обработчик, запрашивающий пароль sub handler { my $r = shift; return AUTH_REQUIRED unless $r; my (undef, $password) = $r->get_basic_auth_pw; my ($login) = $r->connection->user; return AUTH_REQUIRED unless $password; # Проверяем, все ли в порядке # Проверка может быть любой # Можно свериться с базой данных, а мы будем считать, что пароль должен быть # равен логину, прочитанному задом наперед. my $rev_login = reverse($login); # Проверка пароля if ($rev_login ne $passwd_sent) { return AUTH_REQUIRED; } else { return OK; } }; 1; В файле настроек сервера httpd.conf необходимо указать, что авторизовать пользователя мы будем сами: %Location = ( '/myhandler' => { 'PerlHandler' => 'MyHandler::view', 'SetHandler' => 'perl-script', 'PerlSendHeader' => 'on' 'require' => 'valid-user', 'Limit' => { 'METHODS' => 'GET POST' }, 'AuthType' => 'Basic', 'AuthName' => 'PersonaUser', 'PerlAuthenHandler' => 'MyAuthorization ->handler()' }, ); Теперь доступ к /myhandler защищен - браузер выведет пользователю стандартное окно для ввода пароля. Более подробно с технологией mod_perl можно познакомиться на сайте http://perl.apache.org/ Использование конвейеров Старайтесь не производить обработку данных в интерактивных скриптах. Записывайте их в лог-файлы, а затем агрегируйте и обрабатывайте уже отдельным процессом. Например, ответ пользователя в интерактивном голосовании может вызывать у вас изменения в десятке различных параметров статистики (распределение ответов, активность пользователей, общее число проголосовавших и так далее). Не проводите их сразу. Вместо этого разбейте процедуру на две части. Первая - непосредствен- но голосование, запись результата и вывод ответной страницы пользователю. Вторая - обработка голосования, изменение статистики и т.д. Вообще надо стараться минимизировать количество интерактивных операций. В идеальном случае скрипт для учета голосования вообще ничего не делает, кроме записи информации в лог-файл. А для обработки данных из лог-файла можно запускать отдельный процесс-демон. Для примера рассмотрим механизм обработки статистики в баннерной сети Фламинго-2. В ней был реализован 4-х ступенчатый конвейер: 1) Информация о каждом запросе записывалась в полный лог. Это была очень подробная информация и записывалась она без всякого сжатия, на которое потратилось бы много времени. Размер этого лога очень велик - одна запись в нем занимала 250 байт. Данные в этом логе не хранились дольше нескольких часов. 2) С периодичностью раз в 10 минут запускалась программа, которая обрабатывала полный лог и в компактном виде писала информацию в таблицы базы данных. На этой же стадии учитывались показы, изменялись временные таблицы, используемые для выдачи баннеров пользователю и для работы следующих стадий. 3) Часовой демон, который строил почасовую статистику, производил сложные географические расчеты и многое другое, запускался в конвейере один раз в час. Он уже не имел доступа к полному логу и использовал информацию исключительно из второй стадии. 4) В задачи последней стадии входила дневная ротация файлов, статистика, подведение балансов и рассылка почтовых предупреждений. Эта стадия работала каждые сутки поздно ночью, когда нагрузка на сервер была минимальной. Как видите, механизм достаточно сложный, и наладить его корректную работу было нелегко. Чем больше стадий, тем больше проблем при их сопряжении друг с другом. Тем не менее, такая система позволяла достаточно эффективно распределять нагрузку и шустро работала на простом IDE-диске (расчетная пропускная способность была около 2-3 миллионов обращений в день при пиковой нагрузке 200 обращений в секунду). При этом система вела большое количество статистики. Итак, резюмируем: для увеличения скорости работы программ, взаимодействующих с пользователем, разбиваем их работу на части, причем интерактивная часть должна содержать минимум расчетов и операций записи. Все необходимые расчеты можно произвести позднее, в более благоприятное с точки зрения нагрузки время и более эффективно. |