shoorick: (Рыжий)
Как я только не запускал перловые скрипты на веб-серверах — и как CGI, и как mod_perl (на обоих апачах), и как FastCGI через nginx.

А какой способ принято сейчас использовать?

Мы завели отдельную железяку под перловый хостинг, чтоб выселить туда всё перловое: несколько сайтов на Mojolicious, Catalyst и Movable Type плюс древний самописный кошмар, который давно переписать на чём-нибудь современном.

Хочется сделать это хорошо и правильно. Как быть? Что читать?
shoorick: (Default)
Каталистовое приложение жрёт достаточно много памяти

Конечно, это можно пытаться обойти, перезапуская дочерние процессы сервера после обработки определённого количества запросов, но это как-то не со совсем правильно: уже после пары десятков запросов каждый процесс съедает до 150 метров, а когда процессы жиди подольше и запускались через mod_perl, апачные процессы раздувались ещё сильнее.

С другой стороны, более правильным методом было бы устранение утечек, а не отстрел процессов. Для этого есть куча методов: например, на xpoint.ru лежит список модулей, помогающих обнаружить утечки памяти. Попробовал запустить сервер, используя Devel::LeakTrace::Fast — всё затормозилось: только запуск ждать пришлось минут десять, если не больше, а отрисовка страницы занимала от одной до трёх минут. В результате в STDERR вывалился здоровенный список дырявых мест, причём бóльшая их часть — не в нашем приложении, а во внешних модулях.

Что делать — непонятно. Для начала, думаю, надо посмотреть и разобраться, что же мы сами-то написали.
shoorick: (Default)
Пытаюсь водрузить каталист на сервер под FreeBSD — там какая-то фигня с деревом портов (хотя порты свежеобновлённые): почему-то одни порты не то, что не ставятся, а даже не загружаются (ни через make, ни через portupgrade) — пишут distinfo is out of date, or ... spelled incorrectly, хотя вручную всё прекрасно скачивается; другие же — и вовсе куда-то пропали и вместо установки перломодуля из портов приходится ставить его командой cpan, что в данном случае не совсем правильно.

Понятно, что при помощи лома, напильника и такой-то матери можно заставить всё это работать, но как-то уж очень некомфортно.

Думаю, что следующий крупный перловый сайт будет никак не на каталисте — может быть, на Mojolicious — там хотя бы не надо половину CPAN вытягивать.
shoorick: (Default)
Ускоряем каталистовый сайт, переписываем слишком медленные запросы с DBIx::Class на обычный DBI. Попутно допилил напильником каталистовую модель, чтобы она поддерживала UTF-8 в MySQL, о чём и написал в [livejournal.com profile] ru_catalyst. Кому надо — пользуйтесь.
shoorick: (Default)
Процесс перевода каталистового приложения на новый сервер что-то затягивается: после установки всего необходимого приложение наконец-то запускается, но работать не хочет: сначала ругалось на Wide characters и помирало, теперь, после бубна и напильника, не ругается и, вроде, живёт, но выводит странную кашу: данные, пришедшие из БД и из конфирурационного файла, отображаются правильно, а вот содержимое шаблонов лишний раз перекодируется и выводится примерно так: помоÑ.

Читаю Using Unicode in Catalyst Applications — вижу, что некоторые рекомендации оттуда я как-то применял, но закомментировал: наверное, они были, как минимум, не нужны, а то и вредны. Продолжаю читать и пробовать...

upd/17:40: Отключил кэширование шаблонов в TT, чтобы глаза не мозолили, сделал всё, рекомендованное в Using Unicode in Catalyst Applications — заработало.
shoorick: (Default)
За давностию лет уж позабыл, каково ставить каталист. Пришлось вспомнить. Часть модулей в портах отсутствует (включая Lingua::RU::Inflect, чью версию 0.03 всё никак не доделаю).

Попутно обнаружил странное: некоторые мелкие модули с первого раза не ставятся. Из-за этого не ставятся большие. Попутно у системы срывает крышу: pkg_version считает, что модуль не установлен, но portinstall его ставить отказывается, ссылаясь на то, что он якобы уже есть. Приходится, стуча в бубен и матерясь, идти в /usr/ports/portname и собирать командой make. А иногда помогал и просто повторный запуск portinstall. Почему так — не знаю.

