'

Perl Debugger and mod_perl

Понравилась презентация – покажи это...





Слайд 0

Perl Debugger and mod_perl серия «книжко-малышко»


Слайд 1

Содержание Вступление Немного про mod_perl Проблема mod_perl Почему течёт память Варианты использования mod_perl Проблема отладки mod_perl Подключение debugger Собственные конфиги apache Тестовый запуск Прикручиваем perl debugger Тестовый запуск с perl debugger Сложности структуры Вашего проекта Материал и данные по тестированию


Слайд 2

Вступление Всегда есть упрямые. Спорить ни с кем не собираюсь. Любите отладку на warn – ваше личное дело. Но, вместе с тем, просто задумайтесь над тем, что логи выполнения perl кода нужны для «истории» работы, а не для поиска ошибок. Кто знает perl debugger – знает perl В этой презентации целью является - показать, как отлаживать ваш mod_perl проект так же, как если бы вы работали через debugger с cgi или pl скриптом. Предполагается, что Вы уже знаете: команды perl debugger имеете общее представление о mod_perl имеете общее представление о httpd.conf Так же, рассчитываю, что у Вас под рукой уже есть рабочее приложение под mod_perl, которое и станет нашим полигоном для испытаний ;)


Слайд 3

Немного про mod_perl mod_perl – это модуль к веб серверу Apache. Единственное его назначение – это подгрузить ваш perl-код сразу в каждый чилд apache. Такой подход позволяет экономить время на компиляции. Получается весьма быстро. Достигается это тем, что весь код как бы «оборачивается» стандартным для mod_perl описанием, и итоговый код представляет собой единый листинг* с кодом вашего приложения указанным для обработки в httpd.conf. *Именно по этой причине, вы не можете обращаться к секции __DATA__ ваших скриптов. Есть возможность указывать сколько request (число) должен обработать каждый чилд перед тем, как «перезапуститься». Т.о. решается проблема «течки» памяти mod_perl. Если выставить, что каждый чилд обрабатывает только 1 запрос и умирает, то вы получите некий эквивалент классического CGI.


Слайд 4

Проблема mod_perl Единственная, действительно неразрешимая проблема mod_perl, так это то, что mod_perl просто «ускоритель» и ни чего более. А это означает, что написать приложение под mod_perl можно абсолютно не читаемо, так как Вас никто не ограничивает. Поскольку в perl нет инструмента более мощного для чтения чужого кода, чем perl debugger, я поражён тем, что тема практически не раскрыта в рунете. Если Вы хотите иметь (по мимо высокой скорости) и удобную, читаемую структуру кода, обратите своё внимание на перловый фреймворк Catalyst. Здесь Вам и MVC, и возможность переключаться между работой под mod_perl и FastCGI без изменения кода приложения. Да и отлаживается он без дополнительных ухищрений. Большое количество плагинов, отличная документация. В общем всё, чтобы Вы остались довольны.


Слайд 5

Почему течёт память В общем случае, после появления чилда apache, он уже будет содержать скомпиленный код вашего приложения. При обработке разных запросов, для каждой функции/метода в вашем приложении будет резервироваться память. И если метод для одного запроса потребовал 1Мб памяти, а для следующего ему потребовалось всего 500Kb, то за этим методом/процессом всё равно останется зарезервированным 1Mb оперативной памяти. Так как разные запросы требуют обработки разного объёма данных, получается, что чилд apache «нажирается». Конечно, есть много других моментов, скажем связанные с ссылками. Но их все можно устранить. Как уже понятно, вопрос времени – когда процесс станет до неприличия жирным. Поэтому и есть такой параметр в настройках apache, отвечающий за смерть чилда после обработки определённого количества запросов.


Слайд 6

