1

私はphpのウェブサイトを持っています。私はテンプレート エンジンを使用しており、常に "ワンショット" で html を実行しているため、html ドキュメントのサイズがあらかじめわかっています。そこで、パフォーマンスを向上させるために Content-Length ヘッダーを設定することにしました。設定しない場合、ドキュメントはチャンク エンコーディングを使用して転送されます。

HTML 出力の php コードは次のようになります。

header('Accept-Ranges: none');
header('Content-Length: '.strlen($content));

echo $content;

Chrome、IE、Firefox、およびSafariのウィンドウでテストしました-ファイルで動作します。ただし、Microsoft Bing ボット (bing ウェブマスター ツールを使用) は、Web サイトが応答しないと述べています。私は調査することにしました、そしてここに私が見つけたものがあります:

  • wget は CentOS 5.x および CentOS 6.x で正常に動作します
  • CentOS 6.x の elinks は正常に動作します
  • CentOS 5.x の elinks が停止する(バージョン elinks-0.11.1-6.el5_4.1)

したがって、Centos 5 の elinks は、サイトへのアクセスに問題があることがわかった唯一の http クライアントでした。ただし、デバッグ情報を取得する方法がわかりません。

質問:

  1. elink からデバッグ情報を取得する方法を教えてください。http+headers の raw dup を持つことは可能ですか? またはある種のエラーログ
  2. あるクライアントで失速が発生し、別のクライアントでは発生しない理由は何ですか?
  3. 問題を引き起こしているのは、おそらく間違ったヘッダー「Content-Length」です。これを削除すると、elinks と Bing で正常に動作するためです。コンテンツの長さの違いの原因
  4. 他にテストする http クライアントはありますか?

すべてのテストは、同じ Web サーバー、同じ PHP バージョン、同じ Web ページ、同じコンテンツで実行されます。私が考えることができるのは、UTF-8 テキスト ファイル識別子 (一部のブラウザが配置するテキスト ファイルの前の数バイト) です。

以下は、wget を使用したヘッダーのダンプです。

wget dev.site.com/ --server-response -O /dev/null
--2013-11-09 01:32:37--  http://dev.site.com/
Resolving dev.site.com... 127.0.0.1
Connecting to dev.site.com|127.0.0.1|:80... connected.
HTTP request sent, awaiting response...
  HTTP/1.1 200 OK
  Date: Fri, 08 Nov 2013 23:32:37 GMT
  Server: Apache
  Set-Cookie: lng=en; expires=Wed, 07-May-2014 23:32:37 GMT; path=/; domain=dev.site.com
  Last-Modified: Fri, 08 Nov 2013 23:32:37 GMT
  Cache-Control: must-revalidate, post-check=0, pre-check=0
  Pragma: no-cache
  Expires: 0
  Set-Cookie: PHPSESSID=8a1e9b871474b882e1eef4ca0dfea0fc; expires=Thu, 06-Feb-2014 23:32:37 GMT; path=/
  Content-Language: en
  Set-Cookie: hc=1518952; expires=Mon, 17-Nov-2036 00:38:00 GMT; path=/; domain=dev.site.com
  Accept-Ranges: none
  Content-Length: 16970
  Keep-Alive: timeout=15, max=100
  Connection: Keep-Alive
  Content-Type: text/html; charset=UTF-8
Length: 16970 (17K) [text/html]
Saving to: “/dev/null”

100%[===================================================================================================================================================================================================>] 16,970      --.-K/s   in 0.1s

2013-11-09 01:32:37 (152 KB/s) - “/dev/null” saved [16970/16970]

アップデート:

問題を再現できましたが、本番サーバーでのみです。動作している elink と動作していない elink の違いの 1 つは、動作していない elink が次のヘッダーを送信することです: Accept-Encoding: gzip

