ホームページ >バックエンド開発 >PHPチュートリアル >PHP のメモリ オーバーフロー、コマンド ライン、Web サービスの実行方法についての理解

PHP のメモリ オーバーフロー、コマンド ライン、Web サービスの実行方法についての理解

不言
不言オリジナル
2018-05-31 16:53:252085ブラウズ

この記事では主に、PHP のメモリ オーバーフロー、コマンド ライン、Web サービスの 2 つの実行方法について説明します。これは、開発プロセス中に参照できるように、共有します。データベースから読み取られたデータの量が多すぎるため、インターフェイスはステータス 200 を返しますが、応答データはありません。PHP エラー ログには次の情報が含まれています。 PHP 致命的エラー: 許容メモリ サイズ 134217728 バイトが使い果たされました。 。

これは明らかにメモリ不足によるエラーですが、私が困惑しているのは、Yii フレームワークのビジネス ログ (application.log) に出力がなく、ページ上にもスタック トレースのエラー メッセージがないことです。原因を調査してください。

その理由は次のとおりです。まず、Yii フレームワークの CApplication.php ファイルのコア コードを確認してください。

public function run()
{    if($this->hasEventHandler('onBeginRequest'))        
$this->onBeginRequest(new CEvent($this));
    register_shutdown_function(array($this,'end'),0,false);    
    $this->processRequest();    
    if($this->hasEventHandler('onEndRequest'))        
    $this->onEndRequest(new CEvent($this));
}

異常終了が発生したときにコールバックを登録するリクエストを処理する前に、register_shutdown_function を使用します。 、PHP がスクリプトの異常終了を検出すると、end() メソッドがコールバックされます。onEndRequestのリスナーで error_get_last() を使用できます。 > このエラーを取得するイベント。

ただし、OOM が発生すると、Linux のメモリ不足キラーは kill -9 を実行して SIGKILL シグナルを送信します。PHP マニュアルの指示によれば、SIGKILL シグナルをキャプチャして傍受することはできず、PHP スクリプトは直接終了します。クリーンアップ コードは実行されないため、register_shutdown_function メソッドは機能せず、当然、その後のログ記録、エラー ページの表示、その他のプロセスは行われません。 register_shutdown_function 注册异常终止时的回调,正常来说,PHP 出现异常脚本终止时会回调 end() 方法,在 onEndRequest 事件的监听器中可以使用 error_get_last() 获取到本次错误。

但是,当 OOM 发生时,Linux Out Of Memory killer 会执行 kill -9 发送 SIGKILL 信号,根据 PHP 手册中的说明, SIGKILL 信号无法捕获和拦截,PHP 脚本会直接退出,任何清理代码都不会执行,所以 register_shutdown_function 方法不会发挥作用,自然也不会有后续的日志记录、错误页面显示等流程。

另外在开发中注意到一个现象:通过 Web 访问会出现 OOM,但通过 Console 执行就不会报错。

由此可见两种方式是有区别的,Web 访问时,PHP 脚本进程由 PHP-FPM启动,还要受 FPM 配置文件限制,/etc/php-fpm.d里配置文件有 php_admin_value[memory_limit] = 128M 限制。所以通过 Web 访问时,仅增加 php.ini 中的 memory_limit 无效。

而 Console 方式执行不经过 PHP-FPM,所以仅受 php.ini 中配置的内存参数限制,而开发机中配置的 memory_limit => 512M => 512M,所以此时不会产生 OOM。

这里有个疑问,从实现原理的角度,PHP-FPM 是如何对 PHP 进程管理的?PHP-FPM 真的会用 kill -9 杀死 PHP 脚本进程么?


附上 WebServer、PHP-FPM、PHP 脚本的调用关系:

请求首先进入 Web 服务器(如 Nginx),Nginx 分发请求(依据server节点、location节点等配置):

  1. 请求静态资源不需要 FastCGI 处理,直接转到相应文件位置

  2. 动态请求需要 PHP 代码处理,则需要把请求交给实现了 FastCGI 协议的程序(PHP-FPM)

