ホームページ  >  記事  >  バックエンド開発  >  [転送]ブラウザが終了した後もphpは実行され続けますか? ,php は実行を継続します_PHP チュートリアル

[転送]ブラウザが終了した後もphpは実行され続けますか? ,php は実行を継続します_PHP チュートリアル

WBOY
WBOYオリジナル
2016-07-12 08:52:34738ブラウズ

[転送]ブラウザを終了した後もphpは実行され続けますか? 、php は実行を継続します

元のリンク: http://www.cnblogs.com/yjf512/p/5362025.html

前提: ここで話しているのは、典型的な lnmp 構造、nginx+php-fpm モードです

コード内に sleep() が含まれていても実行が非常に遅い php プログラムがある場合、ブラウザがサービスに接続すると php-fpm プロセスが開始されますが、この時点でブラウザが閉じていると、このとき、サーバー上の php-fpm プロセスは実行され続けますか?

今日はこの問題を解決します。

最も簡単な実験

最も簡単な方法は、プログラムを書いてみましょう: file_put_contents を使用してスリープの前後にログを書き込みます:

リーリー

実際の操作の結果は、サーバーがスリープしている間にクライアントのブラウザを閉じると、ログに 2222 が書き込まれることになります。

これは、ブラウザを閉じた後もサーバー側の PHP は引き続き実行されることを意味しますか?

ignore_user_abort

Lao Wang と diogin は、これが php のignore_user_abort 関数に関連している可能性があることを思い出させてくれました。

そこで、コードを次のように少し変更しました:

リーリー

ソフトウェアの使用がないことがわかり、ignore_user_abort がどのような値に設定されても実行され続けます。

しかしここで質問があります: user_abort とは何ですか?

このドキュメントでは、PHP スクリプトが実行され、ユーザーがスクリプトを終了すると、中断がトリガーされることが明確に説明されています。次に、スクリプトは、ignore_user_abort に基づいて実行を継続するかどうかを決定します。

しかし、公式ドキュメントには CGI モードでの中止について明確に記載されていません。クライアントが切断されても、CGI モードの PHP はアボートを受け取らないようです。
Ignore_user_abort は CGI モードでは効果がありませんか?

心拍の問題ですか?

最初に思い浮かぶのは心拍の問題でしょうか?ブラウザ クライアントを切断することは、クライアントを閉じずに接続を切断することと同じであり、サーバーは TCP キープアライブを検出する前に到着するのを待つ必要があります。

まず、ブラウザ設定でキープアライブの問題をトラブルシューティングする必要があります。

ブラウザを放棄してクライアント プログラムを作成します。プログラムは http サービスに接続した後、ヘッダーを送信し、接続をアクティブに閉じる前に 1 秒間スリープします。ただし、このプログラムには http キープアライブ ヘッダーがありません。

手順は以下の通りです

リーリー

サーバープログラム:

リーリー

ignore_user_abort が設定されているかどうかに関係なく、PHP は依然として同じであることがわかりました。どうやら、ignore_user_abort はまだ有効になっていないようです。

ignore_user_abort をトリガーする方法

ignore_user_abort をトリガーするにはどうすればよいですか?サーバーはこのソケットが使用できないことをどのようにして知るのでしょうか? Lao Wang と Diogin は、ソケットが使用できるかどうかを判断するために、サーバーがソケットと積極的に対話する必要があるかどうかを尋ねました。

さらに、PHP には connection_status と connection_aborted という 2 つのメソッドが用意されており、どちらも現在の接続ステータスを検出できることもわかりました。したがって、コードのログ行は次のように変更できます:

リーリー

手動接続処理の表示に従って、現在の接続ステータスを印刷できます。

以下には、ソケットと対話するプログラムがありません。echo を使用します。フラッシュの影響を排除するために、後でフラッシュすることを忘れないでください。

プログラムは次のように変更されます:

リーリー

わかりました。前に作成したクライアントを実行します。観察記録:

リーリー

ついに中止されました。ログには、今後数回の中止ステータスが 1 であることも示されています。

しかし、ここで何か奇妙なことがあります。最初の 2 つの接続ステータスのステータスが 0 (正常) のままなのはなぜですか。

RST

Wireshark を使用してパケットをキャプチャし、クライアントとサーバー間の対話プロセス全体を確認します

このプロセス全体では 14 パケットのみが送信されます。サーバーが初めて 22222 を送信したときに、クライアントが RST を返すことを見てみましょう。それ以降のパッケージ要求はありません。