На прошлой неделе начал ставить перломодули, необходимые нашему каталистовому мегаизделию — сегодня закончил:
# grep p5- 100521-all.txt | wc -l
       1
# grep p5- 100525-all.txt | wc -l
     241
Оно запустилось. Правда, пишет бред. Но это уже другой вопрос.

upd/22:50: Надо всё-таки почитать документацию по правильным методам развёртывания перловых приложений, чтобы не устраивать подобных бубнений в будущем.
shoorick: (Default)
Больной! Вы хвастаетесь или жалуетесь?
Обнаружил, что вызываемый каталистом модуль YAML::XS не может прочитать файл, который читался старым модулем YAML. Написал в соответствующее сообщество. Хотя зачем? Спрятал ненужные данные — проблема исчезла.
shoorick: (Default)
Это я такое написал? Проще уж на обычном SQL писать...
$c->stash->{'checkpoints'} = [
    $c->model($MODEL)->search(
        {
            'stgroup_id.id'           => $student->stgroup_id->id,
            'checkresults.student_id' => [ $student->id, undef ],
        },
        {
            'select'   => [ \'me.name cpname', qw/me.id me.date max_ball/ ],
            'join'      => [
                'checkresults', {
                    'tss_id' => [
                        qw/stgroup_id subject_id/,
                        { 'teacher_id' => 'user_id' }
                    ],
                }
            ],
            '+columns'  => [
                qw/subject_id.name checkresults.ball/,
                qw/user_id.fname user_id.sname user_id.lname/,
            ],
#             '+as'       => [ qw/subject_name ball/ ],
            'order_by'  => [ qw/date/ ],
        },
    )
];
shoorick: (Default)
Пытаюсь воткнуть свежезарелизенное в один из наших проектов. С одной стороны, конечно, надо придерживаться правила «Не сломалось — не чини», но, с другой, если модуль выложен на CPAN и, следовательно, уже не сильно связан с исходным проектом — нет смысла держать дубль. Пока натыкаюсь на ошибки:
Malformed UTF-8 character (unexpected continuation byte 0x80, with no preceding start byte) in pattern match (m//) at /usr/local/lib/perl5/site_perl/5.8.9/Lingua/RU/Inflect.pm line 254.
[error] Caught exception in engine "Wide character in memGzip at /usr/local/lib/perl5/site_perl/5.8.9/Catalyst/Plugin/Compress/Gzip.pm line 36"
Попробовал добавить в проблемный участок вызовы функций encode и decode:
my @name = Lingua::RU::Inflect::inflect_given_name(
    GENITIVE,
    decode('utf8', $student->user_id->lname),
    decode('utf8', $student->user_id->fname),
    decode('utf8', $student->user_id->sname),
);

push @name, shift @name; # ФИО → ИОФ
$c->stash->{'student_genitive'} = encode('utf8', join(' ', @name));
Вроде, заработало, но выглядит паршиво.

Надо бы perlunicode перечитать...
shoorick: (Default)
Предыдущие замеры производительности каталистовых серверов были не вполне чисты: на некоторых серверах использовалась тестовая версия БД, на некоторых — боевая. Хоть обе базы живут на одной машине и управляются одни SQL-сервером, их содержимое не совпадает. Понятно, что различие в содержимом может оказывать влияние на скорость — надо было сразу взять напильник в руки и настроить все серверы на использование одной и той же версии базы.

Сегодня протестировал с одинаковой базой — выяснил, что скорости апача и nginx + Catalyst::Engine::HTTP::Prefork совпадают. Более того, апач иногда проигрывает несколько процентов. Получается, что выбор не той базы давал апачу незаслуженное преимущество, достигавшее нескольких десятков процентов.

В итоге данные заметно поменялись: И теперь график выглядит так: )
shoorick: (Default)
Попробовал позавчера найти экспериментальным путём лучшее (с точки зрения производительности) количество дочерних процессов, с которыми следует запускать nginx + Catalyst::Engine::HTTP::Prefork и Apache + mod_perl.

Апач настраивал изменением параметра MaxClients в httpd.conf.

Связку нгинкса с каталистовым сервером — чуть сложнее: нгинкс не трогал, а менял параметры каталистового сервера: методу AppName->run можно, помимо прочих параметров, передать max_servers, задающий максимально допустимое количество создаваемых сервером дочерних процессов.

Картина получилась достаточно странная:

Зависимость производительности от числа запущенных процессов

