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 2004-11-01 (月) 21:55:57

ちょっと確認: 類似の技術: mod_deflate

  • 津田ふみかの日記: Apacheのコンテンツ圧縮方法
    • http://fumika.jp/nikki/2004/09/mod_deflate
    • "Apache 1.x 系では、mod_gzip というモジュールを導入する必要がありました。Apache 2.0 系では、mod_deflate というモジュールとして組み込まれています。"
  • mod_deflate
    • http://httpd.apache.org/docs-2.0/ja/mod/mod_deflate.html
    • "mod_deflate モジュールは DEFLATE 出力フィルタを提供します。これはサーバからの出力を、ネットワークを 通してクライアントに送る前に圧縮することを可能にします。"
    • Varyに関する説明あり。 (Proxy向け)
  • (official:雑談より)
    • DEFLATEフィルタ問題の解決策書きました。 http://tokiwa.hn.org/mt/archives/000106.html -- tokiwa? 2004-12-03 (金) 04:21:42
      • "ApacheでDEFLATEフィルタを書けた状態でPukiWikiのAttachによる圧縮ファイルダウンロードを行うとMIME/Typeによらず強制的に2重圧縮されてしまう(DEFLATEフィルタとはmod_deflateによるgzip圧縮フィルタのことです)。この現象は AddOutputFilterByTypeでDEFLATEフィルタを制御してる場合に起きます。Files等でフィルタ適用を制御している場合には、対象のファイルを除外することで回避可能。AddOutputFilterByTypeのみで管理したい人はPukiWikiを改修する必要があります。改修するファイルはplugin/attach.inc.phpで、650行目辺りを下記のように改修してください。"
        header('Content-Length: '.$this->size);
        header('Content-Type: '.$this->type);
        header('Content-Encoding: none'); // この行を追加
        @readfile($this->filename);
        exit;
  • 情報ありがとうございます。(そうか、そういえば自分でdeflateを試すこともできたのだったなぁ。。。 (^^; ええ時代や・・・) -- henoheno 2004-12-03 (金) 23:16:53
  • (通りすがりより追記) -- 2009-10-07 (水) 12:24:54
    • DEFLATEフィルタ問題について
      refを用いて画像を表示している場合もmod_deflateで、画像に対する圧縮を除外しているにもかかわらず、強制圧縮対象となってしまっていました。 この問題について、plugin/attach.inc.phpの改修と同様の事をplugin/ref.inc.phpに対しても行う事でrefで表示している画像に対する圧縮を避け、CPUリソースの無駄な消費を回避できます。

そのほか

画像が壊れる?

  • 関連して、手元の環境(FreeBSD + Apache2.0.52_1 + PHP 4.3.9)では ref およびattachプラグインが出力する画像が壊れます。マニュアル通りの対処法としては ini_set(zlib.output_compression, 'Off'); を実行すると良いはずなのですが、とりあえず私の環境では(FALSEが帰って来ており)動作を確認できていません。 -- henoheno 2004-11-01 (月) 22:42:42
    • PHP 4.3.2 以降、Content-Type が image であるものについては自動的に compression がoffになる、という動作が(も)有効に働いていない予感。
    • 久しぶりに別の視点からチェックしてみました。画像については「壊れる」のではなく「gzip圧縮される」というのが正解で、通常コンテンツと同様にContent-Encodingなどをつければ動作する事を確認しました。 -- henoheno 2004-11-27 (土) 19:54:36
    • Firefox 1.0 および Internet Explorer 6 では特に問題なく画像が表示できるようです。 -- henoheno 2004-11-27 (土) 20:07:00

試してみた 試してみてね

  • Linux/Windowsメインな方、anotherブラウザな方のテストをお待ちしております :) -- henoheno 2004-11-27 (土) 20:22:17
    • テストの意味合いが良くわからないのですが、項目名が「試してみた」になっているので既にdevに適用済という事でしょうか?それともCVSの最新版を導入して各自確かめてねという事でしょうか? -- にぶんのに 2004-11-27 (土) 20:48:42
    • まぎらわしかったようですいません (^^; 影響範囲が不明である状態でdevにいきなり適用するなんて怖いことはできません (^^; *1 CVS版を導入して各自お試しいただいて、コメントをいただければと思っています。影響範囲を狭める意味で特に様子を見ていただきたいのはサーバー側で言えばLinuxとWindows、クライアント側で言えば上に挙げていないブラウザです。 -- henoheno 2004-11-27 (土) 21:13:17
  • 試してみました。ref及びattach以外の変わった方法で画像を表示させると、やはり壊れたようになってしまいます。 -- 2005-01-18 (火) 23:49:14
    • 訂正します。refを使っても表示ができませんでした。WinXP+IE6/Opera8/FireFox1.0で確認済みです。ファイルは全てCVSから取得した最新版を使用しています。 -- 2005-01-19 (水) 00:06:25
    • .haccessで有効にするとこの現象が起きます。特に.haccessでOnにしなくても圧縮転送が働いているようなので、サーバの設定の方で有効になっている場合は問題ないです。 -- 2005-01-19 (水) 11:08:44
    • こんにちは :) Webサーバーの種類と、そのプラットフォーム(OS)とPHPの実行形態を教えて下さい(ApacheモジュールなのかCGI起動なのか)。PukiWikiは勝手に圧縮するようなことはしません。http.confなどで zlib.output.compression をOnにされていたり、mod_deflateのような別の手段を有効にされていることをお忘れでないですか? -- henoheno 2005-01-19 (水) 21:29:47
    • サーバはXREAを使っています。その為、http.confの内容はよく分かりませんが、どうやらXREAではデフォルトで圧縮転送を行うようになっているようです。PHPはモジュールとして動作しています。OSはLinuxだそうです。これって、サーバとユーザで2重に定義するとまずいのでしょうか。 -- 2005-01-20 (木) 01:58:38
      • このページのすぐ上にあるmod_deflateのような別の問題とごっちゃにしてない?
  • ちなみに FreeBSD 以外のプラットフォームでどうなるのかはまだ報告を受けていません。Logueさんとこで動いているらしいのですが、あのサーバーはLinuxかしらん? -- henoheno 2005-01-19 (水) 21:33:10
  • Linuxの1.3.33ですね。zlib.output.compressionを使うと、サーバーエラーになって使えません。 -- Logue 2005-01-21 (金) 18:03:44
    • Linux上のApache1.3.33ですよね? -- 2005-01-21 (金) 18:51:14
    • はい。 -- Logue 2005-01-23 (日) 00:13:52
  • Windows 2000 + IIS 5.0 + PHP 4.3.10(ISAPI) でテストしました。今現在 pkwk_common_headers() で出力している zlib.output_compression 関係のヘッダが不要(過剰)です。これが添付した画像ファイルを壊してしまいます。 -- henoheno 2005-01-22 (土) 21:21:24
    • ということは、Linuxでも動作を見たくなってくるなぁ。 -- henoheno 2005-01-22 (土) 21:21:53
    • そうなると、FreeBSDかどうかを切り分けるか、zlib関連の何かの設定をキーにしてFreeBSDをケアすることになるのかしらん。 -- henoheno 2005-01-22 (土) 21:23:14
  • 発見。FreeBSD側の問題は、PHP側のバグが、FreeBSD (ports)の構成によって顕在化したものである様子。私はそれを知らずにworkaroundを書いて無理やりFreeBSDで動作させてしまっているらしい (^^; -- henoheno 2005-01-22 (土) 22:02:28
  • Debian Woody ,Apache/1.3.33 (Unix), PHP/4.3.10でやってみました。特に問題ないようです。他に試して欲しいことがあれば仰って下さい。 -- okkez 2005-01-24 (月) 03:47:59
  • ちなみにPukiWikiは今日CVSからアップデートしたものです。 -- okkez 2005-01-24 (月) 03:49:38
    • 拝見しましたが、添付されている画像が正しくGetできない様ですので、バッチリ問題になっている様です (^^; ご確認を... (CVS版は現状zlib.output_compressionを検知すると画一的に圧縮ヘッダを付与してしまいます。zlib.output_compressionが正しく機能している環境では、画像ファイルについては圧縮が回避されます。しかしそれらにもPukiWikiが圧縮ヘッダをつけてしまうと、当然ですが正常に表示されなくなります) -- henoheno 2005-01-24 (月) 23:13:29
    • 現象が確認できませんでした。こちらのやったことは、画面下の添付ファイル一覧から
      • sleipnir1.66で右クリックして「対象をファイルに保存」
      • Opera7.22で右クリックして「リンク先を保存」
      • Firefoxで右クリックして「リンク先を名前を付けて保存」
        その後、ローカルで画像を見ても壊れていませんでした。以上いずれの環境でもブラウザ上の表示でも画像は壊れていませんでした。この現象というのはブラウザ上に表示される画像が壊れることなんですよね?もしかして、根本的に勘違いしてるor無知を晒していたりするのでしょうか? -- okkez 2005-01-25 (火) 01:27:45
    • とりあえず、zlib.output_compressionはコメントアウトしておきます。また明日出先にPCがあるのでそこから試してみたいと思います。 -- okkez 2005-01-25 (火) 01:37:25
  • うーん。色々調べていると自分のサーバー圧縮かかってなかったみたいです。htaccessで有効化しようとすると、サーバーエラーになってしまいます。ただ、フォーラムで使っているスクリプト*2で帯域圧縮をフォーラムの設定で有効にしたところ、ちゃんと効いてたので、どうも.htaccessで設定を振り分けるのに問題があるような気がします。 -- Logue 2005-02-13 (日) 18:43:22
  • 続報ですがSMFのソースをあさってたところ、ob-gzhandlerという関数に当たりました。そこで、ob-gzhandlerについて調べていると、ob_start("ob_gzhandler");を入れるだけ圧縮されるみたいなことが書かれてました。ためしに、html.phpのOutput common HTTP headersを書き換えてみたところ、無事圧縮されて出力されてきました! -- Logue 2005-02-13 (日) 19:12:58

(開発日記/2005-01-26)

  • cvs:lib/html.php (1.27): if(defined('PKWK_ZLIB_LOADABLE_MODULE'))
    • 今までテストしていたFreeBSDがむしろ特殊だったという事がわかってきたため、そのような構成向けのヘッダ出力をdefaultでoffに。onにするには、上記の定義をどこかでdefineするべし。

  • 時を超えて・・・
    (下の表記とほぼ同じなので削除)
    という感じでいいと思います。 -- Logue 2010-08-19 (木) 10:17:34
  • 上のコードからLogueさんが著述した部分をdiffで示した上で、経験された知見を第三者にわかるようにお書き下さい。(最初からdiffにして下さい)よろしくお願いします -- henoheno 2010-08-28 (土) 13:22:39
  • 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 2010-08-29 (日) 09:34:11
    	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 2010-08-29 (日) 14:05:21
  • いろいろ、漁って合成したので著作と言えるほどものはないかと。来歴は、2005年頃書いた雑談/11のコードに、他のハンドラとかぶると言われたので、かぶりそうなハンドラを条件で弾いた処理をいれたぐらいです。 -- Logue 2010-08-29 (日) 15:29:52
  • 何度もお手間かと思いますが、「一部upk氏のコードが含まれています。Varyの部分です。」というの部分の由来を明確に説明して下さい。 -- henoheno 2010-08-29 (日) 16:23:14
  • すみません、get_language_header_vary()という関数の部分が本家にもあると勘違いしていました。Plusのlang.phpで定義されているコードで、これがupk氏が書いたコードです。-- Logue 2010-08-31 (火) 22:01:57
    			$vary = get_language_header_vary();
    			if (! empty($vary)) $vary .= ',';
    			header('Vary: '.$vary.' Accept-Encoding');
  • こちらの件ですが、受け取りを拒否せざるをえません。言い辛いのですが、プロジェクトを危険にさらすレベルの痕跡が複数見受けられるため。 -- henoheno 2010-09-05 (日) 21:56:43
    • 複数の著作物を知らず知らずに紛れ込ませてしまえるような作り方をしている時点でまずいです。
    • パッチでなく実装を提示できてしまう点もまずいです。
    • ポイントの説明なしに露出させてしまえる点もまずいです。受け入れる側の負荷が高いです。
    • 読解に手間がかかるものを提示してしまえる点もまずいです。受け入れる側の負荷が高いです。
    • 絶対に動かないコードをテストせずに提示できる点もまずいです*3。ありえないです。
    • こうした事故を防ぐ手順は確実に存在しますが、身に着けていないのがまずいです。
    Logueさんには一旦立ち止まってもらって、よそのプロジェクトに迷惑をかけない = 問題の無い創作ができる体制を身に付けていただいてから活動を再開していただけないでしょうか。でないと、恐ろしさをよっぽど解っていないか、本当はそうでないかもしれないのに、手抜きをするキャラクターであるかのように受け取られてしまいます。 -- henoheno 2010-09-05 (日) 21:57:08
  • 最初の実装の貼り付けは、その後のdiffと内容が重複していますので削除させていただきます。 -- henoheno 2010-09-05 (日) 22:13:27
  • 上のdiff形式のコードなのですが・・・良く見たら「違いが無い部分」に半角スペースが挿入されていないのですよね(ツールのdiffを使っていたらそのような挙動は無いと思われます)。また、preformatted text表現のための半角スペースの挿入のされ方も一定ではありません。diff表現の先頭二行(ファイル名とか)が無いのも不思議でしたが、これを手で作りましたか? 答えなくても良いのですが、合っている場合、それは止めた方が良いです。 -- henoheno 2010-09-05 (日) 22:18:53
  • 関連: BugTrack2/333 BugTrack2/337 -- henoheno 2010-09-05 (日) 22:23:12
  • EmYvEZKSHyOvQHTGkTP -- cjbsmolcp? 2015-02-24 (火) 17:08:33


*1 なお、devサイトのメンテナンスは現在もぱんださんがなさってます
*2 Simple Machines Forum
*3 人のことはあまり言えないのですが、別のサイトでも指摘されていましたよね

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2015-02-24 (火) 17:08:33
Site admin: PukiWiki Development Team

PukiWiki 1.5.2+ © 2001-2019 PukiWiki Development Team. Powered by PHP 5.6.40-0+deb8u7. HTML convert time: 0.350 sec.

OSDN