PHPバッファとは何ですか?

伊谢尔伦
伊谢尔伦オリジナル
2017-06-23 14:22:481715ブラウズ

バッファとは何ですか?
簡単に言うと、バッファの機能は、入力または出力の内容を表示したり読み取ったりせずに、最初にメモリに入れることです。なぜバッファがあるのか​​というと、これは非常に広範な質問です。興味のある方は、Web サイトで情報をご覧ください
実際、バッファの最も重要な役割は、高速 CPU と比較的低速な IO デバイス (ディスクなど) の動作を調整することです

PHP はどこで役に立ちますか。
PHPのバッファを理解したい場合は、PHP実行時にバッファがどこに設定されているかを知る必要があります。
PHPを実行する際、echo print_rなどのデータを出力するコードに遭遇すると、PHPは出力するデータをPHP自身のバッファに入れて出力を待ちます
PHP自身のバッファがバッファの内容を出力する命令を受け取ると、バッファ内のデータを apache に出力し、apacheはPHPが出力したデータを受け取ります。 Apache が独自のバッファにデータを格納し、出力されるまで待機します。Apache が命令を受け取り、バッファの内容のみを出力したい場合は、ブラウザに戻ります。

PHP がデータを出力したいとき、2 つのバッファー (最初は独自のバッファー、次に Apache のバッファー) を通過してからブラウザーに戻ることがわかりました。

バッファーは PHP で開始されます。何が行われるのでしょうか?

1.ヘッダー関数を使用する前に一部のデータが出力されているため、次のような特定のエラーが発生します。ヘッダー情報は既に送信されています。このエラーの理由は、はい、ヘッダーの前に一部のデータが出力されています。このデータを出力すると同時に、Apache はブラウザに応答ステータスを送信します (出力があるため、リクエストは有効です)。その後、再試行します。header 関数
を使用して http ヘッダーを送信すると、このエラーが発生しますエラーは、HTTP ヘッダーが送信され、それを変更できないことを意味します。

バッファーを使用すると、ヘッダー関数が発生しても影響を受けないためです。 , PHP はすぐに Apache を実行して、この http ヘッダーをブラウザに送信します。

PHP が出力バッファを開いた後、出力データがバッファに保存されます。これにより、以前に発生したエラーを回避できます。 2. PHP を介してファイル ダウンロード プログラムを作成する場合
ファイルのダウンロードをより安全にし、制御性を向上させるために、多くの友人が PHP を使用してファイルのダウンロード ページを作成することを好みます。原理は非常に簡単です。 fwrite を介してコンテンツを送信し、ヘッダーを介して HTTP ヘッダーを送信して、これが添付ファイルであることをブラウザーに知らせます。このようにして、上記の方法を使用するとダウンロード ページが提供されます。ファイルが非常に大きい場合、たとえば 100M の場合、バッファ出力をオンにせずに 100M のデータをすべて読み取ってから、一度にページに戻す必要があります。すべてのデータが読み取られるまで応答が得られません
。これにより、ユーザー エクスペリエンスが低下します。
出力バッファがオンになっている場合、PHP プログラムはファイルの特定のセクションの読み取りを完了すると、すぐに Apache に出力します。 Apache がすぐにブラウザに戻るようにすると、後続のデータはどうなるでしょうか? ファイルをセクションごとに読み取るたびに、セクションが読み込まれるまですぐに出力されます。すべてのファイルが出力されるまで、ブラウザーはすべてのファイルが読み取られるまで待つことなくデータを受信し続けることができます

さらに、このアプローチは、たとえば、ファイルが 100M である場合の別の非常に深刻な問題も解決します。バッファの場合、100M のファイルをすべてメモリに読み込んでから出力する必要があります。ただし、PHP プログラムにメモリ制限がある場合は、サーバーの安定性を確保するために、通常、 PHP 実行のメモリの制限 (php.ini の合計memory_limit による、デフォルト値は 8M)。つまり、各 PHP プログラムが使用するメモリは、値が 8M であると仮定します。読み取られる量は 100M です。これは単純にファイルを読み取るのに十分なメモリがありません。この問題を解決するには、メモリを避けるために、一度に特定のセクションのみを読み取る必要があります。制限事項
3. 静的ファイルのキャッシュ
現在、多くの企業がそのような要件を持っています。つまり、特定のページに初めてアクセスすると、PHP が実行され、同時に表示されたコンテンツがブラウザーに返されます。表示されたコンテンツを次回アクセスできるようにサーバーに保存する必要がある場合、PHP を介さずにサーバーに保存されたファイルを直接表示するだけです
これは、いわゆる「静的ページ キャッシュ」です。では、コンテンツをブラウザに返すと同時に、データをサーバーに保存するにはどうすればよいでしょうか?これには、出力バッファの使用が必要です。
出力バッファに関する設定
。 INI には、バッファーに密接に関連する 2 つの設定項目があります
1.output_buffering