Хотя результат по-прежнему зависит непонятно от чего: например, сегодня оба варианта показали бóльшую производительность, но с прежним соотношением: 9 к 12.

Либо можно попытаться ускорить само каталистовое приложение (Как? Менять шаблонизатор? Оптимизировать SQL-запросы? Апгрейдить железо? Выбрасывать бэкенд на отдельную машину?) — и не забивать себе голову подобными соревнованиями.

upd/21.01.2010: Более точное тестирование показало равную производительность апача и нгинкса.
shoorick: (Default)
По результатам гуглений и бубнений настроил nginx и каталист для совместной работы. В нгинксовом конфигурационном файле в моём случае надо указать, что фронтенд должен передать бэкенду не только своё имя, но и порт:
proxy_set_header   Host             $host;
proxy_set_header   X-Real-IP        $remote_addr;
proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
proxy_set_header   X-Forwarded-Host $http_host;
proxy_set_header   X-Forwarded-Port $http_port;
Это связано с тем, что оба работают на одной машине на разных портах. А каталистовому приложению надо сказать, что оно может быть спрятано от внешнего мира за прокси-сервером. Существуют разные методы, простейший из них — добавить в конфигурацию параметр using_frontend_proxy, равный единице. Чтобы не засорять модули, добавит его в конфиг.yml — это проще всего и вполне работоспособно.

Если не сделать такой настройки, то каталистовая функция uri_for будет возвращать ссылки на адреса бэкенда, который посетителю показывать совсем не надо.

Теперь осталось убедиться в корректной работе получившейся связки, проверить способность нгинкса к старту при загрузке системы — и можно будет запускать весь этот комбайн в космос боевую эксплуатацию.
shoorick: (Default)
Тестирование производительности по-разному запущенного каталистового приложения показывает неожиданные результаты: апач с мод_перлом с точки зрения производительности оказались более предпочтительными, чем другие варианты: и встроенный сервер (как в конфигурации по умолчанию, так и с CATALYST_ENGINE='HTTP::Prefork'), и nginx+FastCGI работают заметно медленнее, чем апач.

Из всех испробованных вариантов помимо чистого апача годится ещё nginx+Apache — статичные файлы можно раздавать nginx'ом, а динамику — апачем. Хотя сам апач прекрасно справляется и с раздачей статики, он жрёт гораздо больше памяти, чем nginx. С учётом того, что аппетит апача в отношении памяти можно ограничить директивами MaxClients (апач работал и с пятью дочерними процессами — скорость была не хуже скорости с пятьюдесятью процессами) и MaxRequestsPerChild (время жизни дочернего процесса (в принятых запросах), по умолчанию дочерние процессы живут бесконечно, что в данном случае не годится) — видимо такую систему и придётся сооружать (после того, как разберусь с uri_for).

График спрятан )
shoorick: (Default)
Удалось запустить подопытный сайт через nginx+FastCGI. Предварительно пришлось поставить p5-FastCGI-ProcManager, который почему-то не был автоматически поставлен при установке каталиста и обновить libtool, без которого FastCGI::ProcManager не желал ставиться.

Наблюдается интересная картина: производительность, судя по результатам работы ab, в 2–2,5 раза хуже, чем при использовании Apache+mod_perl (но во столько же лучше, чем у каталистового тестового сервера), однако расход памяти заметно ниже: апач на каждый процесс сразу отъедал около 60 метров памяти, процессы размножались и раздувались (до 200 метров на процесс — легко!), потребляя в сумме несколько гигабайт (стремясь сожрать всю доступную память: и физическую, и виртуальную); при использовании FastCGI всё не так: запускается всего 2 процесса со сходными аппетитами на память, один из них ничего не делает, зато другой делает, видимо, всё остальное:
$ top
  PID USERNAME THR PRI NICE   SIZE    RES STATE  C   TIME   WCPU COMMAND
72718 as         1 125    0 57400K 49068K RUN    1   0:55 74.72% perl
72715 as         1   8    0 56896K 44720K wait   0   0:03  0.00% perl
Статичные файлы, как можно догадаться, раздаются непосредственно nginx'ом. Лёгкие файлы (например, иконка весом менее килобайта) выдаются раза в 2 быстрее, чем апачем, тяжёлые (например, prototype.js — больше 100 кБ) — примерно с одинаковой скоростью.
shoorick: (Default)
Попробовал между клиентом и каталистом воткнуть nginx.