クライアントとサーバー間のおおよその対話プロセスは次のとおりです。

サーバーがループで初めて 2222 を送信すると、クライアントは切断され、RST を返しますが、この送信プロセスは成功したリクエストとみなされます。サーバーが再度このソケットで書き込み操作を実行する必要があるときまで、このソケットはネットワーク送信を実行せず、接続ステータスが中止であることを直接返します。したがって、上記の状況が発生したのは最初の 222 のステータスが 0 で、中止が発生したのは 2 回目でした。

確認してください

strace php -S XXX を使用して検証することもできます

プロセス全体の strace ログは次のとおりです:

リーリー

ステータスが0から1に変化するところを見てみましょう。

<code class="hljs erlang">...
<span class="hljs-function"><span class="hljs-title">sendto<span class="hljs-params">(<span class="hljs-number">4, <span class="hljs-string">"22222", <span class="hljs-number">5, <span class="hljs-number">0, NULL, <span class="hljs-number">0)       = 5
...
<span class="hljs-title">write<span class="hljs-params">(<span class="hljs-number">5, <span class="hljs-string">"2 connection status: 0abort:0\n", <span class="hljs-number">30) = 30
<span class="hljs-title">close<span class="hljs-params">(<span class="hljs-number">5)                                = 0
<span class="hljs-title">rt_sigprocmask<span class="hljs-params">(SIG_BLOCK, [CHLD], [], <span class="hljs-number">8) = 0
<span class="hljs-title">rt_sigaction<span class="hljs-params">(SIGCHLD, NULL, {SIG_DFL, [], <span class="hljs-number">0}, <span class="hljs-number">8) = 0
<span class="hljs-title">rt_sigprocmask<span class="hljs-params">(SIG_SETMASK, [], NULL, <span class="hljs-number">8) = 0
<span class="hljs-title">nanosleep<span class="hljs-params">({<span class="hljs-number">1, <span class="hljs-number">0}, <span class="hljs-number">0x7fff60a40290)       = 0
<span class="hljs-title">sendto<span class="hljs-params">(<span class="hljs-number">4, <span class="hljs-string">"22222", <span class="hljs-number">5, <span class="hljs-number">0, NULL, <span class="hljs-number">0)       = -1 EPIPE <span class="hljs-params">(Broken pipe)
--- SIGPIPE {<span class="hljs-title">si_signo=SIGPIPE, <span class="hljs-title">si_code=SI_USER, <span class="hljs-title">si_pid=2819, <span class="hljs-title">si_uid=0} ---
<span class="hljs-title">open<span class="hljs-params">(<span class="hljs-string">"/tmp/test.log", O_WRONLY|O_CREAT|O_APPEND, <span class="hljs-number">0666) = 5
<span class="hljs-title">fstat<span class="hljs-params">(<span class="hljs-number">5, {st_mode=S_IFREG|<span class="hljs-number">0644, st_size=<span class="hljs-number">49873711, ...}) = 0
<span class="hljs-title">lseek<span class="hljs-params">(<span class="hljs-number">5, <span class="hljs-number">0, SEEK_CUR)                   = 0
<span class="hljs-title">lseek<span class="hljs-params">(<span class="hljs-number">5, <span class="hljs-number">0, SEEK_CUR)                   = 0
<span class="hljs-title">flock<span class="hljs-params">(<span class="hljs-number">5, LOCK_EX)                       = 0
<span class="hljs-title">write<span class="hljs-params">(<span class="hljs-number">5, <span class="hljs-string">"2 connection status: 1abort:1\n", <span class="hljs-number">30) = 30
<span class="hljs-title">close<span class="hljs-params">(<span class="hljs-number">5)                                = 0</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>

第二次往socket中发送2222的时候显示了Broken pipe。这就是程序告诉我们,这个socket已经不能使用了,顺便php中的connection_status就会被设置为1了。后续的写操作也都不会再执行了。

总结

正常情况下,如果客户端client异常推出了,服务端的程序还是会继续执行,直到与IO进行了两次交互操作。服务端发现客户端已经断开连接,这个 时候会触发一个user_abort,如果这个没有设置ignore_user_abort,那么这个php-fpm的程序才会被中断。

至此,问题结了。

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/1126842.htmlTechArticle[转]浏览器退出之后php还会继续执行么?,php继续执行 原文链接:http://www.cnblogs.com/yjf512/p/5362025.html 前提:这里说的是典型的lnmp结构,ng...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。