[Moscow.pm] [ANN] nginx-perl

Ruslan Zakirov ruz на bestpractical.com
Ср Ноя 2 15:15:15 UTC 2011


Привет,

Есть в загашнике один асинхронный проект, но пока нету времени к нему
вернуться, но все равно спрошу общие вопросы.

Я еще раньше смотрел на ваш Nginx::Engine краем глаза. Я так понимаю
это новое решение полностью вытеснит необходимость в Nginx::Engine.
Верно?

Судя по всему можно поверх этого дела написать реализацию
AnyEvent::Impl::Nginx. Верно?

2011/11/1 Alexandr Gomoliako <zzz на zzz.org.ua>:
> Hello,
>
> Предлагаю попробовать расширенный встроенный перл.
> Я решил переделать все то, что мне не нравилось в прошлом
> моем модуле, но уже в виде патча для nginx,
>
> Взять в виде дистрибутива можно тут:
>    https://github.com/zzzcpan/nginx-perl
>
> Вся документация пока только в этом письме.
>
> Старый API не меняется и практически не тронут:
>    http://nginx.org/ru/docs/http/ngx_http_perl_module.html
>
>
> 1. Установка
>
> Сразу советую собрать с новым перлом, использованиe
> памяти в других не обрадует:
> Сейчас это довольно просто:
>    % sudo cpan App::perlbrew
>    % perlbrew --force install perl-5.14.2
>
> И через пол часа получите перл в
>    /home/<user>/perl5/perlbrew/perls/perl-5.14.2/
>
> Теперь nginx, перл там включен сразу, нужно только
> указать, с каким собрать:
>    % ./configure
> --with-perl=/home/<user>/perl5/perlbrew/perls/perl-5.14.2/bin/perl
>    % make
>
> В дистрибутиве есть готовый конфиг для быстрого старта:
>    % mkdir hello/logs
>    % ./objs/nginx -p hello
>
> Пример модуля лежит в hello/lib/Hello.pm, конфиг в hello/conf/nginx.conf.
>
>
> 2. Асинхронные ответы
>
> Можно отвечать на запросы асинхронно из другого
> обработчика:
>
>    sub handler {
>        my $r = shift;
>
>        $r->main_count_inc;
>
>        # ... здесь создаем обработчики для других событий
>
>        return NGX_DONE;
>    }
>
> NGX_DONE позволяет не обрабатывать запрос по старому,
> а сразу выйти из обрабтчика и вернуться в event loop.
>
> Чтобы отправить ответ позже, нужно две строчки:
>
>    $r->send_special(NGX_HTTP_LAST);
>    $r->finalize_request(NGX_OK);
>
> Пример, создать таймер и ответить через секунду:
>
>    sub handler {
>        my $r = shift;
>        $r->main_count_inc;
>
>        ngx_timer 1, 0, sub {
>            $r->send_http_header("text/html");
>            $r->print("Hello\n");
>
>            $r->send_special(NGX_HTTP_LAST);
>            $r->finalize_request(NGX_OK);
>        }
>
>        return NGX_DONE;
>    }
>
>
> 3. Асинхронные соединения:
>
>  - все ошибки устанавливаются в $!,
>  - EOF считается ошибкой, можно проверить условием:
>        $! == NGX_EOF
>  - flow control происходит через return:
>        return NGX_READ;
>        return NGX_WRITE;
>        return NGX_CLOSE;
>
> Чтобы подключиться к какому-то хосту используется
> ngx_connector:
>
>    ngx_connector $host, $port, $timeout, sub {
>        return NGX_CLOSE  if $!;
>        my $connection = shift;
>        ...
>    };
>
> Внутри коннектора можно создавать функции чтения
> и записи:
>
>    ngx_writer $buf, $timeout, sub {
>        return NGX_CLOSE  if $!;
>        ...
>        return NGX_READ;
>    };
>
>    ngx_reader $buf, $min, $max, $timeout, sub {
>        return NGX_CLOSE  if $!;
>        ...
>        return NGX_CLOSE;
>    };
>
> ngx_reader и ngx_writer можно пересоздавать
> внутри сколько угодно раз.
>
> Пример: подключиться к какому-то фтп и считать
> приветствие:
>
>    ngx_connector '87.51.34.132', 21, 5, sub {
>        return NGX_CLOSE  if $!;
>
>        my $c = shift;
>        my $buf = '';
>
>        ngx_reader $c, $buf, 0, 0, 5, sub {
>            return NGX_CLOSE  if $!;
>            return NGX_READ  if $buf !~ /\x0a/;
>
>            warn "buf = $buf\n";
>
>            return NGX_CLOSE;
>        };
>
>        return NGX_READ;
>    };
>
> Более сложный пример можно найти в hello/lib/Hello.pm,
> функция selftest_get. Она отправляет простой http запрос,
> принимает ответ и возвращает результат в колбэк.
>
>
> 4. Подход
>
> Уже наверное понятно, какой подход реализован:
>  - все, что вложено --  последовательно
>  - все, что подряд -- параллельно
>
> Все переменные хранятся в пэдах, никаких объектов.
> Чтобы не запутаться, лучше так и продолжать, это довольно
> просто:
>
>    sub foo ($\$&) {
>        my ($arg, $arg_ref, $cb) = @_;
>        # ...  здесь можно вызывать таймер, коннектор и т.д.
>        &$cb();
>    }
>
> Вызов:
>    foo 1, $buf, sub {
>         print $buf;
>    };
>
>
> 5. Баги
>
> Модуль довольно большой, так что не без багов.
>
> Будьте осторожны с отправкой ответа два раза, это
> вызовет segfault, потому что $r уже после первого будет
> указывать на осоводившуюся память.
> Со временем пофиксим.
>
>
> На всякий случай прикладываю и в виде патча.
> --
> Moscow.pm mailing list
> moscow-pm на pm.org | http://moscow.pm.org
>



-- 
Best regards, Ruslan.


Подробная информация о списке рассылки nginx-ru