2016-12-20 5 views
1

ここでは、Parallel :: ForkManagerを使用するプログラムの欠点を示します。これは、Mojo :: UserAgentに送信するURLを収集するpgsqlクエリのサイズに応じて、200プロセス(時には約30)で停止するようです。どこか厳しい制限があるようですね?私はこれらの制限に遭遇しないようにこれを書くための良い方法がありますか?稼働しているマシンは16のCPUと128GBのメモリを持っているため、Mojo :: UserAgentのタイムアウト(通常は2秒)後に200を超える処理が確実に実行されます。メモリ、CPU使用量に応じて、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

16個のCPUしか持っていないと、200個のプロセスをフォークするのはなぜですか? – 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またはnon-blockingの呼び出しスタイルを使用します。

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

Mojo :: IOLoop :: DelayでURLが遅くなったりタイムアウトするとどうなりますか?次のURLに入るためにURLが完成するまでMIOLDをハングアップしますか? MIOLDは並行して処理されるのか、同時に処理されるのか、同期して処理されますか – ajmcello

+0

私は "our $ counter = 0;"というグローバル変数を宣言して実行フローを制御します。ノンブロッキング関数を呼び出す前にカウンタをインクリメントし、実行が終了したらコールバックでデクリメントします。新しいURLを取得する前に$ counterが定義された最大待機に達したとき。それは単なるアイデアであり、うまくいくかどうかはわかりません。 – user3606329

-1

ほとんどの場合、スレッドまたはプロセスのオペレーティングシステムの制限を実行している可能性があります。これを修正するための迅速かつ汚れた方法は、通常は設定可能な制限を増やすことです。つまり、短命のスレッドをあまり使わないようにコードを書き直すことは、よりスケーラブルな解決策です。

関連する問題