Perl Debugger и mod_perl
Upcoming SlideShare
Loading in...5
×
 

Perl Debugger и mod_perl

on

  • 2,460 views

Прикручиваем perl debuuger к mod_perl

Прикручиваем perl debuuger к mod_perl

Statistics

Views

Total Views
2,460
Views on SlideShare
2,452
Embed Views
8

Actions

Likes
0
Downloads
6
Comments
2

1 Embed 8

http://www.slideshare.net 8

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • 2) Если выходить из perl debuuger не корректно (over kill signal on perl debugger process), то у вас могут накапливаться симофоры чилдов apache. И, в один прекрасный момент, отладичк просто перестанет запускаться. Поэтому полезно давать периодически команду на удаление этих симофоров:
    ipcs -s | grep you_login | perl -e 'while () { @a=split(/\s+/); print `ipcrm sem $a[1]`}'
    Are you sure you want to
    Your message goes here
    Processing…
  • 1) В описании VirtualHost может использоваться директива: PerlSwitches -I/path_to/lib
    , чтобы подсосать путь к вашим либам. Чтобы отладчик работал корректно, нужно поменять следующим образом:
    use lib ’/path_to/lib’;
    use Apache::DB ();
    ....
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Perl Debugger и mod_perl Perl Debugger и mod_perl Presentation Transcript

  • Perl Debugger and mod_perl серия «книжко-малышко»
  • Содержание
    • Вступление
    • Немного про mod_perl
    • Проблема mod_perl
    • Почему течёт память
    • Варианты использования mod_perl
    • Проблема отладки mod_perl
    • Подключение debugger
    • Собственные конфиги apache
    • Тестовый запуск
    • Прикручиваем perl debugger
    • Тестовый запуск с perl debugger
    • Сложности структуры Вашего проекта
    • Материал и данные по тестированию
  • Вступление
    • Всегда есть упрямые. Спорить ни с кем не собираюсь. Любите отладку на warn – ваше личное дело.
    • Но, вместе с тем, просто задумайтесь над тем, что логи выполнения perl кода нужны для «истории» работы, а не для поиска ошибок.
    • Кто знает perl debugger – знает perl
    • В этой презентации целью является - показать, как отлаживать ваш mod_perl проект так же, как если бы вы работали через debugger с cgi или pl скриптом.
    • Предполагается, что Вы уже знаете:
    • команды perl debugger
    • имеете общее представление о mod_perl
    • имеете общее представление о httpd.conf
    • Так же, рассчитываю, что у Вас под рукой уже есть рабочее приложение под mod_perl , которое и станет нашим полигоном для испытаний ;)
  • Немного про mod_perl
    • mod_perl – это модуль к веб серверу Apache .
    • Единственное его назначение – это подгрузить ваш perl- код сразу в каждый чилд apache . Такой подход позволяет экономить время на компиляции. Получается весьма быстро.
    • Достигается это тем, что весь код как бы «оборачивается» стандартным для mod_perl описанием, и итоговый код представляет собой единый листинг* с кодом вашего приложения указанным для обработки в httpd.conf .
    • *Именно по этой причине, вы не можете обращаться к секции __DATA__ ваших скриптов.
    • Есть возможность указывать сколько request (число) должен обработать каждый чилд перед тем, как «перезапуститься». Т.о. решается проблема «течки» памяти mod_perl .
    • Если выставить, что каждый чилд обрабатывает только 1 запрос и умирает, то вы получите некий эквивалент классического CGI .
  • Проблема mod_perl
    • Единственная, действительно неразрешимая проблема mod_perl , так это то, что mod_perl просто «ускоритель» и ни чего более.
    • А это означает, что написать приложение под mod_perl можно абсолютно не читаемо, так как Вас никто не ограничивает.
    • Поскольку в perl нет инструмента более мощного для чтения чужого кода, чем perl debugger , я поражён тем, что тема практически не раскрыта в рунете.
    • Если Вы хотите иметь (по мимо высокой скорости) и удобную, читаемую структуру кода, обратите своё внимание на перловый фреймворк Catalyst . Здесь Вам и MVC , и возможность переключаться между работой под mod_perl и FastCGI без изменения кода приложения. Да и отлаживается он без дополнительных ухищрений. Большое количество плагинов, отличная документация. В общем всё, чтобы Вы остались довольны.
  • Почему течёт память
    • В общем случае, после появления чилда apache , он уже будет содержать скомпиленный код вашего приложения. При обработке разных запросов, для каждой функции / метода в вашем приложении будет резервироваться память. И если метод для одного запроса потребовал 1Мб памяти, а для следующего ему потребовалось всего 500 Kb , то за этим методом / процессом всё равно останется зарезервированным 1Mb оперативной памяти. Так как разные запросы требуют обработки разного объёма данных, получается, что чилд apache «нажирается».
    • Конечно, есть много других моментов, скажем связанные с ссылками. Но их все можно устранить.
    • Как уже понятно, вопрос времени – когда процесс станет до неприличия жирным. Поэтому и есть такой параметр в настройках apache , отвечающий за смерть чилда после обработки определённого количества запросов.
  • Варианты использования 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
  • Варианты использования mod_perl
    • По пути /path/developer у нас может быть скрипт типа simple_example.pl с контентом:
    • use Apache2::Request;
    • my $r = shift;
    • $r->content_type('text/plain');
    • $r->print(&quot;mod_perl rules! &quot;);
    • Или в более традиционном виде:
    • use Apache2::Const -compile => qw(REDIRECT NOT_FOUND);
    • sub handler{
    • my $r = shift;
    • $r->send_http_header('text/plain');
    • print &quot;mod_perl rules! &quot;;
    • return OK;
    • }
    • 1;
    • И в одном и в другом случае, в браузере по пути url/develiper/imple_example.pl мы увидим:
    • mod_perl rules!
  • Варианты использования 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
  • Варианты использования 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/){
    • ...
    • ...
    • }
  • Варианты использования mod_perl
    • 3. mod_perl реализуется как симбиоз вариантов 1 и 2.
    • Сложно сказать, какой путь для Вас более оптимален. Пожалуй чаще, встречается вариант2.
  • Проблема отладки mod_perl
    • Как уже понятно, речь идёт о подключении perl debugger к perl коду в чилде apache .
    • Так как рунете сложно найти описание подобного механизма, многие предпочитают использовать отладку на warn . Т.е. расставляют warn , запускают, смотрят лог, перемещают warn , запускают программу и т.д. до тех пор, пока ошибка не локализуется достаточно, чтобы программист её нашёл.
    • Особенно забавно, что многие отлаживают на warn продакшн код. И если речь идёт о часто используемом месте проекта, то даже за несколько секунд лог может получиться ёмким. Добавим к этому «ошибка появляется редко» и, получается, что времени на локализацию проблемы уходит много.
    • С perl debugger вы находитесь внутри исполняемой программы и можете без труда «с первого захода» успешно локализовать код с ошибкой.
  • Подключение debugger
    • Для отладки нам потребуется:
    • Создать собственные конфиги apache (в home )
    • Прописать обработку каждого запроса через perl отладчик
    • Запустить httpd процесс в non-forking режиме (один чилд) с обработкой через perl debugger и нашими конфигами
    • Запросить url через браузер, и приступить к отладке
    • Корректно выйти из отладчика
    • Итак, приступим.
  • Собственные конфиги 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
  • Собственные конфиги apache
    • Как было сказано вначале, я считаю, что у Вас уже есть рабочее mod_perl приложение.
    • Вам необходимо найти httpd.conf
    • Сделать это можно так:
    • $ httpd –V
    • Конфиг apache будет по пути HTTPD_ROOT .’/’. SERVER_CONFIG_FILE
    • Например, если HTTPD_ROOT=&quot;/usr/local&quot; и SERVER_CONFIG_FILE=&quot;etc/apache22/httpd.conf&quot; ,
    • то полный путь к конфигу будет /usr/local / etc/apache22/httpd.conf
    • Откопируем его в наш хомяк:
    • $ cp /usr/local / etc/apache22/httpd.conf ~/ httpd.conf
  • Собственные конфиги apache
    • Откройте для редактирования ~/httpd.conf Обратите внимание на параметр Listen. Его значение означает порт, который слушает apache .
    • Обычно это 80-й, 81-й порт. Порты, как известно, до 1024-го привилегированные. Поэтому в нашем конфиге поставим любой свободный порт, а-ля :
    • Listen 3000
    • Пусть ваш username в системе – yesiam . И хомяк по пути /home/yesiam.
    • Меняем параметры:
    • ErrorLog &quot;/home/yesiam/httpd-error.log&quot;
    • CustomLog &quot;/home/yesiam/httpd-access.log&quot; combined
    • Но это ещё не всё.
  • Собственные конфиги 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
  • Собственные конфиги 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>
    • Содержимое должно быть вам понятно.
  • Собственные конфиги 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- файлы будут храниться в нашем хомяке
    • Осталось сделать тестовый запуск.
  • Тестовый запуск
    • Все обращения, что до этого вы делали на http://mysite.ru:80 или http://mysite.ru:8 1 (зависит от 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 на отдельном порту. Вам не потребовалась помощь админа, или какие-то особые права.
  • Прикручиваем 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>
  • Тестовый запуск с 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 отладчика.
  • Тестовый запуск с 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
  • Сложности структуры Вашего проекта
    • Конечно, Ваш проект может быть не так прост. У Вас скорее всего есть 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
  • Материал и данные по тестированию
    • За основу было взято описание процесса отладки с http://perl.apache.org/docs/1.0/guide/debug.html
    • И проверено на практике.
    • Тестирование проводилось на FreeBSD 6.2 и Apache/2.2.11