Варианты использования mod_perl На практике, я встречал 3 вида использования mod_perl: 1. mod_perl подвязывается непосредственно к скриптам Вот пример httpd.conf <IfModule mod_perl.c> Alias /developer/ /path/developer/ <Location /developer> SetHandler perl-script PerlHandler ModPerl::Registry Options ExecCGI PerlSendHeader On allow from all </Location> </IfModule> Здесь указывается, что при обращении по пути url/developer/… задействовать скрипты, которые находятся в папке /path/developer (см Alias). *отдельно отмечу, что в конфигах старых версий apache может встречаться PerlHandler Apache::PerlRun


Слайд 7

Варианты использования mod_perl По пути /path/developer у нас может быть скрипт типа simple_example.pl с контентом: use Apache2::Request; my $r = shift; $r->content_type('text/plain'); $r->print("mod_perl rules!\n"); Или в более традиционном виде: use Apache2::Const -compile => qw(REDIRECT NOT_FOUND); sub handler{ my $r = shift; $r->send_http_header('text/plain'); print "mod_perl rules!\n"; return OK; } 1; И в одном и в другом случае, в браузере по пути url/develiper/imple_example.pl мы увидим: mod_perl rules!


Слайд 8

Варианты использования mod_perl 2. mod_perl подвязывается к перл модулю, который обрабатывает $r->uri() и принимает решение какой ответ дать. Вот пример httpd.conf: <IfModule mod_perl.c> PerlModule MyPackage::Main <Location /> SetHandler perl-script PerlHandler MyPackage::Main </Location> </IfModule> <Location /> указывает, что нужно отдавать/обрабатывать любой request модулю MyPackage::Main


Слайд 9

