ПРОЕКТЫ 


  АРХИВ 


Apache-Talk @lexa.ru 

Inet-Admins @info.east.ru 

Filmscanners @halftone.co.uk 

Security-alerts @yandex-team.ru 

nginx-ru @sysoev.ru 


  СТАТЬИ 


  ПЕРСОНАЛЬНОЕ 


  ПРОГРАММЫ 



ПИШИТЕ
ПИСЬМА












     АРХИВ :: nginx-ru
Nginx-ru mailing list archive (nginx-ru@sysoev.ru)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[ANN] nginx-perl


  • To: nginx-ru@xxxxxxxxx, moscow-pm@xxxxxx
  • Subject: [ANN] nginx-perl
  • From: Alexandr Gomoliako <zzz@xxxxxxxxxx>
  • Date: Tue, 1 Nov 2011 19:48:42 +0200
  • Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:sender:date:x-google-sender-auth:message-id:subject :from:to:content-type:content-transfer-encoding; bh=5I45POtY7kRKr7HzZoTA+b1ytYaLrOWdSApvcu+f7nY=; b=ZEBdgP4j3tEL9nRbWSMQM2HgwnQQjjlE+sn7ls0f+BKdwhsqKnVFnJlKGwil36fOa1 uIZDJp5M7C0Z2RXrX093X3/kzVO1gtRgCg/SLXwa1jCjkbibS42+gbeM5EMNZFTCcWF5 vbfGvrf0rqB9Ozyv1uPEXS0qRte0fX1FokPo8=

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 уже после первого будет
указывать на осоводившуюся память.
Со временем пофиксим.


На всякий случай прикладываю и в виде патча.
_______________________________________________
nginx-ru mailing list
nginx-ru@xxxxxxxxx
http://mailman.nginx.org/mailman/listinfo/nginx-ru


 




Copyright © Lexa Software, 1996-2009.