もちろん、gzip されている場合、サイズは異なります。php.ini で zlib.output_compression がオンになっています。それが問題かもしれないと思います。また、出力バッファリングは 4096 です。これは奇妙なことです。ほとんどのブラウザーは、可能な場合は圧縮を使用するからです。Web ブラウザでもう一度試してみます。

はい、ブラウザー (chrome) も圧縮を要求し、応答ヘッダーに gzip が存在します。

Content-Length: 15916
Content-Encoding: gzip

ソースを表示すると、正確に 15916 バイトが表示されます。Chrome には、生のヘッダーと解析済みのヘッダーを表示するオプションがあります。起こり得ることは、Chrome がカウントする前に実際にデータを解凍することです。奇妙に聞こえるかもしれませんが、GUI Web ブラウザーが機能し、一部の下位レベルのクライアントが機能しない唯一の説明です。

4

3 に答える 3

1

答えはすでにそこにあります。'$content' が圧縮されたContent-Lengthのサイズである、実際に送信されているサイズでなければなりません。view-source で表示されるコンテンツのサイズは、当然のことながら解凍されたサイズです。

接続はストールしません。ブラウザはさらにデータが来るのを待っていますが、圧縮されたデータのサイズはブラウザが待っているサイズよりも小さくなっています。サーバーが最終的に接続をタイムアウトした場合、ブラウザはすべてのデータを取得したと見なして表示します。それらはaccept-compressionヘッダーを送信せず、サーバーは圧縮された応答を送信しないため、wgetなどで機能します。

必要に応じて、圧縮を無効にし、手動で圧縮して送信$contentし、適切なContent-Encodingヘッダーを送信することもできます。

もう1つのオプションは、ページを圧縮せずにダウンロードすることです(Accept-Encoding: gzipwgetで送信します。解凍されないと思いますが、デフォルトでは有効になっていませんが、結局wgetは圧縮をサポートしている可能性があります。サポートしている場合は使用できます)、応答からヘッダーを除いたサイズ (つまり、ヘッダー エンド シーケンスの のデータのサイズのみ) を取得し、送信時にそのサイズを使用します。しかしもちろん、圧縮レベルまたは実装 (異なる Web サーバー/モジュールまたは同じ Web サーバー/モジュールの異なるバージョン) を変更すると、結果として得られる圧縮データのサイズが変更されるため、これは非常に壊れやすい方法です。\r\n\r\nContent-Length

そもそもなんで改造Content-Lengthしてんの?PHPまたはWebサーバーがそれを処理することになっています。

于 2013-11-09T01:30:10.290 に答える
1

きれいな解決策はありません。zlib バッファ サイズを次のように設定できるようにしたいと考えています。

zlib.output_compression = 131072

ページが 128k (非圧縮) を超えないと確信している場合でも、バッファの圧縮サイズを取得する方法はありません。

したがって、2 つの解決策があります。

  1. 出力圧縮をオフにするか、Content-Length を設定しないでください...これはあまり解決策ではありませんが、機能します
  2. zlib 圧縮ハンドラを次のものに置き換えます。

ob_start(); // start normal buffer
ob_start("ob_gzhandler"); // start gzip buffer
echo $content;
ob_end_flush(); // output gzipped content

$gzippedContent = ob_get_contents(); // store gzipped content to get size
header('Content-Length: '.strlen($gzippedContent));
ob_end_flush(); // flush gzipped content

ただし、zlib.output_compression が Off であることを確認してください。

php のマニュアルでは zlib.output_compression が優先されると書かれていますが、ob_gzhandler を使用するとパフォーマンスが劇的に低下するとは思えません。

で圧縮レベルを設定できます

ini_set('zlib.output_compression_level', 4);

テストしたところ、クライアント/ブラウザーで gzip が有効になっている場合と gzip が無効になっている場合の両方で動作します。

wget --header='Accept-Encoding: gzip,deflate' -O ./page.html.gz http://www.site.com/ && gunzip page.html.gz
wget -O ./page.html http://www.site.com/
于 2013-11-09T02:12:10.583 に答える