7

多数のレコードを送信する PHP スクリプトがあり、各レコードが利用可能になるとすぐにフラッシュしたい: クライアントは各レコードが到着すると処理できるため、応答全体を待つ必要はありません。複数のパケットで送信する必要があるため、転送全体に少し時間がかかることがわかりましたが、それでもクライアントはより早く作業を開始できます.

私はさまざまな機能をすべて試しましたflush()ob_flush()、ページが終了する前にデータを実際に回線経由で送信するのに役立つものは何もないようです。telnetでテストしたので、Webブラウザではないことを確認しました。

4

3 に答える 3

7

私にとってうまくいった唯一の解決策はoutput_buffering、php.ini のディレクティブを「オフ」に設定することでした。サーバー全体に対してこれを行いたくはありませんでした。この 1 つの特定のリソースに対してだけです。通常は PHP スクリプトから使用できますが、何らかの理由で php ではこの方法での設定がini_set許可されていません( php マニュアルを参照)。output_buffering

Apache を使用している場合output_buffering、.htaccess ファイルを含むサーバー構成からいくつかの php ini ディレクティブ (を含む) を設定できることがわかりました。そのため、.htaccess ファイルで次を使用して、その 1 つのファイルだけで output_buffering を無効にしました。

<Files "q.php">
    php_value output_buffering Off
</Files>

そして、私の静的サーバー構成では、.htaccess ファイルでそれを許可するためにAllowOverride Options=php_value(または のような大きなハンマー) が必要でした。AllowOverride All

于 2013-02-22T16:18:24.167 に答える
5

使用している Web サーバーについては言及していませんが、ここで Apache2 を推測します。私はあなたが説明したものとほぼ同じものを打ちました。全体をバッファリングするのではなく、CGIスクリプトが準備が整ったときに情報を返すようにしようとしていました。curl などでは一瞬動作しましたが、ブラウザ (ほとんどすべてのブラウザ) でバッファリングされました。これは少なくとも腹立たしいことでした。あなたが説明した正確な手順を実行しました。sites-enabled/terrifico.com私の場合の解決策は、 Apache2 の構成ファイルを変更することでした(問題の行は

SetEnvIfNoCase

(その行の上下のものは無視してかまいません。配置した場所を参照するために表示しているだけです。)

<VirtualHost *:80>
ServerAdmin webmaster@localhost
ServerName test.terrifico.com
ServerAlias test.terrifico.com

SetEnvIfNoCase Request_URI \.cgi$ no-gzip dont-vary

DocumentRoot /var/www/test.terrifico.com

行き来するネットワーク トラフィックをじっと見つめているうちに、ブラウザーがあらゆるもの (テキスト) のデフレを受け入れることを宣伝していることにようやく気付きました。たとえば、それがブラウザとカールの違いでした。顕著な部分は

Accept-Encoding:gzip、deflate、sdch

について少しありましたがchunking、それはこの特定の問題には影響しませんでした。そのため、ブラウザーはmod_deflateキックインを要求していましたが、CGI スクリプトでバイトを取得したときに、慎重に吐き出すバイトを打ち負かしました。ブラウザで変更することもできますが、サーバー上で一度変更する方が賢明に思えました。

おそらくこれが役立ちます。

于 2013-06-21T20:28:31.443 に答える
4

php.iniファイルを変更したり、.htaccessファイルを用意したりせずに PHP で実行時に出力バッファリングをオフにするには、スクリプトの先頭でob_end_flush()orを使用します。ob_end_clean()例えば:

これは、バッファリングなしで出力する必要があります。

<?php
ob_end_clean();

for ($i = 0; $i < 5; $i++)
{
    echo "$i\n";
    flush();
    usleep(0.5e6);
}

これは、呼び出しoutput_bufferingに関係なく、がオンの場合、バッファリングを使用して (一度にすべて) 出力します。flush()

<?php

for ($i = 0; $i < 5; $i++)
{
    echo "$i\n";
    flush();
    usleep(0.5e6);
}

その名前にもかかわらず、各出力の後に暗黙的にではなくをob_implicit_flush呼び出します。これは、最初に出力バッファを閉じた後のこのインスタンスで便利です。flush()ob_flush()

<?php
ob_end_clean(); // disable output buffer
ob_implicit_flush(); // call flush() automatically after every output

for ($i = 0; $i < 5; $i++)
{
    echo "$i\n";
    usleep(0.5e6);
}

これにより、PHP 側が修正されます。または同様のことが起こっている可能性がありますmod_deflate(Ted Collins による回答を参照)。また、Firefox が何かを出力し始める前に、少なくとも 1024 バイトが必要であることを確認しました。

于 2015-02-22T17:27:10.423 に答える