Варианты использования mod_perl В каком-то смысле, классический пример контента для MyPackage::Main package MyPackage::Main; use strict; use Apache2::Request; use MyPackage::Config; use Apache2::Const -compile => qw(REDIRECT NOT_FOUND); use Apache2::Cookie; sub handler{ my $r = shift; my $req = Apache2::Request->new($r); my $uri = $r->uri(); my $cfg = MyPackage::Config->new(); my $page_controller = undef; my $answer = undef; if($uri =~ /^\/foo\/bar/){ ... ... }


Слайд 10

Варианты использования mod_perl 3. mod_perl реализуется как симбиоз вариантов 1 и 2. Сложно сказать, какой путь для Вас более оптимален. Пожалуй чаще, встречается вариант2.


Слайд 11

Проблема отладки mod_perl Как уже понятно, речь идёт о подключении perl debugger к perl коду в чилде apache. Так как рунете сложно найти описание подобного механизма, многие предпочитают использовать отладку на warn. Т.е. расставляют warn, запускают, смотрят лог, перемещают warn, запускают программу и т.д. до тех пор, пока ошибка не локализуется достаточно, чтобы программист её нашёл. Особенно забавно, что многие отлаживают на warn продакшн код. И если речь идёт о часто используемом месте проекта, то даже за несколько секунд лог может получиться ёмким. Добавим к этому «ошибка появляется редко» и, получается, что времени на локализацию проблемы уходит много. С perl debugger вы находитесь внутри исполняемой программы и можете без труда «с первого захода» успешно локализовать код с ошибкой.


Слайд 12

Подключение debugger Для отладки нам потребуется: Создать собственные конфиги apache (в home) Прописать обработку каждого запроса через perl отладчик Запустить httpd процесс в non-forking режиме (один чилд) с обработкой через perl debugger и нашими конфигами Запросить url через браузер, и приступить к отладке Корректно выйти из отладчика Итак, приступим.


Слайд 13

Собственные конфиги apache Рассмотрим следующий вариант работы apache: 1 – определение вашего приложения в обработке mod_perl 2 – появление чилдов apache с проинициализированным кодом вашего perl приложения 3 – запрос пользователя, который перенаправляется apache на один из своих child Apache Ваше perl приложение mod_perl WEB C H I L D C H I L D C H I L D C H I L D 1 2 3


Слайд 14

Собственные конфиги apache Как было сказано вначале, я считаю, что у Вас уже есть рабочее mod_perl приложение. Вам необходимо найти httpd.conf Сделать это можно так: $ httpd –V Конфиг apache будет по пути HTTPD_ROOT.’/’. SERVER_CONFIG_FILE Например, если HTTPD_ROOT="/usr/local" и SERVER_CONFIG_FILE="etc/apache22/httpd.conf", то полный путь к конфигу будет /usr/local/etc/apache22/httpd.conf Откопируем его в наш хомяк: $ cp /usr/local/etc/apache22/httpd.conf ~/httpd.conf


Слайд 15

Собственные конфиги apache Откройте для редактирования ~/httpd.conf Обратите внимание на параметр Listen. Его значение означает порт, который слушает apache. Обычно это 80-й, 81-й порт. Порты, как известно, до 1024-го привилегированные. Поэтому в нашем конфиге поставим любой свободный порт, а-ля: Listen 3000 Пусть ваш username в системе – yesiam. И хомяк по пути /home/yesiam. Меняем параметры: ErrorLog "/home/yesiam/httpd-error.log" CustomLog "/home/yesiam/httpd-access.log" combined Но это ещё не всё.


Слайд 16

Собственные конфиги apache Хороший админ не описывает виртхосты в самом httpd.conf. Для этого, он использует такой параметр, как: Include etc/apache22/Includes/*.conf В вашем случае, путь может отличаться. Здесь говорится: «дополни данные конфига, содержимым файлов с расширением conf по пути $HTTPD_ROOT/etc/apache22/Includes/» Если у вас есть такая директива, то ищите описания виртхостов в указанной папке и откопируйте в хомяк нужное описание. Пусть это будет файл mysite.conf. $ cp /usr/local/etc/apache22/Includes/mysite.conf ~/mysite.conf В ~/httpd.conf поменяйте: Include etc/apache22/Includes/*.conf на Include /home/yesiam/mysite.conf И, последний штрих в ~/httpd.conf: PidFile /home/yesiam/apache.pid LockFile /home/yesiam/accept.lock


Слайд 17

Собственные конфиги apache Итак, мы сделали описание для apache, но ещё никак не затронули описание виртхоста, который как раз и работает у нас с mod_perl. Как было сказано выше, это описание может быть и в самом httpd.conf, так и в отдельном файле. Я рассматриваю случай отдельного описания в mysite.conf. Его содержимое изначально будет (к примеру): <VirtualHost *:80> ServerName mysite.ru:80 CustomLog /var/log/access.log combined ErrorLog /var/log/error.log DocumentRoot /site .... <IfModule mod_perl.c> PerlModule MyPackage::Main <Location /> SetHandler perl-script PerlHandler MyPackage::Main </Location> </IfModule> </VirtualHost> Содержимое должно быть вам понятно.


Слайд 18

Собственные конфиги apache Отредактируем его (~/ mysite.conf) до вида: <VirtualHost *:3000> ServerName mysite.ru:3000 CustomLog /home/yesiam/log/access.log combined ErrorLog /home/yesiam/log/error.log DocumentRoot /site .... <IfModule mod_perl.c> PerlModule MyPackage::Main <Location /> SetHandler perl-script PerlHandler MyPackage::Main </Location> </IfModule> </VirtualHost> Не забудьте создать папку ~/log Итак, мы скопировали конфиги к себе в хомяк, отредктировали их так, что: при запуске мы будем слушать порт 3000 все логи, pid-файлы и lock-файлы будут храниться в нашем хомяке Осталось сделать тестовый запуск.


Слайд 19

Тестовый запуск Все обращения, что до этого вы делали на http://mysite.ru:80 или http://mysite.ru:81 (зависит от Listen в изначальном httpd.conf) к этому apache должны быть доступны и при обращении к http://mysite.ru:3000 Пусть mod_perl у вас обрабатывал урл http://mysite.ru:80/12345/rss.xml Запускаем «наш» apache в non-forking режиме (т.е. у вас будет только 1 чилд) с нашими конфигами: $ httpd -X -k start -f ~/httpd.conf И заходим по урл http://mysite.ru:3000/12345/rss.xml Вы должны увидеть точно такой же ответ в браузере, как если бы Вы зашли на http://mysite.ru:80/12345/rss.xml Если у вас произошла ошибка, посмотрите файлы логов ошибок в своём хомяке. Проблема, если и будет, должна решиться легко. Заметьте, Вы не мешаете работе продакшн кода! И, при этом, локализовали чилд apache на отдельном порту. Вам не потребовалась помощь админа, или какие-то особые права.


Слайд 20

Прикручиваем perl debugger Теперь нам осталось подключить perl debugger в каждый чилд apache. А поскольку мы запускаемся в non-forking режиме, то – только к одному. Для этого добавим в вверх описания виртхоста: <VirtualHost *:3000> ServerName mysite.ru:3000 CustomLog /home/yesiam/log/access.log combined ErrorLog /home/yesiam/log/error.log DocumentRoot /site <IfDefine PERLDB> <Perl> use Apache::DB (); Apache::DB->init; </Perl> <Location /> PerlFixupHandler Apache::DB </Location> </IfDefine> .... <IfModule mod_perl.c> PerlModule MyPackage::Main <Location /> SetHandler perl-script PerlHandler MyPackage::Main </Location> </IfModule> </VirtualHost>


Слайд 21

Тестовый запуск с perl debugger Итак, запускаем: $ httpd -X -D PERLDB -f ~/httpd.conf И, видим приветствие: [notice] Apache::DB initialized in child 17524 Набираем в браузере урл http://mysite.ru:3000/12345/rss.xml и видим, что отладчик остановился в handler нашего MyPackage::Main MyPackage::Main::handler(/site/MyPackage/Main.pm:14): 14: my $r = shift; Всё. Теперь Вы можете приступить к отладке используя стандартные команды perl отладчика.


Слайд 22

Тестовый запуск с perl debugger В отличие от стандартной работы с отладчиком, вы можете указать команду «с» и при этом ваш чилд apache сразу вернёт ответ браузеру (если в коде не встречается $DB::signal). И сделать ещё одно обращение к урл. При этом, отладчик снова остановится на методе handler вашего модуля. Так же стоит уделить внимание корректному выходу из отладчика. Помните, когда вы запустили apache (httpd -X -D PERLDB -f ~/httpd.conf), то он сообщил Вам номер процесса в системе (initialized in child 17524). Так вот, корректный выход будет таким (номер процесса, конечно индивидуален): DB<3> !! kill 17524 DB<4> q Или есть такой вариант: DB<3> p $$ 17524 DB<4> !! kill 17524 DB<5> q Т.е. вы сначала «убиваете» процесс чилда apache, и потом выходите из отладки. *команда «!!» в отладчике передаёт последующие аргументы в shell


Слайд 23

Сложности структуры Вашего проекта Конечно, Ваш проект может быть не так прост. У Вас скорее всего есть Nginx, который может балансировать между несколькими apache на нескольких серверах. Сложность будет в том случае, если на уровне nginx.conf у вас прописано изменение порядка или набора uri аргументов. К примеру для сайта globalsite.ru (вымышленное) в nginx.conf может быть: server { listen 80; server_name globalsite.ru www.globalsite.ru; location /archives/ { if ($uri ~ (\d+)/rss.xml){ set $q $1; rewrite / /rss/$q; proxy_pass http://mysite.ru:80; break; } .... Т.е. обращения на http://globalsite.ru/archives/12345/rss.xml перенаправляются на http://mysite.ru/rss/12345 При этом, если вы тестируете mod_perl на mysite.ru помните о реврайтах на уровне Nginx. И, в нашем случае, за http://globalsite.ru/archives/12345/rss.xml будет отвечать http://mysite.ru:3000/rss/12345


Слайд 24

Материал и данные по тестированию За основу было взято описание процесса отладки с http://perl.apache.org/docs/1.0/guide/debug.html И проверено на практике. Тестирование проводилось на FreeBSD 6.2 и Apache/2.2.11


×

HTML:





Ссылка: