HHVM 上で動かしている MediaWiki の二重 gzip 圧縮問題
スパロボ Wikiをはじめとするクリエイターズネットワークの MediaWiki は、1 月末から表示速度改善・負荷削減のため HHVM + Nginx で動かしているのだが、そのときから特定の環境で表示がおかしいという問題が発生していたようだった。手元の Firefox、Chrome(PC・Android)では一切発生しなかったので気づかなかったが、改めて確認すると IE と Safari で CSS が一切適用されないという問題が発生していた。
原因
原因を探してもなかなか見つからなかったが、開発者ツールを見ていると load.php によるスタイルシート読み込みの一部で変な文字化けが発生していた。本家の「ResourceLoader/Features#Resource: Styles」を見ると gzip 圧縮機能が含まれていた。このあたりが怪しいと思い、検索していくと以下のページがヒットした。
- php - How to disable Nginx double gzip encoding when fastcgi backend occasionally serves gzipped with content-encoding? - Stack Overflow
- HHVM always compresses output if Accept-Encoding: gzip is set, even if zlib.output_compression=Off is set · Issue #5316 · facebook/hhvm
どうやら HHVM と Nginx の両方の設定(HHVM については標準・省略時設定)により二重に gzip 圧縮されていたらしい。この場合、HTTP レスポンスヘッダの Content-Encoding ヘッダが gzip, gzip
という値になる。ここで厄介だったのが、Firefox と Chrome はこの値に対応しており圧縮されていたファイルが正しく展開されるが、IE や Safari は未対応で文字化けファイルと化してしまうということ。この挙動は予想できず対応が遅れてしまった。
対策
ではどうやって対処するか。調べると以下のコミットが見つかった。
片方の gzip 圧縮を無効にすると良いということだった。このコミットでは HHVM 側の gzip 圧縮機能を無効にしている。この他に、MediaWiki 側の圧縮機能を無効にすることもできる(「Manual:$wgDisableOutputCompression - MediaWiki」)。HHVM 側の方がカバーできる範囲が広いので、今回はこちらを選択した。サーバー用の hhvm.ini に以下を記述する。
zlib.output_compression = "Off"
これにより、手元の全ブラウザで正常に表示されることを確認した。
今回のメンテナンス、学校の関係で時間がない中行った結果、確認不足だったりすぐに対応できなかったりしたので申し訳ない限りなのだが、特殊な環境の一部でのみ発生する問題だったので、仮に早く見つかったとしてもすぐに解決できたか怪しい。HHVM 上で MediaWiki を動かしているところはほとんど見ないし、日本語の情報も一切ないので、こういう問題が発生したときの対処は結構難しい…