От форков к событиям и сопрограммам

20
От форков к событиям и сопрограммам 2 ноября 2008 г Ростов-на-Дону South Perl Евгений Торопов ИП Торопов Е.В

Upload: tamekah-moss

Post on 04-Jan-2016

47 views

Category:

Documents


0 download

DESCRIPTION

От форков к событиям и сопрограммам. 2 ноября 2008 г Ростов-на-Дону South Perl Евгений Торопов ИП Торопов Е.В. Skoosh - как это работает ? (вид снаружи). Поиск Фильтры Карта Отель Номер Заказ Оплата Счастье есть!. Skoosh - как это работает ? (вид изнутри). - PowerPoint PPT Presentation

TRANSCRIPT

От форков к событиям и сопрограммам

2 ноября 2008 г

Ростов-на-Дону

South Perl

Евгений Торопов

ИП Торопов Е.В

Skoosh - как это работает?(вид снаружи)

Поиск Фильтры Карта Отель Номер Заказ Оплата Счастье есть!

Skoosh - как это работает?(вид изнутри)

Фронтенд: nginx – проксирование и балансирование

Бэкенд: Apache + mod_perl + MySQL 90% нагрузки и 3 сервера из 4 – под поиски (от

посетителей и партнеров)

Сентябрь – Октябрь 2008: 350 – 400 поисков в минуту Средняя продолжительность поиска: 3 секунды

Поиск

Ищем у себя и сапплаеров Каждому сапплаеру по копии процесса

(fork) Результат родителю через Storable::freeze

и временный файл Аггрегация и отдача клиенту

Многозадачность, альтернативы

Параллельные процессы (fork)

Потоки (use threads)

Событийные машины (POE, EV, Event, IO::Async, etc.)

Что-то еще?

Event loop VS Fork

Системный планировщик Ядро событийной машины

Системные процессы Сессии в рамках одного процесса

Квантование времени Логика, описанная программистом

AnyEvent

Унифицированный интерфейс к другим событийным машинам (POE, EV, Event, IO::Async, etc.)

Набор модулей для повседневных нужд (AnyEvent::Handle, AnyEvent::Socket, AnyEvent::HTTP, etc.)

Интеграция с Coro (неожиданный, но приятный сюрприз)

EV, а не POE

Подробно: http://search.cpan.org/~mlehmann/AnyEvent-4.31/lib/AnyEvent.pm#BENCHMARKS

Кратко: EV в среднем в 1000 раз быстрее POE и расходует в 30 раз меньше памяти.

AnyEvent: watchers

Перловый объект, хранящий информацию о нашей реакции на события

События: I/O, timers, signals, child process Аналог сессии в POE

my $w = AnyEvent->timer(after => 7, cb => sub { warn "timeout\n"});

# to cancel the timer:

undef $w;

AnyEvent: условные переменные

# создаем условную переменнуюmy $got_response = AnyEvent->condvar;

http_request "http://www.ya.ru", sub { $got_response->send;};

# входим в событийный цикл и обслуживаем другие# watcher-ы, пока не будет получен ответ$got_response->recv;

Поиск: было

foreach my $supplier_id (keys %$search_suppliers) {

my $pid = fork();

if ($pid) {

$search_suppliers->{$supplier_id} = $pid;

next;

}

my $results = $supplier->check_availability(...);

Stuffed::System::File->new($filename, 'w', {is_binary => 1})

->print(nfreeze($results))->close;

}

Поиск: стало

my $search_finished = AnyEvent->condvar;

foreach my $supplier_id (keys %$search_suppliers) {

my $w = AnyEvent->timer(after => 0, cb => sub {

my $results = $supplier->check_availability(...);

$supplier_results->{$supplier_id} = {

xml => $xml_log,

results => $results,

};

delete $not_finished->{$supplier_id};

$search_finished->send if not %$not_finished;

});

}

$search_finished->recv;

Inside check_availability

my $request_ready = AnyEvent->condvar;AnyEvent::HTTP::http_request( POST => $url, headers => {

... }, timeout => $HTTP_TIMEOUT, body => $xml, sub { $request_ready->send(@_) },);my ($content, $hdr) = $request_ready->recv;

Проблема

$condvar->recv, стоящий в коллбэке, блокирует выполнение до окончания работы коллбэков, запущенных во время ожидания

Решения

Отказ от $condvar->recv, но тогда последовательный код превращается в кашу из колбэков

Coro – да прибудет с вами сила сопрограмм!

Coro

Один процесс – несколько упрощенных perl-интерпретаторов

Сопрограмма определяется уникальным набором: callchain + lexical variables + @_ + $_ + $@ + $/ + C stack

Отсутствие проблем с синхронизацией и блокировками, как в случае с потоками

Coro::AnyEvent

Делает все необходимое для того, чтобы во время событийного цикла происходило переключение не только между watcher-ами, но и между сопрограммами

Поиск – финальный релизmy $search_finished = AnyEvent->condvar;foreach my $supplier_id (keys %$search_suppliers) {

$not_finished->{$supplier_id}->{coro} = new Coro sub {my $results;$results = $supplier->check_availability(...);$supplier_results->{$supplier_id} = {

xml => $xml_log,results => $results,

};delete $not_finished->{$supplier_id};$search_finished->send if not %$not_finished;

}$not_finished->{$supplier_id}->{coro}->ready;

}$search_finished->recv;

Результаты и замечания

Это работает! Нагрузка на поисковых серверах упала в

3-4 раза Coro segfault-ит под mod_perl 2.0.4, зато с

2.0.3 все замечательно Установка Coro, если “повезет”,

сопровождается танцами с бубном (зависит от ОС и версии perl)

Спасибо за внимание!

Торопов Евгений[email protected]