Ну воткнул, ну запустил (настроив выдачу статики nginx'ом, а остального, как и раньше — апачем) — а пользы не видно: как апачные процессы жрали процессор — так и жрут, как mod_perl отъедал всё больше и больше памяти — так и отъедает.

Скорость выдачи статики у обоих серверов практически совпадает, а на выдаче динамического контента апач даже чуть-чуть шустрее связки nginx+apache (что предсказуемо).

В чём смысл-то? Разве что вынести backend на другую железяку (или завести несколько бэкендов на разных машинах) — может быть, что-то улучшится. Или попробовать FastCGI в надежде на уменьшение потребления памяти? Непонятно.

Толкового мануала к nginx'у нет (во всяком случае, на сайте разработчика). Ни на русском, ни на английском — лишь какие-то обрывки да разрозненные статьи, раскиданные по интернетам. Вот их и придётся изучать...

Re: Ой

Dec. 7th, 2009 09:52 pm
shoorick: (Default)
Поглядев на терзание сервера баз данных нашей поделкой, решил попробовать другой метод: DBIx::Class, вроде бы, позволяет выполнять произвольный SQL-запрос. Запрос-то я написал и протестировал, да вот подсунуть его каталисту пока не получается...

Пойду-ка домой, ужинать и читать мануалы.

Ой

Dec. 7th, 2009 05:45 pm
shoorick: (Default)
Прочитал про отладку в DBIx::Class, включил вывод запросов в лог — ужасаюсь: на отображение одной странички ушло 140 (сто сорок!) запросов (среди них — немало повторяющихся). Даже если СУБД и выдаёт результаты из кэша — это всё равно слишком много. Я, конечно, понимаю, что использование ORM может подразумевать некоторое увеличение использования машинных ресурсов в обмен на экономию времени программиста. Но не до такой же степени!
shoorick: (Default)
[livejournal.com profile] niskam написал в [livejournal.com profile] ru_perl: Кэширование подшаблонов в Template Toolkit. В посте есть ссылка на статью Рэндела Шварца «Profiling in Template Toolkit via overriding», где описан способ оценки производительности отдельных шаблонов на сайте, работающем с использованием Template::Toolkit. Я попробовал применить метод на каталистовом сайте — работает, измеряет.
shoorick: (Default)
Захотелось странного — обновить каталист с 5.7 до 5.8: в новом обещали всякий much easer да much faster. Ну и обновил. А до кучи — и остальные перловые модули, что были в портах. В результате и зайцев не спас, и перед партизанами неудобно выяснилось (чё, спрашивается, сразу не посмотрел?), что в портах каталист старый — 5.71001 и после обновления всё загнулось: и свежие, ещё не закоммиченные версии разрабатываемого сайта, и более старые.

Причина крылась в том, что некоторые модули поменялись, а некоторые — вообще стали deprecated, например, Catalyst::Model::DBIC и http://search.cpan.org/perldoc?Catalyst::Plugin::Authentication::Store::DBIC. И в DBIx::Class что-то поломалось.

Решилось пляской с бубном перегенерацией модулей, описывающих структуру базы данных, командой
script/app_create.pl model Dbase DBIC::Schema Dbase create=static dbi:mysql:БД[:хост] логин пароль
При этом модули создались не там, где раньше, а на один уровень глубже — в каталоге Result.

Пробовал задавать create=dynamic, чтобы поменьше получалось — не выходит: сервер не запускается. Пришлось пока остановиться на этом методе. Почитал мануалы, попробовал погуглить — без особого успеха. Домой пришёл лишь в 22:45.

P. S. Видя такой бардак, решил до кучи и перл проапгрейдить до 5.8.9 — проапгрейдил, но наткнулся на очередные грабли: в портах почему-то нет Catalyst::Plugin::RequireSSL — пришлось ставить через perl -MCPAN -e shell.
shoorick: (Default)
Зная номер порта, на котором работает каталистовый отладочный сервер, все его экземпляры легко можно загасить без использования мыши и ручного набора PIDов:
ps -ax | grep p\ номер_порта | grep -v grep | cut -f1 -d' ' | xargs kill -сигнал

Profile

shoorick: (Default)
shoorick

December 2016

S M T W T F S
    1 23
45678910
11121314151617
18 19 2021222324
25262728293031

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 24th, 2026 08:01 pm
Powered by Dreamwidth Studios