2016-12-20 1 views
1

Вот несколько вариантов использования программы Parallel :: ForkManager. Кажется, он останавливается на 200 попытках, иногда около 30, в зависимости от размера запроса pgsql, который собирает URL-адреса для отправки в Mojo :: UserAgent. Кажется, где-то есть какие-то жесткие ограничения? Есть ли лучший способ написать это, чтобы я не сталкивался с этими ограничениями? Машина, на которой работает компьютер, имеет 16 процессоров и 128 ГБ памяти, поэтому она может запустить более 200 процессов, которые будут умирать после таймаута Mojo :: UserAgent, который обычно составляет 2 секунды.Невозможно разблокировать более 200 процессов, иногда, меньше, в зависимости от памяти, использования процессора

use Parallel::ForkManager; 
use Mojo::Base-strict; 
use Mojo::UserAgent; 
use Mojo::Pg; 
use Math::Random::Secure qw(rand irand); 
use POSIX qw(strftime); 
use Socket; 
use GeoIP2::Database::Reader; 
use File::Spec::Functions qw(:ALL); 
use File::Basename qw(dirname); 

use feature 'say'; 


$max_kids = 500; 
sub do_auth { 
... 
     push(@url, $authurl); 
} 


do_auth(); 

my $pm = Parallel::ForkManager->new($max_kids); 

LINKS: 
foreach my $linkarray (@url) { 
    $pm->start and next LINKS; # do the fork 
    my $ua = Mojo::UserAgent->new(max_redirects => 5, timeout => $timeout); 
    $ua->get($url); 
    $pm->finish; 
} 

$pm->wait_all_children; 
+0

Зачем вам fork 200 обрабатывать, когда у вас только 16 процессоров ??? – ThisSuitIsBlackNot

+1

@ThisSuitIsBlackNot, потому что большинство спали, ожидая ответа HTTP. – ikegami

+3

@ajmcello, вам было бы лучше использовать клиент, способный выполнять несколько запросов, не создавая для этого весь процесс (например, [Net :: Curl :: Multi] (http://search.cpan.org/perldoc? Net :: Curl :: Multi)). – ikegami

ответ

0

Для вашего примера кода (выборка URL) Я бы никогда не использовал Forkmanager. Я бы использовал Mojo :: IOLoop :: Delay или неблокирующий стиль вызова.

use Mojo::UserAgent; 
use feature 'say'; 

my $ua = Mojo::UserAgent->new; 

$ua->inactivity_timeout(15); 
$ua->connect_timeout(15); 
$ua->request_timeout(15); 
$ua->max_connections(0); 

my @url = ("http://stackoverflow.com/questions/41253272/joining-a-view-and-a-table-in-mysql", 
      "http://stackoverflow.com/questions/41252594/develop-my-own-website-builder", 
      "http://stackoverflow.com/questions/41251919/chef-mysql-server-configuration", 
      "http://stackoverflow.com/questions/41251689/sql-trigger-update-error", 
      "http://stackoverflow.com/questions/41251369/entity-framework-how-to-add-complex-objects-to-db", 
      "http://stackoverflow.com/questions/41250730/multi-dimensional-array-from-matching-mysql-columns", 
      "http://stackoverflow.com/questions/41250528/search-against-property-in-json-object-using-mysql-5-6", 
      "http://stackoverflow.com/questions/41249593/laravel-time-difference", 
      "http://stackoverflow.com/questions/41249364/variable-not-work-in-where-clause-php-joomla"); 

foreach my $linkarray (@url) { 
    # Run all requests at the same time 
    $ua->get($linkarray => sub { 
    my ($ua, $tx) = @_; 
    say $tx->res->dom->at('title')->text; 
    }); 
} 
Mojo::IOLoop->start unless Mojo::IOLoop->is_running; 
+0

, если есть десятки тысяч URL-адресов, из-за нехватки клиентских портов возникает проблема; как бы вы изменили этот код, чтобы наложить ограничение на количество URL-адресов для извлечения сразу? – ysth

+0

Что произойдет, если URL-адрес медленный или тайм-аут с помощью Mojo :: IOLoop :: Delay? Будет ли он повесить MIOLD, пока URL-адрес не будет закончен, чтобы перейти к следующему? Работает ли MIOLD параллельно или одновременно или синхронно? – ajmcello

+0

Я бы контролировал поток выполнения, объявляя глобальную переменную, называемую «наш $ counter = 0;» затем увеличивайте счетчик перед вызовом неблокирующей функции и уменьшите ее в обратном вызове после завершения выполнения. Когда $ counter достиг определенного максимального ожидания до получения новых URL-адресов. Это просто идея, может работать или нет. – user3606329

-1

Скорее всего, вы используете лимит операционной системы для потоков или процессов. Быстрый и грязный способ исправить это будет увеличить лимит, который обычно настраивается. Тем не менее, переписывание кода, чтобы не использовать так много короткоживущих потоков, является более масштабируемым решением.

Смежные вопросы