Squidの更新パターンでインターネットアクセスを高速化する

 帯域幅の制限は、インターネットに接続している多くの人にとって今なお残る問題の1つだ。しかし、プロキシキャッシュサーバSquidをネットワークにインストールし、設定パラメータを用いてバイトヒット率を上げれば、利用可能な帯域幅を3~6割近くも拡大できる。

 Squidは、きめ細かいチューニングによってさまざまなニーズに対応できる。現行の安定版には少なくとも249個のパラメータがあり、丁寧なコメントが付いた設定ファイル(通常は「/etc/squid.conf」)は4,600行以上もある。このボリュームには、経験豊かな管理者でも圧倒されるだろう。設定の変更はすべてこのファイル上で行う。

 1週間では一杯にならない(理想をいえば1か月以上持つような)大きなキャッシュがほしいところだ。実際に必要なサイズは、ネットワークのトラフィック量によって変わってくる。キャッシュのサイズが大きいほど、要求されたオブジェクトがキャッシュに保存されている可能性が高くなる。

 メモリ容量は、オペレーティングシステムおよびSquidの実行に必要な分に加え、キャッシュサイズの約1%をキャッシュのデータベース用に確保する必要がある。つまり、100GBのディスク領域をキャッシュにする場合は、そのデータベース用に約1GB、OSおよびSquid用に約100MBが必要になる。

 Squidでキャッシュ可能なオブジェクトの最大サイズは、デフォルトで4MBである。ただし、最近のメディアリッチなインターネットの環境を考えるとこれでは少なすぎる。クライアント側で多数の動画やソフトウェアパッケージをダウンロードするなら、日常的にダウンロードされるファイルの最大サイズを考慮して値を(たとえば100MBに)増やすとよい。

 キャッシュによる保存と提供が行われる対象は、更新パターン(refresh pattern)によって決まる。理想的には、コンテンツを提供するWebサーバの情報に従って、キャッシュ可能な対象と期間を決められるようにしたい。こうした情報は、Squidによって処理され理解されるHTTPヘッダに記されている。残念ながら、ほとんどのサーバによって与えられる情報はWebサーバのデフォルト設定であり、帯域幅の大幅な節約にはつながらない。

 更新パターンの形式を以下に示す。

refresh_pattern [-i] regex min percent max [options]

 ここで、minとmaxは時間を分単位で指定した値、percentはパーセント値である。optionsには次のものを指定できる。

  • override-expire:WebサーバからのExpires(有効期限)ヘッダを無視する。
  • override-lastmod:WebサーバからのLast-modified(最終更新日)ヘッダを無視する。
  • reload-into-ims:クライアントからのreload(再読み込み)要求をIf-Modified-Since(更新日による条件付き取得)要求に変換する。
  • ignore-reload:クライアントのno-cache(キャッシュを利用せず元のサーバからリロード)ディレクティブを無視する。よって、キャッシュから取得可能であればそれを利用して要求に応える。
  • ignore-no-cache:Webサーバからのno-cache(オブジェクトをキャッシュ不可にする)ディレクティブを無視する。
  • ignore-no-store:Webサーバからのno-store(やはりオブジェクトをキャッシュ不可にする)ディレクティブを無視する。
  • ignore-private:Webサーバからのprivate(同じくオブジェクトをキャッシュ不可にする)ディレクティブを無視する。
  • ignore-auth:権限の承認を要求するオブジェクトをキャッシュ不可するとの 制限を無視する。
  • refresh-ims:クライアントからのreflesh(更新)要求をIf-Modified-Since要求に変換する。

 これらのオプションのどれが利用できるかはSquidのバージョンによって異なるので、設定ファイルで確認すること。

 更新パターンが有効なのは、元のサーバからのExpiresヘッダが存在しない場合、あるいは利用する更新パターンにignore-expireオプションが含まれる場合である。次の例を見てみよう。

refresh_pattern -i \.gif$ 1440 20% 10080.

 これは次のような意味になる。

  • 1)名前が「.gif」または「.GIF」で終わるオブジェクト(つまりgif画像ファイル)のいずれにもExpiresヘッダがない場合は2)に進む。それ以外の場合は6)に進む。
  • 2)保存時間(オブジェクトがキャッシュサーバ上にある時間)が1,440分未満の場合は、まだ新しいオブジェクトと見なしてそれを渡し、処理を終了する。それ以外の場合は3)に進む。
  • 3)保存時間が10,080分より長い場合は、古いオブジェクトと見なして元のサーバにアクセスして新しいコピーを取得し、処理を終了する。それ以外の場合は4)に進む。
  • 4)保存時間が1,440~10,080分の場合は、lm-factorを使ってオブジェクトの鮮度を判断する。lm-factorは、キャッシュサーバ上でのオブジェクトの保存時間を、元のサーバにおけるそのオブジェクトの作成または変更からの経過時間で割った値である。たとえば、元のサーバで10,000分前に作成されたオブジェクトが、キャッシュサーバ上に1,800分(=保存時間)に保存されている場合、lm-factorは1,800/10,000 = 18%となる。
  • 5)lm-factorが更新パターンの指定パーセント値(=20%)より小さい場合、新しいオブジェクトと見なして渡し、処理を終了する。それ以外の場合は6)に進む。
  • 6)古いオブジェクトと見なし、元のサーバにアクセスして新しいコピーを取得する。

 動画や画像、音声、実行ファイル、アーカイブなど、ファイルの名前が同じであればその内容にも変化がないことがほとんどであるオブジェクトの場合は、更新パターンを変更して新しいオブジェクトの基準を甘くすることで、キャッシュのヒット率を上げることができる。たとえば、上記の更新パターンは、次のように変更できる。

