ZiproxyでモバイルデバイスにおけるWebページの読み込みを高速化する

 ZiproxyはWebプロキシサーバだが、コンテンツをキャッシュするSquidのようなWebプロキシとは異なり、Webから取得したコンテンツを圧縮してクライアントに転送することを目的としている。これは、携帯インターネット端末のようなモバイルデバイス向けのサービスとして役立つ。こうしたデバイスでは、元の画像の解像度や画質の高さを表示に反映できず、低速かつ通信料が割高なデータ通信プランの下でブラウザが使われるからだ。

 Ziproxyでは、画像を圧縮して画質のより低い(サイズの小さな)JPEGまたはJPEG 2000形式のファイルに変換したり、表示域を縮小したうえでHTMLおよびCSSコンテンツをgzipで圧縮したりできる。JPEG 2000画像はデコードにそれなりのCPUパワーを必要とする反面、PNG画像や通常のJPEG画像に比べてかなりサイズが小さくなる。多くのWebブラウザはgzipエンコードされたコンテンツを自動的にデコードしてくれるので、エンドユーザにはHTMLやCSSが圧縮されているかどうかはわからない。

 Ziproxyのパッケージは、Fedora、Ubuntu、openSUSEのどのリポジトリにも入っていない。ここでは、Ziproxyの最新版2.5.2のソースを使って64ビット版Fedora 9マシンでビルドを行う。画像をJPEG 2000形式に圧縮する場合は、Ziproxyのビルド前にJasPerの開発版パッケージをインストールしておく必要がある。JasPerはopenSUSEの1-Clickインストールに対応しているほか、Ubuntu Hardy用パッケージやFedora 9用パッケージ(Fedora 9リポジトリのjasper-devel)もある。

 以下に、Ziproxyをビルドするコマンドを示す。なお、ZiproxyをJPEG 2000対応にするには、JasPerの開発版パッケージがインストール済みでも「--with-jasper」オプションを指定する必要があった。

$ tar xjf /FromWeb/ziproxy-2.5.2.tar.bz2
$ cd ./ziproxy-2.5.2/
$ ./configure --with-jasper
$ make
$ sudo make install
$ su -l
# cp -av etc/ziproxy /etc
# chown -R root.root /etc/ziproxy

 Ziproxyにはデーモンとして起動するためのinit.dファイルが付属しているが、このスクリプトを使ったZiproxyの起動にはいくつか問題がある。まず、Ziproxyのパスがハードコーディングされており、「/usr/local」にZiproxyをインストールするとバイナリが見つからない。さらにひどいのは、rootでZiproxyを起動していることだ。これらの問題を解決するために、Ziproxyの実行用に新たなユーザを作成し、起動用スクリプトを以下のように変更した。元のスクリプトでgprintfになっていた部分は“g”を消してprintfにしてある。大きな変更点は、suコマンドを使ってZiproxyを実行するようにしたことだ。

