この記事では主に、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</code のリスナーで <code>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节点等配置):
请求静态资源不需要 FastCGI 处理,直接转到相应文件位置
动态请求需要 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
$_GET/$_POST
などを登録し、指定されたPHPスクリプトにアクセスします。リクエスト情報に従ってファイルを作成し、PHP インタプリタを使用して実行します。 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 のメモリ オーバーフロー、コマンド ライン、Web サービスの実行方法についての理解の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。