可以在Nginx看到这样的配置信息:“fastcgi_pass 127.0.0.1:9000;”,执行命令“lsof -i:9000”可以看到9000端口刚好是PHP-FPM进程。

Nginx 将请求信息传给了 PHP-FPM,PHP-FPM 分配一个 Worker 进程处理,Worker 进程注册变量 $_GET/$_POST 等,根据请求信息访问指定的 PHP 脚本文件,然后使用 PHP 解释器执行。
(我的理解是:相当于 PHP-FPM 启动了 PHP 解释器,有点像执行了 php -f script.php

さらに、開発中に気づいた現象: Web 経由でアクセスすると OOM が発生しますが、コンソール経由で実行するとエラーが報告されません。

Web にアクセスするとき、PHP スクリプト プロセスは PHP-FPM によって開始され、/etc/php- 内の FPM 設定ファイルによって制限されることがわかります。 fpm.d には php_admin_value[memory_limit] = 128M の制限があります。したがって、php.ini のmemory_limit を単純に増やしても、Web 経由でアクセスする場合は効果がありません。

コンソール モードの実行は PHP-FPM を経由しないため、php.ini で設定されたメモリ パラメーターと、開発マシンで設定された Memory_limit => 512M => 512M によってのみ制限されるため、この時点では OOM は発生しません時間。

ここで質問があります。実装原則の観点から、PHP-FPM はどのように PHP プロセスを管理しますか? PHP-FPM は本当に kill -9 を使用して PHP スクリプト プロセスを強制終了しますか? 🎜
🎜Web サーバー、PHP-FPM、および PHP スクリプト間の呼び出し関係を添付します。🎜🎜 リクエストは最初に Web サーバー (Nginx など) に入り、Nginx がリクエストを分散します (サーバー ノード、ロケーション ノードなどに基づきます。構成): 🎜
  1. 🎜静的リソースのリクエストには FastCGI 処理は必要なく、対応するファイルの場所に直接送信されます🎜
  2. 🎜動的リクエストには PHP コード処理が必要です。FastCGI プロトコル (PHP-FPM) を実装するプログラムにリクエストを渡す必要があります。🎜
🎜この設定情報は次の場所で確認できます。 Nginx: "fastcgi_pass 127.0.0.1:9000;"、コマンド "lsof -i:9000" を実行すると、ポート 9000 が PHP-FPM プロセスであることがわかります。 🎜🎜Nginxはリクエスト情報をPHP-FPMに渡し、PHP-FPMは処理対象のWorkerプロセスを割り当て、変数$_GET/$_POSTなどを登録し、指定されたPHPスクリプトにアクセスします。リクエスト情報に従ってファイルを作成し、PHP インタプリタを使用して実行します。
(私の理解では、これは PHP インタープリタを開始する PHP-FPM と同等であり、php -f script.php コマンドの実行に少し似ています) 🎜🎜ネットワークリクエスト情報はレイヤーに渡されますレイヤーごとに最終的に PHP に到達するので、この HTTP リクエストのさまざまなパラメーターを PHP コードで取得できます。 🎜🎜Nginx は、どの PHP スクリプトを実行するかを PHP-FPM に指示します。Nginx 設定に次の行が表示されます。🎜
fastcgi_param SCRIPT_FILENAME /home/dev_user/www/xxx/webroot/index.php;
🎜PHP ファイルを指定しない場合は、index.php ファイルを使用してみてください。ルートディレクトリにあります。フレームワーク プログラムは、index.php で開始され、フレームワークは対応するコントローラーとアクションを見つけて、実際のビジネス ロジックを完成させます。 🎜

以上がPHP のメモリ オーバーフロー、コマンド ライン、Web サービスの実行方法についての理解の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。