• Like
  • Save
Perl Debugger и mod_perl
Upcoming SlideShare
Loading in...5
×
 

Perl Debugger и mod_perl

on

  • 2,437 views

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

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

Statistics

Views

Total Views
2,437
Views on SlideShare
2,429
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

12 of 2

  • 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