PHP中刷新輸出緩衝詳解

      buffer是一個內存地址空間,Linux系統默認大小一般爲4096(1kb),即一個內存頁。主要用於存儲速度不同步的設備或者優先級不同的設備之間傳辦理數據的區域。通過buffer,可以使進程這間的相互等待變少。這裏說一個通俗一點的例子,你打開文本編輯器編輯一個文件的時候,你每輸入 一個字符,操作系統並不會立即把這個字符直接寫入到磁盤,而是先寫入到buffer,當寫滿了一個buffer的時候,纔會把buffer中的數據寫入磁 盤,當然當調用內核函數flush()的時候,強制要求把buffer中的髒數據寫回磁盤。

      同樣的道理,在PHP中,當執行echo,print的時候,輸出並沒有立即通過tcp傳給客戶端瀏覽器顯示, 而是將數據寫入php buffer。php output_buffering機制,意味在tcp buffer之前,建立了一新的隊列,數據必須經過該隊列。當一個php buffer寫滿的時候,腳本進程會將php buffer中的輸出數據交給系統內核交由tcp傳給瀏覽器顯示。所以,數據會依次寫到這幾個地方echo/pring -> php buffer -> tcp buffer -> browser


在PHP中與刷新緩衝相關的函數有三個:

1). flush
刷新PHP程序的緩衝,而不論PHP執行在何種情況下。該函數將當前爲止程序的所有輸出發送到用戶的瀏覽器。 但是該函數不會對服務器或客戶端瀏覽器的緩存模式產生任何影響,也不會對PHP本身的緩存產生任何影響。

2).ob_flush

該函數對PHP本身的的緩存進行輸出。PHP本身的緩存受php.ini中的output_buffering的控制。ob_flush()的作用就是將本來存在輸出緩存中的內容取出來,設置爲等待輸出狀態,但不會直接發送到客戶端,這時你就需要先使用ob_flush()再使用flush(),客戶端才能立即獲得腳本的輸出。

    與PHP本身輸出緩衝相關的兩個PHP配置是:
      參數1:output_buffering :on/off 或者整數 。設置爲on時,將在所有腳本中使用輸出緩存控制,不限制緩存的大小。而設置爲整數時,如output_buffering=4096,當緩存數據達到4096字節時會自動輸出刷新緩存。而這個參數的不同正是導致以上代碼在不同時候執行結果不同的原因。當output_buffering關閉時,腳本所有的輸出(echo)都會即時發送到客戶端,執行上面代碼時就是每秒輸出一個數字。而開啓output_buffering後,輸出內容就會先緩存在服務端,直到腳本結束時才一起發送給客戶端。
     參數2:implicit_flush:on/off。設定ON意味着,當腳本有輸出時,自動立即發送到客戶端。相當於在echo後自動加flush()。


3).ob_implicit_flush

這個函數強制每當有輸出的時候,即刻把輸出發送到瀏覽器。這樣就不需要每次輸出(echo)後,都用flush()來發送到瀏覽器了。

以下是舉例:

<?php
ob_end_clean();
echo str_pad(" ", 256);
for ($i=100; $i>0; $i--) {
   echo $i, '<br/>';
   flush();
   sleep(1); 
} 
?>
以上代碼應該隔一秒鐘輸出一次$i.  以上echo str_pad(" ", 256)的目的是IE需要接受到256個字節之後纔開始顯示。 以上代碼還有以下兩種寫法。

<?php
echo str_pad(" ", 256);
for ($i=100; $i>0; $i--) {
   echo $i, '<br />';
   ob_flush();
   flush();
   sleep(1); 
} 
?>

<?php
ob_implicit_flush(true);
echo str_pad(" ", 256);
for ($i=100; $i>0; $i--) {
   echo $i, '<br />';
   ob_flush();
   sleep(1); 
} 
?>

另外我們還需要注意刷新緩衝不光受以上幾方面的影響,還受以下影響:

1). 個別web服務器程序,特別是Win32下的web服務器程序,在發送結果到瀏覽器之前,仍然會緩存腳本的輸出,直到程序結束爲止。有些Apache的模塊,比如mod_gzip,可能自己進行輸出緩存,這將導致flush()函數產生的結果不會立即被髮送到客戶端瀏覽器。甚至瀏覽器也會在顯示之前,緩存接收到的內容。例如 Netscape 瀏覽器會在接受到換行或 html 標記的開頭之前緩存內容,並且在接受到 </table> 標記之前,不會顯示出整個表格。一些版本的 Microsoft Internet Explorer 只有當接受到的256個字節以後纔開始顯示該頁面,所以必須發送一些額外的空格來讓這些瀏覽器顯示頁面內容。

2). PHP安裝模式的影響。以上方式對於PHP以Apache模塊方式安裝的情況,可以直接使用。  如果以FastCgi方式還需要注意以下幾下配置:

    a). Apache+Fcgid+PHP
        FcgidOutputBufferSize 0(默認是65536)

        在配置Fcgid時, 設置這項值爲0, 以上代碼做刷新緩衝時,才能達到自己想要的效果。

    b).IIS+FastCgi+PHP

        ResponseBufferLimit=0

        修改WINDOWS\system32\inetsrv\fcgiext.ini下的這一項。

    c).nginx+php-fpm

        fastcgi_buffer_size 4k;

        fastcgi_buffers 8 4k;
        fastcgi_busy_buffers_size 4k
        gzip off;


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章