web-dev-qa-db-ja.com

pcntl_forkはPHPでどのように機能しますか?

私は混乱しています pcntl_fork PHPでは。

マルチスレッドを実行すると思いますが、どのように機能し、スクリプトでどのように使用しますか?

19
user1432856

PCNTLはスレッドを作成できません。現在のPHPプロセスを「フォーク」するだけです。どういう意味ですか?pcntl_fork()を呼び出すと、現在のプロセスは2つのプロセスに分割されます。親プロセスの名前名全体がにコピーされます。子と両方のプロセスは、1つの違いだけで並行して実行を続行します。つまり、pcntl_fork()は子のPIDを親に返し、0を子に返します。

いくつかのヒント:

  • デフォルトでは無効になっています。それを有効にできた場合は、CLIに対してのみ実行してください。 Webサーバーで使用しないでください。非決定論的な方法で動作します。また、マシン全体をダウンさせる可能性もあります。無効のままにして、読み進めてください。
  • プロセス間の通信は可能ですが、恐ろしいものです(共有メモリ内のシリアル化されたオブジェクトを介して)。
  • ファイル記述子(およびデータベース接続)は共有されているため、問題が頻繁に発生します。 フォークした後にDBを再接続する必要があります。そうしないと、最初のプロセスが接続を閉じるときに、すべてのフォークされたプロセスからMySQL server has gone awayのようなエラーが発生します。
  • 親プロセスは、子プロセスが終了するのを待つ必要があります。そうしないと、ゾンビプロセスがシステムリソースを消費することになります。

ここに例があります ドキュメントから

<?php

$pid = pcntl_fork();
if ($pid == -1) {
     die('could not fork');
} else if ($pid) {
     // we are the parent
     pcntl_wait($status); //Protect against Zombie children
} else {
     // we are the child
}

ただし、PHPは単なるスクリプト言語です。並列コンピューティング用には設計されていません。必要に応じて、CRON、メッセージキュー、またはプログラムを低レベル言語で同時に実行することで、より良い仕事をすることができます。

Forked PHPプログラムは、読み、理解し、デバッグするのが非常に困難です。そのプログラムを維持することは悪夢になります。

間違えないで、分岐しないでください。あなたはそれを必要としません。本当に必要なのは非同期タスクランナーです。朗報です。 RabbitMQ素敵なチュートリアル ;-) Bunny という有望なRabbitMQライブラリを試すこともできます。

PS:フォークの代わりにメッセージキューを使用すると、もう1つの利点があります。複数のサーバーでキューを処理し、トラフィックの増加に応じて水平方向に拡張できます。

編集2019-03-07

私は非同期同時実行フレームワークamphpで多くのことをしましたが、ここで言及する必要があります。非同期の非ブロッキングタスクを1回のリクエストで実行する必要がある場合は、amphpが今日の最良のソリューションであると考えています。これは、phpジェネレーター($value = yield $promise)の概念を使用して、reactphpのようなpromisehellなしで人間が読めるコードを実行します。

https://amphp.org/

42
Martin Strouhal