refresh_pattern ^ftp: 1440 20% 10080
refresh_pattern ^gopher: 1440 0% 1440
refresh_pattern -i \.(gif|png|jpg|jpeg|ico)$ 10080 90% 43200 ignore-expire ignore-no-cache ignore-no-store ignore-private
refresh_pattern -i \.(iso|avi|wav|mp3|mp4|mpeg|swf|flv|x-flv)$ 43200 90% 432000 ignore-expire ignore-no-cache ignore-no-store ignore-private
refresh_pattern -i \.(deb|rpm|exe|zip|tar|tgz|ram|rar|bin|ppt|doc|tiff)$ 10080 90% 43200 ignore-expire ignore-no-cache ignore-no-store ignore-private
refresh_pattern -i \.index.(html|htm)$ 0 40% 10080
refresh_pattern -i \.(html|htm|css|js)$ 1440 40% 40320
refresh_pattern . 0 40% 40320

 少なくとも我々には理解しがたい行為だが、元のサーバ側(youtube.comなど)があらゆる手を尽くしてコンテンツのキャッシュを困難または不可能にしようとしている場合がある。上記のオプションは、こうした制限の克服に役立つだろう。

 更新パターンは、すべての要求に対して、該当する規則が見つかるまで上位のものから順にマッチングが行われる。最後の規則はキャッチオール規則で、上位の規則のいずれにも当てはまらなかった要求はすべて、この規則とのマッチングが行われる。通常、FTPやgopherといったほかのプロトコルについては、デフォルトのキャッチオール規則をリストの最上位に別途用意し、下位の規則とのマッチングが行われないようにしておく。

 デフォルトのSquidでは、動的コンテンツのキャッシュを行わない。動的コンテンツは、“cgi-bin”または“?”とのマッチングによって判断される。Squidのこれまでのバージョンでは、この機能が“hierarchy_stoplist”および“cache deny”の設定によって有効になっていた。3.1以降のバージョンでは、この機能の有効化に「refresh_pattern (/cgi-bin/|\?) 0 0% 0」のような更新パターンが使われている。これにより、キャッシュ可能にできる動的コンテンツの提供サイトをバイパス規則で指定することが可能になった。たとえば、次のように更新パターンを設定すればよい。

refresh_pattern -i movies.com/.* 10080 90% 43200
refresh_pattern (/cgi-bin/|\?) 0 0% 0

 この場合は、movies.comのコンテンツが“?”を含むURLで提供されていても、ほかの条件をすべて満たしていれば、このコンテンツはキャッシュされる。

 古いバージョンのSquidでは、例外としたいコンテンツプロバイダについてアクセス制御リスト(ACL)を定義し、「cache deny」規則よりも前に「cache allow」を使ってこれを免除する必要があるだろう。以下は、SquidのWikiに記されている例である。

# Let the client's favourite video site through
acl youtube dstdomain .youtube.com
cache allow youtube
# Now stop other dynamic stuff being cached
hierarchy_stoplist cgi-bin ?
acl QUERY urlpath_regex cgi-bin \?
cache deny QUERY

 Squidが発するDNS要求は多く、HTTP要求ごとにDNS要求を1つ出す。サーバにDNSキャッシュサーバをインストールし、これをSquidで利用すればDNS要求を減らすことができる。その方法については、こちらが参考になるだろう。

 ネットワークによっては、Microsoftのwindowsupdate.com(ほとんどすべてのWindows PCがOSのアップデートに利用している)のようなサイトが、最も帯域幅を必要とするサイトの1つになっている。残念ながら、こうしたサイトは部分的にコンテンツを提供する(HTTPステータスコード206を返す)ため、現状のSquidではキャッシュができない。クライアントマシンの管理を行っているなら、Microsoft Updateサーバを用意することでwindowsupdate用のキャッシュが扱えるようになる。Updateサーバが使えないなら、Squidの帯域幅管理手法である遅延プール(delay pool)を使って、ピーク時間帯にwindowsupdateが消費する帯域幅を制限することができる。クライアント側は、それ以外の時間帯に接続を行ってアップデートを完了することになる。

 次の例は、グローバル遅延プールの1つを64Kbps(8KBps)に設定している。これにより、10:00~16:00のピーク時間帯は宛先ドメインがwindowsupdate.comのトラフィックが64Kbpsに制限される。

acl winupdate dstdomain .windowsupdate.com
acl peakperiod time 10:00-16:00
delay_pools 1
delay_class 1 1
# 64 Kbit/s
delay_parameters 1 8000/8000
delay_access 1 allow winupdate peakperiod

 上記のような変更を行うことで、私が利用しているSquidのバイトヒット率は8%から26~37%に向上した。バイトヒット率が33%だとすれば、全トラフィックの3分の1が(より低速なインターネット上のリンクからではなく)キャッシュから得られていることになる。なお、監視およびログ解析によるSquidのパフォーマンス評価には、squid3-clientやcalamarisが使える。

Solomon AsareはHTTP圧縮サービスDelXyの開発者。

Linux.com 原文(2008年11月20日)