zlib.output_compression を用いた転送量の削減を可能に†
- ページ: BugTrack
- 投稿者: henoheno
- 優先順位: 普通
- 状態: 着手
- カテゴリー: 本体新機能
- 投稿日: 2004-11-01 (月) 21:53:35
- バージョン:
メッセージ†
PukiWikiへのアクセス遅延が発生しており、その原因がネットワーク帯域であってCPUには余裕があるとわかっている場合、PHPの zlib.output_compression という機能を試すことができます。これは圧縮データを受け取ることができるブラウザに対して、データを送信する際に自動的に出力を圧縮し、それによって転送量を抑えるという機能です。転送量の削減と引き換えにCPUに負担がかかるため、現状の分析は必須です。
この件について手元の環境(FreeBSD上のPHP4.3.9およびPukiWiki CVS版)にて動作確認をしたところ、スキンからヘッダを追加出力させるだけで動作する事が確認できました。
if(ini_get('zlib.output_compression') &&
preg_match('/\b(gzip|deflate)\b/i', $_SERVER['HTTP_ACCEPT_ENCODING'], $matches)) {
header('Content-Encoding: ' . $matches[1]);
header('Vary: Accept-Encoding');
}
マニュアルを見た範囲では(本来は)この機能は透過的な機能であって、PHPコード側に改造する余地はないはずですが、実際には自動的に出力されるはずのヘッダが出力されないようです。そのため、これを設定にあわせて出力させています。
Content-Encodingを出力してくれないこの状況は、小さなコード片(例えばphpinfo()のみを含んだファイル)でも再現できるため、PHP本体側や他の設定との兼ね合いにその理由があるように思っています。
この機能はphp.iniや、(Apacheのhttpd.confに許可されている場合は) .htaccess から On にすることができます。そのため、.haccessに以下の設定を追加しておきました。(デフォルトでは無効)
## Using zlib.output_compression per directory (via .htaccess),
## needs 'AllowOverride Options' at httpd.conf.
#php_flag zlib.output_compression On
- zlib.compression 利用中に、Accept-Encoding: gzip あるいは deflate を持たないブラウザがアクセスしたときにはheaderを出力しないように、少々修正しました。 -- henoheno
ちょっと確認: 類似の技術: mod_deflate†
- 津田ふみかの日記: Apacheのコンテンツ圧縮方法
- 情報ありがとうございます。(そうか、そういえば自分でdeflateを試すこともできたのだったなぁ。。。 (^^; ええ時代や・・・) -- henoheno
- (通りすがりより追記) --
- DEFLATEフィルタ問題について
refを用いて画像を表示している場合もmod_deflateで、画像に対する圧縮を除外しているにもかかわらず、強制圧縮対象となってしまっていました。
この問題について、plugin/attach.inc.phpの改修と同様の事をplugin/ref.inc.phpに対しても行う事でrefで表示している画像に対する圧縮を避け、CPUリソースの無駄な消費を回避できます。
そのほか†
- Port80 Softwareの Web server compression check
画像が壊れる?†
- 関連して、手元の環境(FreeBSD + Apache2.0.52_1 + PHP 4.3.9)では ref およびattachプラグインが出力する画像が壊れます。マニュアル通りの対処法としては ini_set(zlib.output_compression, 'Off'); を実行すると良いはずなのですが、とりあえず私の環境では(FALSEが帰って来ており)動作を確認できていません。 -- henoheno
- PHP 4.3.2 以降、Content-Type が image であるものについては自動的に compression がoffになる、という動作が(も)有効に働いていない予感。
- 久しぶりに別の視点からチェックしてみました。画像については「壊れる」のではなく「gzip圧縮される」というのが正解で、通常コンテンツと同様にContent-Encodingなどをつければ動作する事を確認しました。 -- henoheno
- Firefox 1.0 および Internet Explorer 6 では特に問題なく画像が表示できるようです。 -- henoheno
試してみた 試してみてね†
- Linux/Windowsメインな方、anotherブラウザな方のテストをお待ちしております :) -- henoheno
- テストの意味合いが良くわからないのですが、項目名が「試してみた」になっているので既にdevに適用済という事でしょうか?それともCVSの最新版を導入して各自確かめてねという事でしょうか? -- にぶんのに
- まぎらわしかったようですいません (^^; 影響範囲が不明である状態でdevにいきなり適用するなんて怖いことはできません (^^; *1 CVS版を導入して各自お試しいただいて、コメントをいただければと思っています。影響範囲を狭める意味で特に様子を見ていただきたいのはサーバー側で言えばLinuxとWindows、クライアント側で言えば上に挙げていないブラウザです。 -- henoheno
- 試してみました。ref及びattach以外の変わった方法で画像を表示させると、やはり壊れたようになってしまいます。 --
- 訂正します。refを使っても表示ができませんでした。WinXP+IE6/Opera8/FireFox1.0で確認済みです。ファイルは全てCVSから取得した最新版を使用しています。 --
- .haccessで有効にするとこの現象が起きます。特に.haccessでOnにしなくても圧縮転送が働いているようなので、サーバの設定の方で有効になっている場合は問題ないです。 --
- こんにちは :) Webサーバーの種類と、そのプラットフォーム(OS)とPHPの実行形態を教えて下さい(ApacheモジュールなのかCGI起動なのか)。PukiWikiは勝手に圧縮するようなことはしません。http.confなどで zlib.output.compression をOnにされていたり、mod_deflateのような別の手段を有効にされていることをお忘れでないですか? -- henoheno
- サーバはXREAを使っています。その為、http.confの内容はよく分かりませんが、どうやらXREAではデフォルトで圧縮転送を行うようになっているようです。PHPはモジュールとして動作しています。OSはLinuxだそうです。これって、サーバとユーザで2重に定義するとまずいのでしょうか。 --
- このページのすぐ上にあるmod_deflateのような別の問題とごっちゃにしてない?
- ちなみに FreeBSD 以外のプラットフォームでどうなるのかはまだ報告を受けていません。Logueさんとこで動いているらしいのですが、あのサーバーはLinuxかしらん? -- henoheno
- Linuxの1.3.33ですね。zlib.output.compressionを使うと、サーバーエラーになって使えません。 -- Logue
- Linux上のApache1.3.33ですよね? --
- はい。 -- Logue
- Windows 2000 + IIS 5.0 + PHP 4.3.10(ISAPI) でテストしました。今現在 pkwk_common_headers() で出力している zlib.output_compression 関係のヘッダが不要(過剰)です。これが添付した画像ファイルを壊してしまいます。 -- henoheno
- ということは、Linuxでも動作を見たくなってくるなぁ。 -- henoheno
- そうなると、FreeBSDかどうかを切り分けるか、zlib関連の何かの設定をキーにしてFreeBSDをケアすることになるのかしらん。 -- henoheno
- 発見。FreeBSD側の問題は、PHP側のバグが、FreeBSD (ports)の構成によって顕在化したものである様子。私はそれを知らずにworkaroundを書いて無理やりFreeBSDで動作させてしまっているらしい (^^; -- henoheno
- Bug #29350 output_compression not working with zlib as loadable module
- ports/69810: zlib output compression does not work as loadable module
- Debian Woody ,Apache/1.3.33 (Unix), PHP/4.3.10でやってみました。特に問題ないようです。他に試して欲しいことがあれば仰って下さい。 -- okkez
- ちなみにPukiWikiは今日CVSからアップデートしたものです。 -- okkez
- 拝見しましたが、添付されている画像が正しくGetできない様ですので、バッチリ問題になっている様です (^^; ご確認を... (CVS版は現状zlib.output_compressionを検知すると画一的に圧縮ヘッダを付与してしまいます。zlib.output_compressionが正しく機能している環境では、画像ファイルについては圧縮が回避されます。しかしそれらにもPukiWikiが圧縮ヘッダをつけてしまうと、当然ですが正常に表示されなくなります) -- henoheno
- 現象が確認できませんでした。こちらのやったことは、画面下の添付ファイル一覧から
- sleipnir1.66で右クリックして「対象をファイルに保存」
- Opera7.22で右クリックして「リンク先を保存」
- Firefoxで右クリックして「リンク先を名前を付けて保存」
その後、ローカルで画像を見ても壊れていませんでした。以上いずれの環境でもブラウザ上の表示でも画像は壊れていませんでした。この現象というのはブラウザ上に表示される画像が壊れることなんですよね?もしかして、根本的に勘違いしてるor無知を晒していたりするのでしょうか? -- okkez
- とりあえず、zlib.output_compressionはコメントアウトしておきます。また明日出先にPCがあるのでそこから試してみたいと思います。 -- okkez
- うーん。色々調べていると自分のサーバー圧縮かかってなかったみたいです。htaccessで有効化しようとすると、サーバーエラーになってしまいます。ただ、フォーラムで使っているスクリプト*2で帯域圧縮をフォーラムの設定で有効にしたところ、ちゃんと効いてたので、どうも.htaccessで設定を振り分けるのに問題があるような気がします。 -- Logue
- 続報ですがSMFのソースをあさってたところ、ob-gzhandlerという関数に当たりました。そこで、ob-gzhandlerについて調べていると、ob_start("ob_gzhandler");を入れるだけ圧縮されるみたいなことが書かれてました。ためしに、html.phpのOutput common HTTP headersを書き換えてみたところ、無事圧縮されて出力されてきました! -- Logue
(開発日記/2005-01-26)
- cvs:lib/html.php (1.27): if(defined('PKWK_ZLIB_LOADABLE_MODULE'))
- 今までテストしていたFreeBSDがむしろ特殊だったという事がわかってきたため、そのような構成向けのヘッダ出力をdefaultでoffに。onにするには、上記の定義をどこかでdefineするべし。
- 時を超えて・・・
(下の表記とほぼ同じなので削除)
という感じでいいと思います。 -- Logue
- 上のコードからLogueさんが著述した部分をdiffで示した上で、経験された知見を第三者にわかるようにお書き下さい。(最初からdiffにして下さい)よろしくお願いします -- henoheno
- Diffってこれでいいですか?
// Output common HTTP headers
-function pkwk_common_headers(){
+function pkwk_common_headers($compress){
if (! PKWK_OPTIMISE) pkwk_headers_sent();
if(PKWK_ZLIB_LOADABLE_MODULE == true && $compress != false) {
$matches = array();
+ if(extension_loaded('zlib') &&
+ ob_get_length() === FALSE &&
+ !ini_get('zlib.output_compression') &&
+ ini_get('output_handler') !== 'ob_gzhandler' &&
+ ini_get('output_handler') !== 'mb_output_handler'){ // mb_output_handlerとかち合うらしいので、その場合は弾く。http://pukiwiki.sourceforge.jp/dev/?%BB%A8%C3%CC%2F11
+ // http://jp.php.net/manual/ja/function.ob-gzhandler.php
+ ob_start('ob_gzhandler');
- if(ini_get('zlib.output_compression') &&
+ }else if(ini_get('zlib.output_compression') &&
preg_match('/\b(gzip|deflate)\b/i', $_SERVER['HTTP_ACCEPT_ENCODING'], $matches)) {
// Bug #29350 output_compression compresses everything _without header_ as loadable module
// http://bugs.php.net/bug.php?id=29350
header('Content-Encoding: ' . $matches[1]);
- header('Vary: Accept-Encoding');
+ //http://pukiwiki.cafelounge.net/plus/?%E9%96%8B%E7%99%BA%E8%AB%87%E7%BE%A9%2F25&word=Accept-Encoding
+ $vary = get_language_header_vary();
+ if (! empty($vary)) $vary .= ',';
+ header('Vary: '.$vary.' Accept-Encoding');
}
}
+ // PHPで動的に生成されるページはキャシュすべきではない
+ header('Cache-Control: no-cache, must-revalidate');
+ header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
+ header('Pragma: no-cache');
}
$compressスイッチは、attachなどでファイルが2重圧縮されるのを防ぐためのものです。一部upk氏のコードが含まれています。Varyの部分です。他の+は自分で書きました。ただ、ob_end_flush():を出力が終わったときに実行したほうがいいらしいので、exitの手前に下記のコードがいるかもしれません。 -- Logue
if(PKWK_ZLIB_LOADABLE_MODULE == true && extension_loaded('zlib') &&
ob_get_length() === FALSE &&
!ini_get('zlib.output_compression') &&
ini_get('output_handler') !== 'ob_gzhandler' &&
ini_get('output_handler') !== 'mb_output_handler'){
ob_end_flush();
}
それにしても、PKWK_ZLIB_LOADABLE_MODULEは、どこで定義してたっけ?
- この著作物の来歴を説明して下さい。どこから持って来ましたか? なぜ他者の著作が入っているのですか? (diffの表現についてはそんな感じでよろしいかと思います。ただし先頭の数行が恐らく欠けておるので、正しい比較元と比較されたかが良く解りません) -- henoheno
- いろいろ、漁って合成したので著作と言えるほどものはないかと。来歴は、2005年頃書いた雑談/11のコードに、他のハンドラとかぶると言われたので、かぶりそうなハンドラを条件で弾いた処理をいれたぐらいです。 -- Logue
- 何度もお手間かと思いますが、「一部upk氏のコードが含まれています。Varyの部分です。」というの部分の由来を明確に説明して下さい。 -- henoheno
- すみません、get_language_header_vary()という関数の部分が本家にもあると勘違いしていました。Plusのlang.phpで定義されているコードで、これがupk氏が書いたコードです。-- Logue
$vary = get_language_header_vary();
if (! empty($vary)) $vary .= ',';
header('Vary: '.$vary.' Accept-Encoding');
- こちらの件ですが、受け取りを拒否せざるをえません。言い辛いのですが、プロジェクトを危険にさらすレベルの痕跡が複数見受けられるため。 -- henoheno
- 複数の著作物を知らず知らずに紛れ込ませてしまえるような作り方をしている時点でまずいです。
- パッチでなく実装を提示できてしまう点もまずいです。
- ポイントの説明なしに露出させてしまえる点もまずいです。受け入れる側の負荷が高いです。
- 読解に手間がかかるものを提示してしまえる点もまずいです。受け入れる側の負荷が高いです。
- 絶対に動かないコードをテストせずに提示できる点もまずいです*3。ありえないです。
- こうした事故を防ぐ手順は確実に存在しますが、身に着けていないのがまずいです。
Logueさんには一旦立ち止まってもらって、よそのプロジェクトに迷惑をかけない = 問題の無い創作ができる体制を身に付けていただいてから活動を再開していただけないでしょうか。でないと、恐ろしさをよっぽど解っていないか、本当はそうでないかもしれないのに、手抜きをするキャラクターであるかのように受け取られてしまいます。 -- henoheno
- 最初の実装の貼り付けは、その後のdiffと内容が重複していますので削除させていただきます。 -- henoheno
- 上のdiff形式のコードなのですが・・・良く見たら「違いが無い部分」に半角スペースが挿入されていないのですよね(ツールのdiffを使っていたらそのような挙動は無いと思われます)。また、preformatted text表現のための半角スペースの挿入のされ方も一定ではありません。diff表現の先頭二行(ファイル名とか)が無いのも不思議でしたが、これを手で作りましたか? 答えなくても良いのですが、合っている場合、それは止めた方が良いです。 -- henoheno
- 関連: BugTrack2/333 BugTrack2/337 -- henoheno
- EmYvEZKSHyOvQHTGkTP -- cjbsmolcp