PHPは死ぬ

免責事項 :私は10年以上PHP開発をしています。 PHP4がまだ子供で、PHP5がZendの夢だったときに使用し始めました。 彼の助けを借りて、私は多くのことをしました。私は彼を愛し、呪われ、恥ずかしがらずに彼が成長し成長するのを見ました。 私はまだいくつかの継承されたプロジェクトで使用していますが、もう使用しないことを好みます。 また、この記事に記載されているフレームワークまたはツールの作成者と協力していないことにも注意してください。



TL; DR (英語が長すぎます。読みませんでした。だから、特に記事全体を読むのが面倒だと言う-およそ):プロジェクトがバックグラウンドプロセスの機能に基づいている場合(バックグラウンドサービス、デーモン-およそ。 。)PHPを避けます。



私の意見では、ほとんどの場合、PHP嫌いは1つの非常に重要なポイントを見逃しています。PHP は死ぬために作成されました 。 これは、(ある程度)かなり有能なプログラミング言語がどこにも消えないという意味ではありません。 PHPコードが永遠に実行できないことを意味します。 現在、2000年の最初の公式リリースから13年後 、この考えは今でもかなり理にかなっているように思えます。



死にかけているプログラムのモデル



PHPコアは最も単純なワークフローに従います。入力を取得し、処理し、出力を表示し、死にます。 PHP Sadnessのようなサイトは、言語の失敗を特定するのに楽しさと助けになりますが、そのアーキテクチャ全体に最も影響を与えると思います。 しかし、確かに、他の試みがありました。



当初、プロセスの完了(消滅)はWebサイトにとって大きな懸念ではありませんでした。 データベースから何かを読んだり、ロジックを適用したり、データをフォーマットしたりして、大量のHTMLタグの中で結果を表示しました。 このアプローチによってプログラミングの世界にもたらされたすべての恐ろしさにもかかわらず、PHP はいまだに打ち負かすことができません (これはコアの機能です)。 この方法で解決できる問題はすべて解決済みであり、残りの問題はよりインテリジェントで最新のツールで解決できるのは良いことです。そのような小さな機能は通常、大規模で複雑なプロジェクトの一部であるためです。 残念ながら、 PHPは実行後の死を主張します。 そして、反対のことをしようとすると、悪いことが起こります。



単なるウェブサイトではありません



フィードバックフォームからの情報を電子メールで送信することは、PHPにとって依然として大きな課題です。 それには何も問題はありません(まあ、もし私が10年以内にそのようなことを続ければ、おそらくこれは私が以前に非常に悪い決断をしたことを意味するでしょう)。 しかしこれは、すでに数百万通りの方法で何百万回も決定されていることの例でもあります。 実際、他のWebベースの言語またはフレームワークでもこれを実行できます。



この瞬間をスキップしましょう。 現在、実際の複雑なアプリケーションを作成しています。 複雑さとともに、プログラムコードの量は増加しています。 あなたはかなり有能なプログラマーだとしましょう。 PHP 5.xおよび最新のプログラミング方法を使用しています。 インターフェイスとクラスではすべてが非常に抽象的です。 既存のライブラリをどうするか知っています。 現在、独自のORMモデル、サードパーティコード、開発されたインターフェイス、サードパーティのRESTインターフェイス用のクライアントAPI関数などに依存している場合があります。 すべてはPHPで書かれています。



これが悪夢の始まりです。必然的にバックグラウンドでコードを実行する必要があります。 アプリケーションは、HTTPリクエストの完了を待つだけでは不十分なレベルの複雑さに達しました。 次の理由が考えられます。HTTP応答を高速化するには、要求キューまたはキャッシュ情報を処理する必要があります。 定期的に必須の支払いを確認し、結果に基づいて行動するか、外部ソースから受信したデータを常に更新する必要があります。 また、パフォーマンスの低下を防ぐために、データパケット全体をデータベースに書き込む必要があります。 いくつかのネットワーク接続を作成して開いたままにするか、WebSocketアプリケーションのサーバー部分の作業を実行する必要がある場合があります。 これらは単なる例であり、開発しているものに応じて無限にリストできます。



インタラクティブに呼び出す



ただし、上記の最悪の実装は非常に馴染みがあるように見えます。PHPや選択したフレームワークに必要なものは関係ありません-確かに、月5ドルのホスティングにはSSHアクセス、cronユーティリティ、または同様のツールがありません。



