web-dev-qa-db-ja.com

PHP-どうやってやるの?

現在、PHPでジョブキューを実装しようとしています。キューはバッチジョブとして処理され、一部のジョブを並行して処理できるはずです。

私はすでにいくつかの研究を行って、それを実装するいくつかの方法を見つけましたが、それらの長所と短所についてはあまり知りません。

例えば。ここで説明したように、fsockopenを介してスクリプトを数回呼び出して並列処理を実行します。
PHPでの簡単な並列処理

私が見つけた別の方法は、curl_multi関数を使用することでした。
curl_multi_exec PHP docs

しかし、これらの2つの方法は、主にバックグラウンドで実行されるキューでバッチ処理を作成するためのオーバーヘッドをかなり追加すると思いますか?

pcntl_forkについても読みましたが、これも問題を処理する方法のようです。しかし、あなたが何をしているのか本当に分からなければ、それは本当に厄介になる可能性があります(現時点では私のようです;)).

Gearmanも見てきましたが、そこでは、いくつか実行するだけでなく、必要に応じてワーカースレッドを動的に生成し、Gearman Job Serverにそれを無料のワーカーに送信させる必要がありました。特に、1つのジョブが実行された後にスレッドがきれいに終了する必要があるため、最終的にメモリリークが発生することはありません(この問題ではコードが完全ではない場合があります)。
Gearman Getting Started

私の質問は、PHPで並列処理をどのように処理するかです。そして、なぜあなたはあなたの方法を選ぶのですか?異なる方法にはどのような利点/欠点がありますか?

ご意見ありがとうございます。

33
enricog

私はexec()を使用します。その簡単できれい。基本的に、必要なことを行うスレッドマネージャーとスレッドスクリプトを構築する必要があります。

私はfsockopen()が好きではありません。なぜなら、サーバー接続を開きます。

同じ理由でcurl関数が好きではない

pnctlは好きではありません。pnctl拡張機能が必要であり、親子関係を追跡する必要があるためです。

ギアマンと遊んだことはない...

16
Quamis

さて、3つのオプションがあると思います。

A。マルチスレッド:

PHPはマルチスレッドをネイティブにサポートしていません。しかし、pthreads( https://github.com/krakjoe/pthreads )と呼ばれる1つのPHP拡張機能(実験的))があり、これを実行できます。

B。マルチプロセス:

これは、次の3つの方法で実行できます。

  • フォーク
  • コマンドの実行
  • Piping

C。分散並列処理:

仕組み:

  1. Clientアプリは、データ(別名メッセージ)を「JSON形式にすることができます」エンジン(MQエンジン)「Webサービスのローカルまたは外部にすることができます」に送信します
  2. MQ Engineデータを「主にメモリに、オプションでデータベースに」キュー内に保存します(キュー名を定義できます)
  3. Clientアプリは、MQエンジンにデータ(メッセージ)を順番に(FIFOまたは優先度に基づいて)処理するように要求します。「特定のキューからデータを要求することもできます」。


いくつかのMQエンジン:

  • ZeroMQ(良いオプション、使いにくい)メッセージ指向IPCライブラリ、Erlangのメッセージキューサーバー、ジョブをメモリに保存します。同時実行フレームワークとして機能するソケットライブラリです。TCPクラスター製品およびスーパーコンピューティングの場合よりも高速です。
  • RabbitMQ(適切なオプション、使いやすい)セルフホスト、エンタープライズメッセージキュー、実際には作業キューではなく-として使用できるメッセージキュー作業キューですが、追加のセマンティクスが必要です。
  • Beanstalkd(最適なオプション、使いやすい)(Laravelビルトインサポート、facebookで構築、作業キュー用)-「Beanstalkdコンソール」ツールとてもいいです
  • Gearman(問題:分散処理のための集中型ブローカーシステム)
  • Apache ActiveMQJavaで最も人気のあるオープンソースメッセージブローカー(問題:多くのバグと問題)
  • Amazon SQS(Laravelビルトインサポート、ホステッド-管理が不要です。実際にはワークキューではないため、埋め込みなどのセマンティクスを処理するために余分な作業が必要になります。仕事)
  • IronMQ(Laravel組み込みサポート、Goで作成、クラウドバージョンとオンプレミスの両方で利用可能)
  • Redis(Laravel組み込みサポート、そのために設計されていないほど高速ではありません)
  • Sparrow(Ruby memcacheに基づくもので記述)
  • Starling(Ruby Twitterで構築されたmemcacheに基づくもの)
  • Kestrel(ちょうど別のQM)
  • Kafka(ScalaのLinkedInで作成)
  • EagleMQオープンソース、高性能、軽量のキューマネージャー(Cで記述)

それらの多くはここで見つけることができます: http://queues.io

8
Mahmoud Zalt

アプリケーションがunix/linux環境で実行される場合、分岐オプションを選択することをお勧めします。それは基本的に子供がそれを機能させるために遊ぶものです。私はそれをCronマネージャーに使用し、フォークがオプションではない場合にWindowsフレンドリーなコードパスに戻すためのコードを用意しました。

あなたが述べているように、スクリプト全体を数回実行するオプションは、かなりのオーバーヘッドを追加します。スクリプトが小さい場合、問題はないかもしれません。しかし、おそらく、あなたが選択した方法でPHPで並列処理を行うことに慣れるでしょう。そして、次回200MBのデータを使用するジョブがある場合、それは非常に問題になるかもしれません。だから、あなたはあなたが固執できる方法を学ぶ方が良いでしょう。

Gearmanもテストしましたが、とても気に入っています。いくつか考慮すべき点がありますが、全体として、異なる言語で書かれた異なるアプリケーションを実行する異なるサーバーに作品を配布する非常に良い方法を提供します。それを設定することに加えて、実際にPHP内または他の言語からそれを使用することは...もう一度...子どもの遊びです。

あなたが何をする必要があるかについては、それは非常にやり過ぎかもしれません。しかし、データとジョブの処理に関しては、新しい可能性に目が開かれます。そのため、Gearmanを試してみることをお勧めします。

3
inquam

私はPHPのpnctlを使用しています-あなたが何をしているのかを知っている限りそれは良いことです。私はあなたの状況を理解していますが、私たちのコードを理解することは難しいとは思いません。JOBキューまたは並列プロセスを実装するときは、これまで以上に少し意識する必要があります。

あなたがそれを完璧にコーディングし、フローが完全なオフコースであることを確認する限り、実装する際に並列プロセスを念頭に置いておく必要があります。

間違いをする可能性のある場所:

  1. ループ-GLOBAL varで処理できる必要があります。
  2. トランザクションのいくつかのセットを処理します-再び適切なセットを定義する限り、それを完了できるはずです。

この例をご覧ください- https://github.com/rakesh-sankar/Tools/blob/master/PHP/fork-parallel-process.php

それが役に立てば幸い。

2
Rakesh Sankar

私はexec()とギアマンが好きです。 exec()は簡単で、接続がなく、メモリの消費が少ないです。 gearmanにはソケット接続が必要で、ワーカーはいくらかのメモリを使用する必要があります。しかし、gearmanはexec()よりも柔軟で高速です。そして最も重要なのは、ワーカーを他のサーバーに展開できることです。作業が時間とリソースを消費する場合。現在のプロジェクトではギアマンを使用しています。

2
Magic

PHPでの並列処理のいくつかのオプションの概要を以下に示します。

AMP

チェックアウト Amp-単純化された非同期並行性 -これは最も成熟しているように見えるPHP並列処理で見たライブラリ。

Peecのプロセスクラス

このクラスは PHPのexec()関数のコメント に投稿され、新しいプロセスをフォークしてそれらを追跡するための本当の簡単な出発点を提供します。

例:

// You may use status(), start(), and stop(). notice that start() method gets called automatically one time.
$process = new Process('ls -al');

// or if you got the pid, however here only the status() metod will work.
$process = new Process();
$process.setPid(my_pid);

// Then you can start/stop/check status of the job.
$process.stop();
$process.start();
if ($process.status()) {
    echo "The process is currently running";
} else {
    echo "The process is not running.";
}

他のオプションと比較

素晴らしい記事もあります 非同期処理またはPHPのマルチタスク処理 さまざまなアプローチの長所と短所を説明しています:

ドアマン

次に、 (この簡単なチュートリアル もあります。これは Doorman と呼ばれる小さなライブラリにまとめられています。

これらのリンクがより多くの研究の有用な出発点になることを願っています。

1
Simon East

「PHPでの簡単な並列処理」で説明されている方法は、実に怖いです-原則はOKです-しかし、実装?既に指摘したように、curl_multi_ fnsはこのアプローチを実装するより良い方法を提供します。

しかし、私はこれらの2つの方法がかなりのオーバーヘッドを追加すると思います

はい、おそらくあなたは仕事を引き渡すためにクライアントとサーバーのHTTPスタックを必要としません-しかし、Googleで働いていない限り、開発時間はハードウェアコストよりもはるかに高価です-HTTPを管理するためのツールがたくさんあります/ analysing performance-ステータス通知や認証などをカバーする定義済みの標準があります。

ソリューションの実装方法の多くは、必要なレベルのトランザクション整合性と、順序どおりの処理が必要かどうかによって異なります。

あなたが言及したアプローチのうち、curl_multi_を使用したHTTPリクエストメソッドに焦点を当てることをお勧めします。しかし、適切なトランザクション制御/順序配信が必要な場合は、メッセージのソースと処理エージェントの間でブローカーデーモンを必ず実行する必要があります(ブローカーのフレームワークとして使用するのに適した、よく書かれたシングルスレッドサーバーがあります ここ )。処理エージェントは一度に1つのメッセージを処理する必要があることに注意してください。

非常にスケーラブルなソリューションが必要な場合は、 RabbitMQ などの適切なメッセージキューシステムを見てください。

HTH

C.

1
symcbean