この設定は、php 自体のバッファーに直接影響します。on/off/xK (x は整数値) です。バッファをオープンします

off - バッファを閉じます
256k - バッファをオープンします。バッファの内容が 256k を超えると、バッファは自動的に更新されます (データを Apache に送信します);

2.implicit_flush
该配置直接影响apache的缓冲区,有2种配置参数. on/off
on    - 自动刷新apache缓冲区,也就是,当php发送数据到apache的缓冲区的时候,不需要等待其他指令,直接就把输出返回到浏览器
off    - 不自动刷新apache缓冲区,接受到数据后,等待刷新指令

与缓冲区有关的函数
1.ob_implicit_flush
作用和implicit_flush一样,是否自动刷新apache的缓冲区
2.flush
作用是发送指令到apache,让apache刷新自身的输出缓冲区.
3.ob_start
打开输出缓冲区,无论php.ini的文件如何配置,如果使用该函数,即使output_buffering设置成off,也会打开输出缓冲区
ob_start函数还接受一个参数,该参数是一个函数的回调,意思是,在输入缓冲区内容之前,需要使用调用传递进来的参数把缓冲区的内容处理一次,再放入缓冲区内
4.ob_flush
指示php本身刷新自身的缓冲区,把数据发送到apache
5.ob_clean
清除php缓冲区里面的内容
6.ob_end_clean
清除php缓冲区内的内容,并且关闭输出缓冲区
7.ob_end_flush
把php自身的缓冲区里的内容发送到apache,并把清除自身缓冲区内的内容
8.ob_get_clean
获取缓冲区的内容之后,清除缓冲区.
9.ob_get_contents
获取输出缓冲区里的内容
10.ob_get_flush
获取缓冲区里的内容,并且把这些内容发送到apache
11.ob_get_length
获取缓冲区里内容的长度
12.ob_list_handlers
获取运行ob_start时,所回调的函数名称, 例如:
ob_start(‘ob_gzhandler’);
print_r(ob_list_handlers);
将打印出ob_gzhandler;
13.ob_gzhandler
该函数的作用是作为ob_start的回调参数, 在缓冲区刷新之前,会调用该函数对数据进行到底gzip或者deflate压缩.这个函数需要zlib扩展的支持.

使用缓冲区的相关内容
1.ob_flush和flush的次序关系.上面的分析可以看出,ob_flush是和php自身相关的,而flush操作的是apache的缓冲区,所有我们在使用这两个函数的时候,需要先执行ob_flush,
再执行flush,因为我们需要先把数据从PHP上发送到apache,然后再由apache返回到浏览器.如果php还没有把数据刷新到apache,就调用了flush,则apache无任何数据返回到浏览器.

2.有的浏览器,如果接受到的字符太少,则不会把数据显示出来,例如老版的IE(必须要大于256k才显示).这样就会造成一个疑问, 明明在php和apache都进行了刷新缓冲区的操作,但是浏览器就是没有出现自己想要的数据,也许就是这个原因造成的.所以才测试的时候,可以在输出数据的后面加上多个空格,以填满数据,确定不会浏览器造成这类诡异的问题.

3.有些webserver,他自身的输出缓冲区会有一些限制,比如nginx,他有一个配置fastcgi_buffer_size 4k, 就是是表明,当自身的输出缓冲区的内容达到4K才会刷新,所以为了保证内容的数据,可以添加以下代码,保证内容长度

<?php 
   echo str_repeat(" ",4096); 
?>

4.在apache中,如果你开启了mod_gzip的压缩模块,这样可能会导致你的flush函数刷新不成功,其原因是,mod_gzip有自己的输出缓冲区,当php执行了flush函数,指示apache刷新输出缓冲区,但是内容需要压缩,apache就把内容输出到自身的mod_gzip模块,mod_gzip也有自身的输出 缓冲区,他也不会马上输出,所以造成了内容不能马上输出.为了改善这个情况,可以关闭mod_gzip模块,或者在httpd.conf增加以下内容,以禁止压缩

SetEnv no-gzip dont-vary

以上がPHPバッファとは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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