トニックスはますます頑丈になっていますが、それが何であるかはわかりませんが、トニックスは一般的なマルチモジュラー CMS については、おそらくその 構造と部品 (迅速な概要).
上記の構造とパーツを読んで、その色相に感謝するときはいつでも、私はスポンサーやプロジェクトの方法をさらに進めるための資金のために購入しています。あなたはレジャーツールのエンジニアリング、構造の組み立てに関連する仕事をしている、またはあなたはおそらく私に手を差し伸べなければならない別の手を必要としています:
olayemi@tonics.app
または devsrealmer@gmail.com ガイドラインを守って… ではMotorway To Launch カテゴリに関する 1 日の詳細では、Tonics Job と Agenda Supervisor を管理するデーモンに取り組んでいるときに気づいた最も簡単なプラクティスと方法をいくつか紹介します。
ちょっと動こう…
稼働時間の長いプロジェクトに PHP を使用することについての懸念
多くの人々は、PHP がデーモンを構築するのに不健康である、または長期にわたる責任があることを考慮に入れています。それは、PHP は Web ファッションにとって繰り返し古いものであり、通常は動的なオンライン ページの作成に関連しています。 PHP を長時間実行する役割やデーモン プロセスに使用することに関して、よく言われる問題の 2 つには、さまざまな要因があります。メモリ管理 (ガベージ コレクタはほとんどの場合メモリ リークを引き起こす可能性があり、長時間実行されるプロセスでは問題となります)、リソース消費、および安定性を備えています。
ただし、これらの要因は通常、慎重なコーディングの実践、システム ソースの正しい採用、および実行中のプロセスの積極的な監視と保守によって対処できます。
PHP をデーモンや長時間実行する役割に使用することに対するもう 1 つの古典的な批判は、低レベルのシステム プログラミング用に最適化される他の言語ほどパフォーマンスが良くないというものです。 C または Plod として。 確かな雇用インスタンスでのこの主張にはいくつかの真実もありますが、本当の事実は、PHP は、適切に古代に使用され、明示的な責任のために最適化されている場合、非常にパフォーマンスが高くなる可能性があるということです.
さらに、多くのビルダーは、デーモンとフォークの根底にある原則を完全に認識できなくなっており、そのようなシナリオで PHP を回避するという異常な知恵を観察することしかできないことも注目に値します.
私の意見では、応用科学を調査して実験することで、確実な結論に進むことができると信じています。これにより、時間と時間を節約できました。要約すると、PHP は長期実行プロセスとデーモンを構築するための強力なツールになり、すべての雰囲気が成功し、適切になります。 それはさておき、重大な古典的誤りの 1 つと、間違いなく最も優れた慣習や方法を調べてみましょう。 おそらく展開する必要があります…
一般的な間違い #1: フォーキングの扱いの誤り
pcntl_fork は、一部の責任を安全なプロセスに分割するために長期実行プロセスで繰り返し採用されています。分岐として、プロセスを 2 つの同じにもかかわらず別々のプロセスに分割します。 しかし、分岐はトリッキーであり、民俗起源の古典的なエラーがあります。これは、実行時間の長いプロセスまたはデーモンの原因となる可能性があります。 そのような間違いの 1 つは、フォーク プロセスを正常に処理できなくなったことであり、突然の行為やクラッシュさえも引き起こします。図、ファイル記述子 (およびデータベース接続) は、フォーク後に親プロセスと隣接プロセスの間で共有されます。親プロセスまたは隣接プロセスがファイル記述子またはデータベース接続を閉じた場合、これはさらに他のプロセスで閉じられる可能性があり、間違いなく詳細の破損を引き起こします。または他の要因.
どうやって
pcntl_fork は PHP で動作します一例を出品する前に、こんな方法があります pcntl_fork
作品:
$pID=pcntl_fork();if ($pID===-1){
exit(1);
}// これは親プロセスですかif ($pID){ // 親プロセスの実行を進める
}// これは 1 プロセスのチャンクですか if ($pID===0){
// 勝利を収める...前の1つのプロセス
出口;
}機能
pcntl_fork ()
は、最新のプロセスの複製を作成し、親プロセスを作成しますおよび1プロセスのチャンク。 pcntl_fork()
変数は親プロセスと隣接プロセスで決められたラベルを埋めます.親プロセスのラベルの様式と、そのプロセスのラベルを含む $pID 変数を拡張させてください…
いつ pcntl_fork()
は、最新のプロセスの複製。 ここが魅力的なところですb親プロセスと隣接するプロセスの両方が、
の後に同じコードの実行を続行します。 pcntl_fork()機能名、それにもかかわらず のラベル$pID はすべてのプロセスの流行になります. 親プロセスでは、$pID は作成直後になった次のプロセスのプロセス ID に設計されますが、別のプロセスでは $pID は設計されます。 これにより、コードは親プロセスと隣接するプロセスの間で悲鳴を上げ、コードのように勝利を収めることができます。 詳しく説明すると、pcntl_fork() f eature はブランドの異常なプロセスを作成し、親プロセスと派生プロセスのそれぞれが、pcntl_fork() 機能がすぐに知られるようになった場所から同じコードの実行を続行します。
適応は、彼らが $pID の値のファッションを持っていることです.コードブロックに賭ける:
最初の観察評価の場合
pcntl_fork() 機能がすぐに役立つようになりました。 そうでない場合、このデバイスはエラー コード 1 で終了します。 $pID
は、親プロセスでは true です。 そうである場合、このデバイスは、親プロセスのコードである if ブロック内のコードを実行します。観測評価の場合 $pIDのラベルかどうか は、1 つ前のプロセスでは 0 です。 そうである場合、このデバイスは、if ブロック内のコードを実行します。これは、1 つのプロセスのコードです。 exiguous one プロセスの終了時の exit 監視により、exiguous one プロセスが親コードの実行を続行しないことが保証されます。 あなたがおそらく仲介しなければならないのはどうしてですか? 1 つ前のプロセスでは、1 つ前のプロセスのコードを実行した後、次のコードを実行する可能性があります。 if ブロックの後、場所 $pID がチェックされ、0 であることが発見されました。親プロセスからのより長いコードでは、そのプロセスを実行した後に、1 つのプロセスを終了するための終了監視が古くなっています。終了監視により、1 つ前のプロセスがそのまま実行を終了するため、親プロセスでその後に続くコードの実行は続行されなくなります。 PHP でフォークが誤って処理される例
そこにはフォークの見栄えの良い採用例についてですが、1つは、同時に複数のプロセスを通過することを防御することであり、おそらくプロセスの発明をスピードアップします.
例として、ログ ファイルに行を追加するスクリプトがあり、このスクリプトを 10 個のイベントを同時に追跡したいとします。
これを達成するには、おそらく pcntl_fork() スクリプトの個別のイベントを実行する、複数の一連の 1 つのプロセスを作成する PHP の機能 最後のプロセスは、元のファイル記述子とともに、親プロセスのメモリの複製を継承するため、他のプロセスに干渉することなく、すべて同じログ ファイルに書き込みます。 )ここに例があります: 既存: 私は sleep(rand(...)) 機能を使用して、いくつかの謎めいた人が時間がかかるという議論の余地のない真実をシミュレートします他の人より抜ける $fp=fopen("ログを見てください", "a"); $pIDS=; for ($i=0; $i <10; +$i) { $ pID=pcntl_fork(); if ($pID==-1) { 死にます("おそらくおそらくおそらくさらにフォークプロセスはもうありません。");
} そうでなければ ($pID) { // 親プロセス $pIDS=$pID; } 他の {
// 1 つのプロセスが残っている スリープ(2);
fwrite($fp, "Baby process ".$i." running.n"); sleep(rand(2, 10)); exit(0); }
}
fclose($fp);
出口();
上記のコードが正常に実行された場合、次のものを取得する必要があります:赤ちゃんプロセス 0 が実行中です。赤ちゃんプロセス 1 が実行中です.ベイビープロセス2実行中.
赤ちゃんプロセス 3 が実行中です。
ベビープロセス 4 が実行中です。 ベイビープロセス 5 が実行中です。 ベイビープロセス 6 が実行中です。 赤ちゃんのプロセス 7 が実行されています。
赤ちゃんのプロセス 8 が実行されています。ベイビープロセス 9 が実行中です。コードだけだと、もうフィールドなんてないでしょ、正直?
さらに、フォークされたプロセス間でファイル記述子を共有しても、上記で確認したこととは反対のフィールドが存在しないように見えることはなくなります。今のところはサポートを続けましょう。なぜ共有するのかを後で理解する必要があります。フォークされたプロセス間のファイル記述子は、実際にはそれほど鮮明ではありません.問題を簡単に保護するには、l何が起こっているのかをグラフィカルに調査して勝利を収めましょう: ここで起きていることは、親プロセスは、すべての 1 つのプロセスが完了するよりも早く終了しました (一方、タイトルでプロセスを調べます: php bin/console --traipse --onStartUp
、それは親 o あなたの下のティーンエイジャー全体の場合、しばらくすると終了します.
このシナリオで起こることは、 1 つのプロセスが孤児 (親のないプロセス) になり、1 のチャンクが孤児になると、他のすべてのプロセスに採用される可能性が高くなります。 異常な親プロセスが実行されており、そのプロセスに対処しようとしている限り、彼らは責任を全うするか、異常な親プロセスによって終了されるまで実行を続けることができます.ほとんどの場合、孤立したプロセスの異常な親プロセスは init プロセスです。 init プロセスは、システム プロセスの管理を担当します。 孤立したプロセスを処理し、固有の親プロセスがそうで勝利できない場合、すべての孤立したプロセスに対処するように設計されています。ただし、これが必ずしも最も重要な init プロセス (PID 1) であるとは限らないことを指摘することは不可欠です。場合によっては、明示的な顧客またはコースの孤立したプロセスに対処するために、サブ初期化プロセスも構成されます。 このビデオをよく見ていると、私が WSL を使用していて、ターミナルの複数のインスタンスを作成することに成功していることに気付くでしょう。ブランドとは異なる端末を作成すると、通常、その端末に対してブランドとは異なるログイン セッションが作成されます。 ログインセッションは、その端末にリンクされるプロセスを管理する責任があり、通常、そのセッションの孤立したプロセスを処理するサブ初期化プロセスにリンクされます.そのため、1 つのプロセスのチャンクがそのセッションで孤立した場合、おそらく最も不可欠な init プロセスではなく、そのセッションにリンクされたサブ init プロセスによって採用される可能性があります。 これにより、サブ初期化プロセスは、そのセッションに明示的なプロセスに目を向けることができ、間違いなく最も不可欠な初期化プロセスが、複数のコースからの孤立したプロセスで圧倒されることがなくなります。 その端末のサブ init を無駄にするたびに、それがさらに端末イベントを破壊するように見えます.ポイントはあなたが親プロセスが、その元の 1 つのプロセスがすべて完全になる前に終了すると、元の 1 つのプロセスは孤立し、他のすべてのプロセスによって採用されます。 これも必ずしも迅速な検討の理由にはなりませんが、将来的に要因が生じる可能性が最も高いでしょう. 1 つのプロセスのチャンクが孤立すると、プロセスを実行する適性を持つ他のすべてのプロセスに採用される可能性が高くなります。これは、異常な親プロセスも、ガイドラインやソースを利用して、効率性要因、リソース リーク、またはセキュリティ リスクなどの考慮事項につながることを意味します。さらに、他のすべてのプロセスを頼りに、あなたの重要なプロセスに目を向けることで、発生する要因を追跡してトラブルシューティングすることができます.あなたの謎のプロセスの1つで間違いなく状態が発生した場合、どのプロセスが責任を負うかを特定するのが最も可能性が高いです。複数のプロセスがあなたの重要なプロセスを管理していますプロセス。プロセスとその管理を強力にサポートしているため、発生する要因をトラブルシューティングします。 、ここに修理があります: $fp=fopen("ログを見てください", "a");$pIDS=; for ($i=0; $i <10; +$i) {
$ pID=pcntl_fork(); if ($pID==-1) { 死にます("おそらくおそらくおそらくさらにフォークプロセスはもうありません。");
} そうでなければ ($pID) { // 親プロセス $pIDS=$pID; } 他の {
// 1 つのプロセスが残っている スリープ(2);
fwrite($fp, "Baby process ".$i." running.n"); sleep(rand(2, 10)); exit(0); }} foreach ($pID としての $pIDS) { pcntl_waitpid ($pID, $design);}fclose($fp);出口();
上記のコードの修復には、親プロセスがすべての 1 つのプロセスを確実に待機するようにすることで、1 つのプロセスを正常に管理する必要があります。 ここで、 pcntl_waitpid ループ内で、すべての隣接する 1 つのプロセスが完了するまで待機する機能
エラーを修正する修復方法の内訳は次のとおりです:
重要なプロセスを効果的に管理する: pcntl_waitpid
は、親プロセスがすべての隣接する 1 つのプロセスが完全になるのをより早く待機することを保証します。終了します。 これにより、孤立した単一のプロセスが回避され、親プロセスがその単一のプロセスを正常に管理できるようになります。
- fclose転送中: 識別コードでは、
fclose()
憧れよりも早く知られるようになりました重大なものは全体に処理されます。 実装コードでは、 fclose() は、隣接する 1 つのプロセスがすべて完了するのを待つループの後であると理解されます
Comely exit: の追加出口() スクリプトの終了時に、スクリプトが正常に終了することを保証し、スクリプトが実行された後、残りの 1 つのプロセスが引き続き追跡されるのを防ぎます。ここにビデオ付きのイラストがあります: また、今回は、親が終了するよりも早く、その前のプロセスのすべてが完了するのを待っていることにも気付くはずです.
一般的な間違い #2: フォーキング プロパティの扱いの誤りすべき o PHP でプロセスをフォークすると、フォークされた (exiguous プロセス) プロセスは、親からすべての変数とソースをファイル記述子と共に継承します。 繰り返しになりますが、ファイル記述子を分割するために仲介する必要があると思われます。親であり、唯一のプロセスである場合、おそらく永続的に機能することも、その中で勝利を収めることも適切ではない可能性があります。 ここでは、ソースがデータベース接続を高く評価する方法で非常に堅実です.より安全な面であるためには、リソースを開始して閉じてください.すべてのExigous 1プロセスが共有リソースを頼りにせずにその安全な要求に対処できるため、これはスケーラビリティをサポートすることさえできます. つまり、前のコードの有害な方法は次のとおりです: 破損例 - ファイルのオープンとクローズ $fp=fopen("ログを見てください", "a");$IDS=; for ($i=0; $i <10; +$i) { $ pID=pcntl_fork(); if ($pID==-1) { 死にます("おそらくおそらくおそらくさらにフォークプロセスはもうありません。");
} そうでなければ ($pID) { // 親プロセス $pIDS=$pID; } 他の {
// 1 つのプロセスが残っている スリープ(2);
fwrite($fp, "Baby process " . $i . " running.n"); sleep(rand(2, 10)); exit(0); }} foreach ($pID としての $pIDS) { pcntl_waitpid ($pID, $design);}fclose($fp);出口();
そして、ここに美しいマナーがあります:
実際のブループリント - 開閉ファイル
$pIDS=; for ($i=0; $i <10; +$i) {
$ pID=pcntl_fork(); if ($pID==-1) { 死にます("可能 y たぶん、おそらく、さらにフォークプロセスはもうありません。");
} そうでなければ ($pID) { // 親プロセス $pIDS=$pID; } 他の {
// 1 つのプロセスが残っている スリープ(2);
$fp=fopen("ログを見てください", "a");
fwrite($fp, "赤ちゃんのプロセス " . $i . " n");
fclose($ fp); スリープ(rand(2, 10 )); exit(0);
}}foreach ($pID を $pID として) { pcntl_waitpid($pID, $design); }出口();
まさにここに、あらゆる腐敗した美しい提案を示す他のすべての例がありますforkされたプロセスを処理するときにデータベース接続を開く破損例 - データベースのオープンとクローズ繋がり
$db=db();$pIDS=; for ($i=0; $i <10; +$i) { $ pID=pcntl_fork(); if ($pID==-1) { 死ぬ("できたfork プロセスではありません。"); } else if ($pID) { // 親プロセス
$pIDS=$pID; } 他の {
// 子プロセス
echo $db->Select('*')->From("tonics_global") ->Restrict(1)->FetchFirst()?->key; sleep(rand(2, 10));
exit(0); }}foreach ($pID を $pID として) {
pcntl_waitpid($pID, $design);
}
$db->getTonicsQueryBuilder()->destroyPdoConnection();出口();
一方、ファイルを開き、同じファイル記述子を使用すると機能します異なるフォークされたプロセスでは、データベース接続を監視しなくなります。たとえば、1 つの分岐プロセスが閉じるとすぐに、db 接続がダウンします。 、これは、それを利用するために検索する他のプロセスに影響を与えますが、これに打ち勝ち、おそらくエラーも取得する必要があります。 修理は、1 つのプロセスで必要なリソースに目を向けることをサポートすることです:実際の例 - データベース接続の開始と終了
$pIDS=; for ($i=0; $i <10; +$i) { $ pID=pcntl_fork(); if ($pID==-1) { 死ぬ("できたfork プロセスではありません。"); } else if ($pID) { // 親プロセス
$pIDS=$pID; } 他の {
// 子プロセス
$db=db(); echo $db->Select('*')->From("tonics_global")->Restrict (1)->FetchFirst()?->キー;
echo "n"; $デシベル->getTonicsQueryBuilder()->destroyPdoConnection();
sleep(rand(2, 10)); exit(0); }}foreach ($pID を $pID として) { pcntl_waitpid($pID, $design);} 出口();
あなたがしなければならないこととしておそらく見栄えがしますが、これは前の1つのプロセスでdb接続を開き、実行中と同じ速さで開きます med, 我々は PDO 接続を破壊することによってそれを閉じます (pdo オブジェクトを null にする環境), このブループリント, 我々はゾンビの MySQL プロセスを明らかにします. 一般的な間違い #3: PHP デーモンを長引かせる PHP デーモン プロセスが無期限に停止または実行されると、メモリの多様性が生じる可能性があります。 -時間の経過とともにアップします。 これは PHP の話です。ガベージで構成されたほとんどのプログラミング言語を高く評価し、変数、配列、オブジェクト、およびその他の詳細構造に動的にメモリを割り当てます。 デーモン プロセスが実際に長時間実行される場合、さまざまな責任のためにメモリを継続的に割り当てる可能性が高く、そのメモリを正常に生成できなくなると、システムはメモリを使い果たす可能性があります。これにより、場合によっては、システム上の他のプロセスが停止したり、手持ちのメモリ不足に起因する破壊が発生したりすることがあります.さらに、残留デーモンは、ファイル ハンドル、コミュニティ ソケット、データベース接続など、他の種類のソースをランク付けすることもできます。 さらに、これらのソースは時間の経過とともに枯渇し、システムが不安定になる可能性があります.問題のクルーズは、メモリを解放する方法、おそらく手動でガベージコレクションを行うと、メモリの蓄積に進む可能性が最も高いため、修復は、おそらく数秒後(おそらく1時間)または確実なメモリを超えた後に、デーモンを正常に再起動することです.
美しい再起動の意味を広げてみましょう:
従来のシナリオでは、親プロセスは複数のプロセスを生成することもできます ここで、親プロセスが終了または再起動するための予約を受け取った場合 (例:アプリの更新が使用されている場合)、最初に発生する必要があるのは、正常にシャットダウンするために、その前の 1 つのプロセスに取り分けて送信する必要があります。 この保留は、保留される SIGTERM の発明になります。これにより、終了する前に、必要なクリーンアップで重要なプロセスが勝利することができます。
このクリーンアップ フラグメントのすべてを通じて、exigous 1 プロセスは詳細を閉じ、共有ソースを生成し、バッファをフラッシュし、フラクチャ出口よりも早く他のクリーンアップ責任を作成できます。
これにより、ぶら下がっているプロセスやソースが解放されたままになることがなくなります。そうでなければ、このデバイスのその後の再起動を介してすべての青写真を考慮に入れることができます。 . 残りのプロセスがすべて終了するとすぐに、親プロセスは安全に終了でき、このデバイスは再起動されます。おそらく
も採用する必要があります)systemD デーモンの監視をサポートします (単に mu st おそらく、デーモンがダウンしたためすぐにロボットで再起動するように構成します)、おそらくこれを使用する必要があります pcntl_alarm 時刻を設計するプロセスを終了させたい場合、終了が実行されるとすぐに、pcntl_alarm を 0 に設定して、おそらく恐怖を取り消す必要があるようにします。 極端な言い方をすると、親は
SIGTERM すべての重要な 1 つのプロセスを保留にします。これは、プロセスが再起動しようとしているため、正常にシャットダウンするように指示しています。 pcntl_signal と に注目SIGTERM.このチュートリアルは予想以上に長くなってしまったので、Tonics で実行されるブループリントの採用ケースで急速に球体化します。 .私は実際にプロセスを正常にシャットダウンするためのいくつかの指針を残して喜んでおり、長引くことを防ぎます。残留を防ぐための具体的なコード例を含む詳細。おそらくコメントを残す必要があります。 既存: インディケータの非同期処理について触れていませんでした。また、親プロセスで特定の 1 つのプロセスが完全になるのを待つ必要はありませんが、それらが実行されたときに非同期にシャットダウンする一方で、その要素で勝利を収めることができますが、上記の例は従来の雇用インスタンスに適しています.
Train Case: How Tonics Net page up The Job and Agenda Supervisor with PHP Daemon Tonics CMS には、JobManager と ScheduleManager という 2 つのタイプのジョブがあります。 JobManager は急速な責任のために設計されています。つまり、安価な時間内に完了することが期待されます。その例は Jo です。 b は、個人にリセットの電子メールを送信する役割を担っています。一方、ScheduleManagerそれにもかかわらず、これは仕事の発明であり、長期にわたる責任のために想定されています.また、明示的なイベントと間隔で追跡するようにスケジュールされています。 例として、アジェンダはネストされます。他のすべてが実行された後のtraipse。 さらに、ScheduleManager は責任に優先順位を付けることができるため、どの責任を最初に実行する必要があるかを検索できます。例予定されているジョブは アプリ更新 、 時代遅れのクラスのパージ ), 一時記録データの削除、 定期的に API を呼び出してジョブを昇格させる スケジュールに合わせて繰り返されるものは他にもたくさんあります。
JobManager と ScheduleManager の両方が Transporter によって管理されます。 Tonics のデフォルトのトランスポートは DatabaseTransport ですが、使用したいもの (インメモリなど) を追加する必要があると思われます)。お仕事についてマネージャー、すべてのジョブを同じプロセスで次々と実行する DatabaseJobTransporter があり、すべてのジョブに対してブランドの異常なプロセスをスピンオフすることはありません。 このブループリントは、完全に高速であると予想されるジョブに適しています。責任を実行します。 スケジュールされたすべてのジョブは安全なプロセスにスピンオフされ、ScheduleManager が並行して追跡できるようになります。 このブループリントは、すべてのプロセスが安全なリモート プロセスで実行されるため、全体に時間がかかる責任に対して正直です. また、トランスポーターとスーパーバイザーがどのように機能するかのコード全体を指摘することはできませんが、それが機能する青写真についての信念を提供したいと思います。まず、次の画像から始めましょう:
OnStartUpCLI 2 つの命令を余分にスピンする金切り声 (1 つのプロセスが処理するもの): ScheduleManager と ジョブマネージャー .
以前に認めたように、スケジュールされたジョブは安全なプロセスで分割されます。 t おそらく色目 Core_DiscoverUpdate 親の下 ScheduleManager .ちなみに、JobManagerは一通りのプロセスを回しておらず、ささやきの次から次へと歩き回っています、あるいは、これはは、JobManager の DefaultTransport で動作する方法です。そのため、自分の方法で電源を入れる方法を考えると、おそらく、方法を和らげるためにアーキテクチャ上の理由を交換する必要があります.
次のクエリは、ソフトウェア モジュールに異常な更新または調整がある場合に、モジュールまたはアプリの異常な更新を観察した場合、どのように勝利を収めることができるでしょうか?これは、デフォルトでは、デーモンの監視をサポートするための使用法でもあると思われるものに依存する可能性があります。 Tonics 用の systemD プロバイダー ファイルであり、製品は cts と企業は、restart_service.json として知られているファイルに目を通します。 、取引があるときはいつでも、ファイルのテルは更新される可能性がありますが、タイムスタンプを使用しているため、通知が更新されると、プロバイダー ウォッチャーがそれを検出し、プロバイダー ファイルを再起動します。 再起動があると、SystemD は取っておいた SIGTERM を送信します。私たちはそれを聞いて、何をしていても正常にシャットダウンし、その後自動的に再起動します。ここにビデオデモがあります: 以上です.質問があるとき、または仕事を守るために防御しなければならないときはいつでも私と一緒に、私に手を差し伸べてください: olayemi@tonics.app または devsrealmer@gmail.com
$pID
は、親プロセスでは true です。 そうである場合、このデバイスは、親プロセスのコードである if ブロック内のコードを実行します。観測評価の場合 $pIDのラベルかどうか は、1 つ前のプロセスでは 0 です。 そうである場合、このデバイスは、if ブロック内のコードを実行します。これは、1 つのプロセスのコードです。 exiguous one プロセスの終了時の exit 監視により、exiguous one プロセスが親コードの実行を続行しないことが保証されます。 あなたがおそらく仲介しなければならないのはどうしてですか? 1 つ前のプロセスでは、1 つ前のプロセスのコードを実行した後、次のコードを実行する可能性があります。 if ブロックの後、場所 $pID がチェックされ、0 であることが発見されました。親プロセスからのより長いコードでは、そのプロセスを実行した後に、1 つのプロセスを終了するための終了監視が古くなっています。終了監視により、1 つ前のプロセスがそのまま実行を終了するため、親プロセスでその後に続くコードの実行は続行されなくなります。PHP でフォークが誤って処理される例
そこにはフォークの見栄えの良い採用例についてですが、1つは、同時に複数のプロセスを通過することを防御することであり、おそらくプロセスの発明をスピードアップします.
例として、ログ ファイルに行を追加するスクリプトがあり、このスクリプトを 10 個のイベントを同時に追跡したいとします。
スクリプトの個別のイベントを実行する、複数の一連の 1 つのプロセスを作成する PHP の機能 最後のプロセスは、元のファイル記述子とともに、親プロセスのメモリの複製を継承するため、他のプロセスに干渉することなく、すべて同じログ ファイルに書き込みます。 )ここに例があります: 既存: 私は sleep(rand(...)) 機能を使用して、いくつかの謎めいた人が時間がかかるという議論の余地のない真実をシミュレートします他の人より抜ける $fp=fopen("ログを見てください", "a"); $pIDS=; for ($i=0; $i <10; +$i) { $ pID=pcntl_fork(); if ($pID==-1) { 死にます("おそらくおそらくおそらくさらにフォークプロセスはもうありません。");
} そうでなければ ($pID) { // 親プロセス $pIDS=$pID; } 他の {
// 1 つのプロセスが残っている スリープ(2);
fwrite($fp, "Baby process ".$i." running.n"); sleep(rand(2, 10)); exit(0); }
}
fclose($fp);
出口();
上記のコードが正常に実行された場合、次のものを取得する必要があります:赤ちゃんプロセス 0 が実行中です。赤ちゃんプロセス 1 が実行中です.ベイビープロセス2実行中.
$ pID=pcntl_fork();fclose($fp);if ($pID==-1) {死にます("おそらくおそらくおそらくさらにフォークプロセスはもうありません。");
} そうでなければ ($pID) {// 親プロセス $pIDS=$pID; } 他の {
// 1 つのプロセスが残っている スリープ(2);
fwrite($fp, "Baby process ".$i." running.n");sleep(rand(2, 10));
exit(0); }
}
出口();
赤ちゃんプロセス 3 が実行中です。
ベビープロセス 4 が実行中です。 ベイビープロセス 5 が実行中です。 ベイビープロセス 6 が実行中です。 赤ちゃんのプロセス 7 が実行されています。
赤ちゃんのプロセス 8 が実行されています。ベイビープロセス 9 が実行中です。
コードだけだと、もうフィールドなんてないでしょ、正直?
さらに、フォークされたプロセス間でファイル記述子を共有しても、上記で確認したこととは反対のフィールドが存在しないように見えることはなくなります。今のところはサポートを続けましょう。なぜ共有するのかを後で理解する必要があります。フォークされたプロセス間のファイル記述子は、実際にはそれほど鮮明ではありません.問題を簡単に保護するには、l何が起こっているのかをグラフィカルに調査して勝利を収めましょう: ここで起きていることは、親プロセスは、すべての 1 つのプロセスが完了するよりも早く終了しました (一方、タイトルでプロセスを調べます:
php bin/console --traipse --onStartUp
、それは親 o あなたの下のティーンエイジャー全体の場合、しばらくすると終了します.
このシナリオで起こることは、 1 つのプロセスが孤児 (親のないプロセス) になり、1 のチャンクが孤児になると、他のすべてのプロセスに採用される可能性が高くなります。 異常な親プロセスが実行されており、そのプロセスに対処しようとしている限り、彼らは責任を全うするか、異常な親プロセスによって終了されるまで実行を続けることができます.ほとんどの場合、孤立したプロセスの異常な親プロセスは init プロセスです。 init プロセスは、システム プロセスの管理を担当します。 孤立したプロセスを処理し、固有の親プロセスがそうで勝利できない場合、すべての孤立したプロセスに対処するように設計されています。ただし、これが必ずしも最も重要な init プロセス (PID 1) であるとは限らないことを指摘することは不可欠です。場合によっては、明示的な顧客またはコースの孤立したプロセスに対処するために、サブ初期化プロセスも構成されます。 このビデオをよく見ていると、私が WSL を使用していて、ターミナルの複数のインスタンスを作成することに成功していることに気付くでしょう。ブランドとは異なる端末を作成すると、通常、その端末に対してブランドとは異なるログイン セッションが作成されます。 ログインセッションは、その端末にリンクされるプロセスを管理する責任があり、通常、そのセッションの孤立したプロセスを処理するサブ初期化プロセスにリンクされます.そのため、1 つのプロセスのチャンクがそのセッションで孤立した場合、おそらく最も不可欠な init プロセスではなく、そのセッションにリンクされたサブ init プロセスによって採用される可能性があります。 これにより、サブ初期化プロセスは、そのセッションに明示的なプロセスに目を向けることができ、間違いなく最も不可欠な初期化プロセスが、複数のコースからの孤立したプロセスで圧倒されることがなくなります。 その端末のサブ init を無駄にするたびに、それがさらに端末イベントを破壊するように見えます.ポイントはあなたが親プロセスが、その元の 1 つのプロセスがすべて完全になる前に終了すると、元の 1 つのプロセスは孤立し、他のすべてのプロセスによって採用されます。 これも必ずしも迅速な検討の理由にはなりませんが、将来的に要因が生じる可能性が最も高いでしょう. 1 つのプロセスのチャンクが孤立すると、プロセスを実行する適性を持つ他のすべてのプロセスに採用される可能性が高くなります。これは、異常な親プロセスも、ガイドラインやソースを利用して、効率性要因、リソース リーク、またはセキュリティ リスクなどの考慮事項につながることを意味します。さらに、他のすべてのプロセスを頼りに、あなたの重要なプロセスに目を向けることで、発生する要因を追跡してトラブルシューティングすることができます.あなたの謎のプロセスの1つで間違いなく状態が発生した場合、どのプロセスが責任を負うかを特定するのが最も可能性が高いです。複数のプロセスがあなたの重要なプロセスを管理していますプロセス。プロセスとその管理を強力にサポートしているため、発生する要因をトラブルシューティングします。 、ここに修理があります: $fp=fopen("ログを見てください", "a");$pIDS=; for ($i=0; $i <10; +$i) {
$ pID=pcntl_fork();if ($pID==-1) {死にます("おそらくおそらくおそらくさらにフォークプロセスはもうありません。");
} そうでなければ ($pID) {// 親プロセス $pIDS=$pID; } 他の {
// 1 つのプロセスが残っている スリープ(2);
fwrite($fp, "Baby process ".$i." running.n");sleep(rand(2, 10));
exit(0); }} foreach ($pID としての $pIDS) {
pcntl_waitpid ($pID, $design);}fclose($fp);出口();上記のコードの修復には、親プロセスがすべての 1 つのプロセスを確実に待機するようにすることで、1 つのプロセスを正常に管理する必要があります。 ここで、
pcntl_waitpid ループ内で、すべての隣接する 1 つのプロセスが完了するまで待機する機能
エラーを修正する修復方法の内訳は次のとおりです:
重要なプロセスを効果的に管理する:
pcntl_waitpid
は、親プロセスがすべての隣接する 1 つのプロセスが完全になるのをより早く待機することを保証します。終了します。 これにより、孤立した単一のプロセスが回避され、親プロセスがその単一のプロセスを正常に管理できるようになります。- fclose転送中: 識別コードでは、
fclose()
憧れよりも早く知られるようになりました重大なものは全体に処理されます。 実装コードでは、
fclose()
は、隣接する 1 つのプロセスがすべて完了するのを待つループの後であると理解されます
Comely exit: の追加出口() スクリプトの終了時に、スクリプトが正常に終了することを保証し、スクリプトが実行された後、残りの 1 つのプロセスが引き続き追跡されるのを防ぎます。ここにビデオ付きのイラストがあります: また、今回は、親が終了するよりも早く、その前のプロセスのすべてが完了するのを待っていることにも気付くはずです.
一般的な間違い #2: フォーキング プロパティの扱いの誤り
すべき o PHP でプロセスをフォークすると、フォークされた (exiguous プロセス) プロセスは、親からすべての変数とソースをファイル記述子と共に継承します。 繰り返しになりますが、ファイル記述子を分割するために仲介する必要があると思われます。親であり、唯一のプロセスである場合、おそらく永続的に機能することも、その中で勝利を収めることも適切ではない可能性があります。 ここでは、ソースがデータベース接続を高く評価する方法で非常に堅実です.より安全な面であるためには、リソースを開始して閉じてください.すべてのExigous 1プロセスが共有リソースを頼りにせずにその安全な要求に対処できるため、これはスケーラビリティをサポートすることさえできます. つまり、前のコードの有害な方法は次のとおりです:
破損例 - ファイルのオープンとクローズ
$fp=fopen("ログを見てください", "a");$IDS=; for ($i=0; $i <10; +$i) {$ pID=pcntl_fork();if ($pID==-1) {死にます("おそらくおそらくおそらくさらにフォークプロセスはもうありません。");
} そうでなければ ($pID) {// 親プロセス $pIDS=$pID; } 他の {
// 1 つのプロセスが残っている スリープ(2);
fwrite($fp, "Baby process " . $i . " running.n");sleep(rand(2, 10));
exit(0); }} foreach ($pID としての $pIDS) {
pcntl_waitpid ($pID, $design);}fclose($fp);出口();そして、ここに美しいマナーがあります:
実際のブループリント - 開閉ファイル
$pIDS=; for ($i=0; $i <10; +$i) {
$ pID=pcntl_fork();if ($pID==-1) {死にます("可能 y たぶん、おそらく、さらにフォークプロセスはもうありません。");
} そうでなければ ($pID) {// 親プロセス $pIDS=$pID; } 他の {
// 1 つのプロセスが残っている スリープ(2);
$fp=fopen("ログを見てください", "a");fwrite($fp, "赤ちゃんのプロセス " . $i . " n");
fclose($ fp); スリープ(rand(2, 10 ));exit(0);
}}foreach ($pID を $pID として) { pcntl_waitpid($pID, $design); }出口();
まさにここに、あらゆる腐敗した美しい提案を示す他のすべての例がありますforkされたプロセスを処理するときにデータベース接続を開く破損例 - データベースのオープンとクローズ繋がり
$db->getTonicsQueryBuilder()->destroyPdoConnection();
$db=db();$pIDS=; for ($i=0; $i <10; +$i) {$ pID=pcntl_fork();if ($pID==-1) {死ぬ("できたfork プロセスではありません。");} else if ($pID) {// 親プロセス
$pIDS=$pID; } 他の {
// 子プロセス
echo $db->Select('*')->From("tonics_global") ->Restrict(1)->FetchFirst()?->key;sleep(rand(2, 10));
exit(0); }}foreach ($pID を $pID として) {pcntl_waitpid($pID, $design);
}
出口();
一方、ファイルを開き、同じファイル記述子を使用すると機能します異なるフォークされたプロセスでは、データベース接続を監視しなくなります。たとえば、1 つの分岐プロセスが閉じるとすぐに、db 接続がダウンします。 、これは、それを利用するために検索する他のプロセスに影響を与えますが、これに打ち勝ち、おそらくエラーも取得する必要があります。 修理は、1 つのプロセスで必要なリソースに目を向けることをサポートすることです:実際の例 - データベース接続の開始と終了
$pIDS=; for ($i=0; $i <10; +$i) {
$ pID=pcntl_fork();if ($pID==-1) {死ぬ("できたfork プロセスではありません。");} else if ($pID) {// 親プロセス
$pIDS=$pID; } 他の {
// 子プロセス
$db=db(); echo $db->Select('*')->From("tonics_global")->Restrict (1)->FetchFirst()?->キー;
echo "n";$デシベル->getTonicsQueryBuilder()->destroyPdoConnection();
sleep(rand(2, 10));exit(0);
}}foreach ($pID を $pID として) {pcntl_waitpid($pID, $design);}
出口();
あなたがしなければならないこととしておそらく見栄えがしますが、これは前の1つのプロセスでdb接続を開き、実行中と同じ速さで開きます med, 我々は PDO 接続を破壊することによってそれを閉じます (pdo オブジェクトを null にする環境), このブループリント, 我々はゾンビの MySQL プロセスを明らかにします. 一般的な間違い #3: PHP デーモンを長引かせる PHP デーモン プロセスが無期限に停止または実行されると、メモリの多様性が生じる可能性があります。 -時間の経過とともにアップします。 これは PHP の話です。ガベージで構成されたほとんどのプログラミング言語を高く評価し、変数、配列、オブジェクト、およびその他の詳細構造に動的にメモリを割り当てます。 デーモン プロセスが実際に長時間実行される場合、さまざまな責任のためにメモリを継続的に割り当てる可能性が高く、そのメモリを正常に生成できなくなると、システムはメモリを使い果たす可能性があります。これにより、場合によっては、システム上の他のプロセスが停止したり、手持ちのメモリ不足に起因する破壊が発生したりすることがあります.さらに、残留デーモンは、ファイル ハンドル、コミュニティ ソケット、データベース接続など、他の種類のソースをランク付けすることもできます。 さらに、これらのソースは時間の経過とともに枯渇し、システムが不安定になる可能性があります.問題のクルーズは、メモリを解放する方法、おそらく手動でガベージコレクションを行うと、メモリの蓄積に進む可能性が最も高いため、修復は、おそらく数秒後(おそらく1時間)または確実なメモリを超えた後に、デーモンを正常に再起動することです.
美しい再起動の意味を広げてみましょう:
従来のシナリオでは、親プロセスは複数のプロセスを生成することもできます ここで、親プロセスが終了または再起動するための予約を受け取った場合 (例:アプリの更新が使用されている場合)、最初に発生する必要があるのは、正常にシャットダウンするために、その前の 1 つのプロセスに取り分けて送信する必要があります。 この保留は、保留される SIGTERM の発明になります。これにより、終了する前に、必要なクリーンアップで重要なプロセスが勝利することができます。
このクリーンアップ フラグメントのすべてを通じて、exigous 1 プロセスは詳細を閉じ、共有ソースを生成し、バッファをフラッシュし、フラクチャ出口よりも早く他のクリーンアップ責任を作成できます。
これにより、ぶら下がっているプロセスやソースが解放されたままになることがなくなります。そうでなければ、このデバイスのその後の再起動を介してすべての青写真を考慮に入れることができます。 . 残りのプロセスがすべて終了するとすぐに、親プロセスは安全に終了でき、このデバイスは再起動されます。 おそらく
も採用する必要があります)systemD デーモンの監視をサポートします (単に mu st おそらく、デーモンがダウンしたためすぐにロボットで再起動するように構成します)、おそらくこれを使用する必要があります pcntl_alarm 時刻を設計するプロセスを終了させたい場合、終了が実行されるとすぐに、
pcntl_alarm を 0 に設定して、おそらく恐怖を取り消す必要があるようにします。 極端な言い方をすると、親は
SIGTERMすべての重要な 1 つのプロセスを保留にします。これは、プロセスが再起動しようとしているため、正常にシャットダウンするように指示しています。 pcntl_signal と に注目SIGTERM.このチュートリアルは予想以上に長くなってしまったので、Tonics で実行されるブループリントの採用ケースで急速に球体化します。 .私は実際にプロセスを正常にシャットダウンするためのいくつかの指針を残して喜んでおり、長引くことを防ぎます。残留を防ぐための具体的なコード例を含む詳細。おそらくコメントを残す必要があります。
既存: インディケータの非同期処理について触れていませんでした。また、親プロセスで特定の 1 つのプロセスが完全になるのを待つ必要はありませんが、それらが実行されたときに非同期にシャットダウンする一方で、その要素で勝利を収めることができますが、上記の例は従来の雇用インスタンスに適しています.
Train Case: How Tonics Net page up The Job and Agenda Supervisor with PHP Daemon Tonics CMS には、JobManager と ScheduleManager という 2 つのタイプのジョブがあります。
JobManager は急速な責任のために設計されています。つまり、安価な時間内に完了することが期待されます。その例は Jo です。 b は、個人にリセットの電子メールを送信する役割を担っています。一方、ScheduleManagerそれにもかかわらず、これは仕事の発明であり、長期にわたる責任のために想定されています.また、明示的なイベントと間隔で追跡するようにスケジュールされています。 例として、アジェンダはネストされます。他のすべてが実行された後のtraipse。 さらに、ScheduleManager は責任に優先順位を付けることができるため、どの責任を最初に実行する必要があるかを検索できます。例予定されているジョブは アプリ更新 、 時代遅れのクラスのパージ
OnStartUpCLI 2 つの命令を余分にスピンする金切り声 (1 つのプロセスが処理するもの): ScheduleManager と),
JobManager と ScheduleManager の両方が Transporter によって管理されます。 Tonics のデフォルトのトランスポートは DatabaseTransport ですが、使用したいもの (インメモリなど) を追加する必要があると思われます)。一時記録データの削除
、 定期的に API を呼び出してジョブを昇格させる スケジュールに合わせて繰り返されるものは他にもたくさんあります。
お仕事についてマネージャー、すべてのジョブを同じプロセスで次々と実行する DatabaseJobTransporter があり、すべてのジョブに対してブランドの異常なプロセスをスピンオフすることはありません。 このブループリントは、完全に高速であると予想されるジョブに適しています。責任を実行します。 スケジュールされたすべてのジョブは安全なプロセスにスピンオフされ、ScheduleManager が並行して追跡できるようになります。 このブループリントは、すべてのプロセスが安全なリモート プロセスで実行されるため、全体に時間がかかる責任に対して正直です. また、トランスポーターとスーパーバイザーがどのように機能するかのコード全体を指摘することはできませんが、それが機能する青写真についての信念を提供したいと思います。まず、次の画像から始めましょう:
ジョブマネージャー .
以前に認めたように、スケジュールされたジョブは安全なプロセスで分割されます。 t おそらく色目Core_DiscoverUpdate 親の下 ScheduleManager .ちなみに、JobManagerは一通りのプロセスを回しておらず、ささやきの次から次へと歩き回っています、あるいは、これはは、JobManager の DefaultTransport で動作する方法です。そのため、自分の方法で電源を入れる方法を考えると、おそらく、方法を和らげるためにアーキテクチャ上の理由を交換する必要があります.
次のクエリは、ソフトウェア モジュールに異常な更新または調整がある場合に、モジュールまたはアプリの異常な更新を観察した場合、どのように勝利を収めることができるでしょうか?これは、デフォルトでは、デーモンの監視をサポートするための使用法でもあると思われるものに依存する可能性があります。 Tonics 用の systemD プロバイダー ファイルであり、製品は cts と企業は、
restart_service.json として知られているファイルに目を通します。 、取引があるときはいつでも、ファイルのテルは更新される可能性がありますが、タイムスタンプを使用しているため、通知が更新されると、プロバイダー ウォッチャーがそれを検出し、プロバイダー ファイルを再起動します。 再起動があると、SystemD は取っておいた SIGTERM を送信します。私たちはそれを聞いて、何をしていても正常にシャットダウンし、その後自動的に再起動します。ここにビデオデモがあります: 以上です.質問があるとき、または仕事を守るために防御しなければならないときはいつでも私と一緒に、私に手を差し伸べてください: olayemi@tonics.app または devsrealmer@gmail.com