[Moscow.pm] AnyEven::HTTP перед и после fork с сокетами между процессами

Гришаев Анатолий 0body0 на rambler.ru
Ср Окт 16 02:19:23 PDT 2013


Тут виноват не AnyEvent::HTTP, а AnyEvent::DNS, который используетcя 
AnyEvent::HTTP.

Если чуть изменить ваш примерчик и выкинуть в нем резоливинг 
www.bing.com, например так:

1) добавить сабу.
my $tcp_connect = sub {
     use AnyEvent::Socket ();
     $_[0] = "204.79.197.200"; # ( www.bing.com => 204.79.197.200 )
     &AnyEvent::Socket::tcp_connect( @_ );
};
2) и заменить в нем
=============================
         http_get $URL, persistent => 0,  sub {
             print "+ $_[1]{Status} $_[1]{Reason} $_[1]{URL}; $$\n";
             syswrite $parent, "pong\n";
         };
=============================
на
         http_get $URL, persistent => 0, tcp_connect => $tcp_connect, sub {
             print "+ $_[1]{Status} $_[1]{Reason} $_[1]{URL}; $$\n";
             syswrite $parent, "pong\n";
         };
=============================


то пример начинает работать.
Возможно AnyEvent::DNS хранит сокеты внутри себя...


16.10.2013 4:23, ksvs пишет:
> Вот упрростил до совсем маленького примерчика.
> Запускать так:
> - с первым: time perl ae_http_slow_simple.pl 1
> - без:      time perl ae_http_slow_simple.pl 0
>
> Иногда может повести и "с" отработает быстро.
> У меня "без" отрабатывает до 2 секунд. "С" - обычно 15-30 (хотя может и 2).
>
> Знакомый запускал у себя на линоде, так там было пару раз до 5 минут.
>
> Вот этот пример.
>
>
> $| = 1;
> use strict;
> use warnings;
>
> use EV;
> $EV::FLAG_FORKCHECK = 1;
> use AnyEvent;
> use AnyEvent::HTTP;
>
> my $URL = "http://www.bing.com";
>
> if ($ARGV[0]) {
>      my $w = AnyEvent->condvar;
>      http_get $URL, persistent => 0, keepalive => 0, sub {
>          print ". $_[1]{Status} $_[1]{Reason} $_[1]{URL}; $$\n";
>          $w->send;
>      };
>      $w->recv;
>      print "...\n";
> }
>
> use IO::Socket;
> socketpair(my $child, my $parent, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die "socketpair: $!";
>
> my $kid_pid = fork;
> defined $kid_pid or die "Can't fork: $!";
>
> unless ($kid_pid) {
>      close $child;
>      my $w = AnyEvent->condvar;
>      my $wr = AnyEvent->io(fh => $parent, poll => "r", cb => sub {
>          my $len = sysread $parent, my $buf, 1024;
>          unless ($len) {
>              # print"child EXIT\n";
>              exit;
>          };
>          print $buf;
>
>          http_get $URL, persistent => 0, sub {
>              print "+ $_[1]{Status} $_[1]{Reason} $_[1]{URL}; $$\n";
>              syswrite $parent, "pong\n";
>          };
>      });
>      $w->recv;
>      exit;
> } else {
>      close $parent;
>      my $i = 0;
>      my $w = AnyEvent->condvar;
>      my $wr = AnyEvent->io(fh => $child, poll => "r", cb => sub {
>          sysread $child, my $buf, 1024;
>          # print $buf;
>          if (++$i > 3) {
>              # print "parent EXIT\n";
>              exit;
>          } else {
>              syswrite $child, "ping $i\n";
>          }
>      });
>      syswrite $child, "ping $i\n";
>      $w->recv;
> }
>
>
>
>
>
> On Wednesday, 9 October 2013, 10:03, Nikolay Mishin <mi на ya.ru> wrote:
> а ссылку на пример поиграться?
>
>
> 09.10.2013, 07:26, "ksvs" <ksvs1996 на ymail.com>:
>> Есть приложение, в котором главный процесс и дочерние общаются между собой по сокетам, используя EV модуль.
>> Дочерние процессы получают информацию от главного, делают HTTP запросы, анализируют и возвращают результат главному. В дочерних процессах запросы идут параллельно с использованием либо Net::Curl::Multi, либо AnyEven::HTTP.
>>
>> Все было отлично, пока не понадобилось в главном процессе перед fork, сделать HTTMP запрос. LWP использовать можно, но не хочется.
>> Используемые варианты:
>> 1. Делаем первый запрос при помощи AnyEven::HTTP, дочерние работают с Curl - все отлично. Это для проверки.
>> 2. Делаем первый запрос при помощи AnyEven::HTTP на несуществующий адрес, дочерние работают с AnyEven::HTTP - все нормально.
>> 3. Делаем первый запрос при помощи AnyEven::HTTP на существующий адрес, работа AnyEven::HTTP в дочерних процессах зависает. При этом общение между процессами идет: гонял ping для подтверждения того, что EV не завис и система коммуникаций между процессами жива.
>>
>> Может кто-то сталкивался с таким поведением AnyEven::HTTP?
>>
>> Сделал максимально простой вариант для теста.
>> В нем с первоначальным вызовом AnyEven::HTTP, в дочернем процессе AnyEven::HTTP, стал работать, но очень-очень медленно. Точнее все зависит от того, как карты лягут: без первого вызова время выполнения 1,24 секунды, а с первым - может быть 21 секунд, а может быть 5 секунд.
>>
>> Но ведь с Curl работает отлично. Значит дело не в EV, а в AnyEven::HTTP.
>> Для подтверждения этого вместо первого вызова AnyEven::HTTP, сделал просто открытие сокета, EV::WRITE, EV::READ - все работает отлично.
>>
>> AnyEven::HTTP настраивал, чтобы он закрывал все сокеты. Это перед форком. Да и делается ведь EV::break перед форком.
>>
>> Интересно понять причину этого.
>>
>> ,
>> --
>> Moscow.pm mailing list
>> moscow-pm на pm.org | http://moscow.pm.org


-- 
С уважением Анатолий.


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