どのソリューションが最も簡単ですか? もちろん、バックグラウンドからインタラクティブにタスクを転送してください! n番目のページ訪問ごとにランダムに実行します(ページ訪問の1 / n-オリジナル)。 ランダム訪問者は、システム全体のバックグラウンドタスクの完了を待つことに時間を費やし、その完了後にのみユーザーの個人的な要求が処理されます。 多くの「深刻な」および「開発された」フレームワークには 、このプロセスに関与するコードセクションを見つけるだけでなく、それらの織り合わせを理解することも非常に難しいため、最初にそのような関数が組み込まれているという考えに驚くようになります。



それで、問題は何ですか? まず、特別なサーバーアクセスパラメーターは必要ありません。 かなり古く、優れた、洗練されていないFTP。 第二に、すべてがクライアントの要求に応じて機能し、わずかな遅延はクライアントには見えません。 そのため、障害が確実に発生します。テスト中はすべて正常に機能し、実装段階でも優れていますが、実際の負荷ではいです。 数分間隔でタスクを開始するのに必要な数の訪問があると思われます。 しかし、数百のサンプルの疑似ランダム性は、毎分数千のクエリと比較することはできません 。 特定の時間後に開始する必要があるタスクは、実際には瞬きして数回処理されます。 面白いことが起こり始めます。たとえば、同じタスクが同時に開始および終了する、複数のプロセスがロックメカニズムを使用して共有リソースにアクセスしようとするとエラーが発生するなどです。 プロセスの異常終了は、ご存知のようにPHPが死に、その後ユーザーのリクエストを含む他のすべてが終了するため、リクエストされたページをロードできなくなることにも留意してください。 この場合、死は成功を保証するものではありません。



かなり冒険好きなら、バックグラウンドプロセスをcronハンドラのタスクリストに移動できます。 これはすでに優れています。十分な時間があるときに機能します。 この場合、制御変数は1つだけです。 再帰的なタスクの場合(ここでの再帰はcrondデーモンのコアの本質です)、常に1つのタスクが完了してから再び呼び出されると想定しています。 ほとんどの場合、これは事実であることが判明する可能性がありますが、一方で、サーバーの負荷が増加した場合はスケジューラー間隔を調整する必要がある場合があります、またはそれらのいずれかが十分に長い時間実行されることを期待しますアプリケーション。 システム全体では、この方法は非常に複雑になる場合があります。 この時点で、システム全体のタスクを個別のパッケージに分割することをすでに考えています。 しかし、誰かがこれに目を光らせなければなりません。



悪魔を召喚



悪魔またはより粘り強いプロセスの作成が正しい解決策であると思われるときに、本当の悪夢が始まります。 確認には、 WebSocket接続の確立と維持、またはメーカーと消費者のコンポーネントの作成が含まれます。



しかし、PHPはあなたを失望させます。



PHPが適さないタスクがいくつかあります。 PHPは、どのように防止しようとしても死にかけていることを忘れないでください。 1つはメモリリークの問題です。 PHPは、使用されなくなった場合にリリースすることを決して気にしません。なぜなら、すべては終了後(死後)に解放されるからです。 継続的に実行されるプロセスでは、 割り当てられたメモリ(実際には空です)は、しきい値memory_limitに達するまで蓄積されます。 その後、プロセスは警告なしに完了します。 このプロセスが永遠に続くと予想されない限り、問題はあなたにありません。 実際の負荷の下で、「遅い」プロセスを「 かなり速い 」プロセスに置き換えます。



もちろん、「メモリを浪費しないでください」という点で改善はありましたが、十分ではありませんでした。 複雑さが増すか負荷が増えるとすぐに、すべてが壊れます。 次のコードスニペットを検討してください。



class FOO {
    public $f;
}

class BAR {
    public $f;
}

while(1) {
    $a = new FOO();
    $b = new BAR();
    $a->f = $b;
    $b->f = $a;
    print "Memory usage: " . number_format(memory_get_usage(true)) . " bytes\n";
    unset($a);
    unset($b);
}

      
      





, , , . , PHP , , , , unset().



. , , , . , , , : ORM. , , , , . , . , … , ? PHP , , , , , PHP .



, PHP, : ( ) . (Garbage collection — .) PHP 5.3 . : «, ?». 2009 , . ? . , PHP , , , . PHP, — .





. PHP , :



Fatal error: Exception thrown without a stack frame in Unknown on line 0

      
      





? , . 0 PHP-. , , . , PHP. , , : , , . .



, . . PHP , . .





? , PHP — web- ( «yes, i'm a hyred keyboard» — . .) — . , ; , , , , . , , PHP , . , , .



Python, virtualenv, Flask, Supervisor Gunicorn. , , — -. , . : ? , Python . , . , . , PHP .





, . , memory_limit . cron, shell- UNIX. PHP web-, — . , , , , , , , . , 30- .



, , , - PHP. , , , PHP 5.4 PHP 5.5 .



, .



HN Reddit.






All Articles