# useradd ziproxy
# mkdir /var/log/ziproxy
# chown ziproxy.ziproxy /var/log/ziproxy
# cp /.../ziproxy-2.5.2/etc/init.d/ziproxy /etc/init.d
# vi /etc/init.d/ziproxy
...
PID_FILE=/var/tmp/ziproxy.pid
ZIPROXY=/usr/local/bin/ziproxy
...
printf "Starting %s: " "${PROGNAME}"
...
su -c "${ZIPROXY} -d -c ${ZIPROXY_CONF} >${PID_FILE}" ziproxy
...
# /etc/init.d/ziproxy start

 Ziproxyはxinitdを利用して実行することも、スタンドアロンのデーモンとして実行することも可能が、ここでは後者の方法をとる。通常はそのほうがパフォーマンス面で有利である。xinitd経由で実行されるクライアント接続フィルタリング機能があれば、パケットフィルタリングとSSHポート転送の利用によって、インターネットからZiproxyへのアクセスのセキュリティ保護が可能になる。

 Ziproxyの起動前に、設定ファイルである「/etc/ziproxy/ziproxy.conf」の内容を確認しておこう。最初のオプションでは、Ziproxyをバインドするポートおよびアドレスを指定する。OnlyFromオプションには、Ziproxyへのアクセスを許可するIPアドレスまたはその範囲(「<始点アドレス>-<終点アドレス>」の形式)を指定する。OnlyFromの指定がないと、Ziproxyがバインドされているアドレスおよびポートに接続可能な任意のクライアントにサービスが提供される。Ziproxyをモバイルデバイス向けのWebプロキシにする場合は「OnlyFrom=127.0.0.1」とし、SSHポート転送を利用してこのWebプロキシへの接続を行えばよい。

 ziproxy.confファイル内のオプションの多くは、再圧縮の対象とする画像フォーマットやその圧縮先フォーマット、圧縮レベルに関するパラメータを指定するものだ。冒頭で述べたように、最小限のシステムRAMと比較的低速なCPUしか持たないデバイス(インターネット端末など)が対象になる場合は、画像をJPEG 2000形式に圧縮する必要はないだろう。一方、よりCPUパワーの高いノートPCから低速なリンク経由でこのWebプロキシにアクセスする場合は、すべての画像をJPEG 2000形式に圧縮し直してもよい。

 画像圧縮レベルの設定は、画像の大きさ(ピクセル数)ごとに変えることができる。Webページでは、大きな画像ほど高画質で表示させたいものだ。また、レベルを負の値で指定すると、画像はグレースケールに変換されたうえで指定の画質で圧縮される。画質の指定には4つの値を使い、それぞれは5,000ピクセル以下、5,001~50,000ピクセル、50,001~250,000ピクセル、250,001ピクセル以上の画像に対する画質レベルを表す(例:「ImageQuality={17,20,23,25}」)。ただし、JPEG 2000への圧縮を行う場合は「ImageQuality」の代わりに「JP2ImageQuality」というキーワードを用いる。

 デフォルトでは、Ziproxyによる再圧縮の対象がPNG、JPG、GIF画像になっている。これら各画像の再圧縮を無効にするには、「ProcessJPG」(JPG画像の場合)のようなブール型オプションを使う。可能であれば通常のJPEGではなくJPEG 2000への再圧縮を行うには「ProcessToJP2=true」とする。逆に、JPEG 2000画像を通常のJPEGに再圧縮するには「ForceOutputNoJP2=true」とする。JPEG 2000画像の圧縮方法に関するオプションはほかにもあるが、詳細についてはサンプルのziproxy.confファイルを参照してほしい。

 テキスト圧縮のオン/オフは「Gzip=true/false」で指定する(デフォルト値はtrue)。クライアントがgzip圧縮されたコンテンツを扱えない場合や、SSHのプロキシにアクセスしてSSH圧縮を利用する場合は、オフにするとよい。「Compressible={"shockwave","foo"}」オプションを使えば、Ziproxyにほかのデータタイプを圧縮させることも可能だ。

 また「Process」というプレフィックスで始まるオプション群では、HTML、CSS、JavaScriptの各ファイルに途中で手を加えるかどうかを指定できる。これらのオプションによって各コンテンツはいくらか縮小されるが、表示内容が実際のコンテンツとは異なることを示すマーキングが行われる。

 MaxSizeオプションを使えば、Ziproxyで(再)圧縮を行うファイルの上限サイズ(バイト数)を指定できる。

 ImageQualityにすべて負の値を指定して、Ziproxyにすべての画像をグレースケール変換させれば、Webページのどの画像がZiproxyで処理されたかがひと目でわかる。Ziproxyの最初の動作確認をlinux.comとslashdot.orgのページで行い、ログファイルを調べたところ、画像があまり圧縮されていないようだったので、この方法を試すと、グレースケール表示になっていたのはFlash形式でない広告だけだった。同じ設定でarstechnica.comのようなほかのサイトを開くと、ページ上のほとんどの画像がグレースケールになり、ZiproxyからWebブラウザへの転送バイト数が大幅に削減された。

 「Project Gutenberg」サイトの閲覧時には、転送されるCSSファイルの多くが元のサイズの25%に圧縮されていた。いずれも元ファイルは5~20KBほどだが、接続速度が遅い場合には転送量の削減が大きく効いてくる。同サイトのホームページにあるモバイル機器用リーダの30KBのイメージも5KBに圧縮された。『 Dead Souls 』(邦題:死せる魂)のテキストなど、もっと大きなHTMLファイルのダウンロードでは、Ziproxyを使うことで転送サイズを60%ほど削減できた。書籍検索結果のページも、Ziproxyを経由することで8KBから3KBに抑えられた。Gutenbergサイトにおける最後のテストとして、『 The Gambler 』(ドストエフスキー著、邦題:賭博者)の343KBの非圧縮バージョンをダウンロードしたところ、ZiproxyからWebブラウザへの転送サイズは89KBとなった。これに対し、同じサイトにあるzip圧縮バージョンのサイズは126KBだった。もちろん、非圧縮バージョンをダウンロードする場合はZiproxyとGutenbergサイトの間の転送サイズが大きくなるが、それでもZiproxyとクライアント側Webブラウザの間の転送バイト数は確実に減る。

 flickr.comのように画像の多いサイトでは、再圧縮によってもっと大きな効果が得られる。JPEGの圧縮レベルを-20ないし-15とすれば、多くの画像が元のサイズの10分の1未満になる。もちろん、こうした極端な圧縮を行うとJPEG圧縮画像はグレースケール表示になる。

さらなるチューニング

 ローカルホスト以外からは接続できないように設定してZiproxyを使うという手もある。この場合、クライアントはSSHポート転送を使ってZiproxyにアクセスし、クライアントマシン側のポートをZiproxyの実行マシンに接続することになる。SSHには通信を圧縮する「-C」オプションがあるが、SSHによる圧縮をオフにしてZiproxyを使ったほうが圧縮効率は向上する(特に画像ファイルの場合)。汎用の圧縮(「ssh -C」の場合はgzipが使われる)は、画像用のJPEG圧縮にはかなわない。

 Webサイトの閲覧では、広告やセーフブラウジングのチェックがバイト転送の最大のネックになりうる。とはいえ、Adblock Plusのようなソフトウェアで広告を除去している場合でも、Ziproxyを使えばクライアントへのバイト転送量をかなり減らせる。ZiproxyによるCSSおよびHTMLコンテンツの圧縮効果は、クライアント側がサポートしている暗黙的な圧縮がすでにそのWebサイトで利用されているかどうかで変わってくる。gzip圧縮はHTMLおよびCSSデータをエンドユーザにわからない形で圧縮してくれるが、少しでもバイト数を減らすためには、設定オプションを使って画像の圧縮方法をチューニングするとよい。

Ben Martinは10年以上前からファイルシステムに携わっている。博士号を持ち、現在はlibferris、各種ファイルシステム、検索ソリューションを中心としたコンサルティング業務に従事。

Linux.com 原文(2008年9月24日)