Varnish + Nginx:Ubuntu上の高負荷ウェブサイトを救う「切り札」

Ubuntu tutorial - IT technology blog
Ubuntu tutorial - IT technology blog

「高トラフィック」の悪夢とサーバーダウンの不安

ウェブサイトが安定して稼働していると思っていた矢先、突然ダウンしてしまう場面を想像してみてください。原因は、記事がバズったことや、広告キャンペーンによるトラフィックの急増かもしれません。筆者もかつて、502 Bad Gatewayエラーを連発する VPSの対応で徹夜したことがあります。RAMを4GBから16GBにアップグレードしても、CPU使用率は制御不能なまま100%に跳ね上がっていました。

実際の問題はサーバーのスペック不足ではなく、リクエストの処理方法にありました。アクセスがあるたびに、NginxはPHP-FPMを呼び出し、PHPはMySQLにクエリを投げ、ようやく結果を返します。このプロセスが数千回繰り返されることで、リソースはあっという間に枯渇してしまいます。

なぜ高スペックなサーバーでも重くなるのか?

ブログや商品ページのコンテンツの多くは、頻繁には変更されません。同じコンテンツに対してサーバーに何度もPHPコードを実行させ、データベースにクエリを投げさせるのは、非常に大きな無駄です。

主な原因はI/O WaitCPU Overloadです。NginxのFastCGI Cacheを使用しても、膨大な同時接続(コンカレント)リクエストが発生すると、パフォーマンスには限界が生じます。ここで、負荷を肩代わりするためのより専門的なキャッシュレイヤーが必要になります。

現在主流の3つの解決策

パフォーマンスの課題に直面したとき、エンジニアは通常、次の3つのアプローチから選択します。

  • ハードウェアのアップグレード: 手っ取り早いですがコストがかかります。RAMを無限に増やすことはできませんし、冗長な処理という根本的な解決にはなりません。
  • オブジェクトキャッシュ(Redis/Memcached)の利用: データベースの負荷を軽減します。しかし、Redis from データを取得するために依然としてPHPを動かす必要があり、CPUは働き続けることになります。
  • リバースプロキシキャッシュの利用: これが最も効果的な解決策です。ウェブサーバーの前面にキャッシュレイヤーを配置し、HTMLをRAMに保存して、ユーザーに即座に返します。

Varnish Cache — 超高速な「中継ステーション」

Varnish Cacheは非常に強力なHTTPアクセラレータです。自動販売機のようなものだと考えてください。ユーザーがウェブページをリクエストすると、VarnishはRAM内にコピーがあるか確認します。あれば(Cache Hit)、わずか10〜50msで返します。なければ(Cache Miss)、そこで初めてNginxにリクエストを転送します。

筆者の実務経験では、Varnishを導入した後、一般的なWordPressサイトでCPU使用率を10%未満に抑えつつ、負荷耐性を20倍に高めることができました。以下に、UbuntuでVarnishとNginxを組み合わせる方法を説明します。

詳細なインストール手順

ステップ1:NginxとVarnishのインストール

まず、以下のコマンドでシステムを更新し、必要なパッケージをインストールします。

sudo apt update
sudo apt install nginx varnish -y

ステップ2:Nginxをバックエンドに変更する

デフォルトではNginxはポート80で動作しています。Varnishを「最前線」(ポート80)に配置し、Nginxを後方(ポート8080)に下げます。

ウェブサイトの設定ファイル(通常はdefaultファイル)を開きます:

sudo nano /etc/nginx/sites-available/default

listen 80;listen 8080; に変更します。IPv6の行がある場合は、それも忘れずに変更してください:

server {
    listen 8080 default_server;
    listen [::]:8080 default_server;
    # ... 他の設定はそのまま維持 ...
}

その後、構文をチェックしてNginxを再起動します:

sudo nginx -t
sudo systemctl restart nginx

ステップ3:Varnishをポート80で待機するように設定する

次に、Varnishがポート80でリクエストを受け取り、ポート8080のNginxからデータを取得するように設定します。

Varnishのサービス設定ファイルを編集します:

sudo systemctl edit --full varnish

ExecStart の行を探し、-a :6081-a :80 に変更します:

ExecStart=/usr/sbin/varnishd -a :80 -a localhost:8443,PROXY -f /etc/varnish/default.vcl -s malloc,512m

ヒント: -s malloc,512m パラメータは、キャッシュ保存用に512MBのRAMを割り当てます。サーバーに8GB以上のRAMがある場合は、思い切って1gや2gに増やしても良いでしょう。

次に、VCLファイル内でVarnishがバックエンドのNginxを参照するように設定します:

sudo nano /etc/varnish/default.vcl

backendブロックを確認し、以下の設定になっているか確認します:

backend default {
    .host = "127.0.0.1";
    .port = "8080";
}

最後に、サービスを再起動します:

sudo systemctl daemon-reload
sudo systemctl restart varnish

SSL(HTTPS)への対応

VarnishはHTTPSを直接サポートしていません。これに対処するために、SSL Termination(SSL終端)という構成をとります。

データフローは次のようになります:**ユーザー (Port 443) -> Nginx (SSL処理) -> Varnish (Port 80) -> Nginx (バックエンド – Port 8080)**。この方法により、安全なSSL証明書を維持しつつ、Varnishの爆速なスピードを享受できます。

ポート443をリッスンするNginxサーバーブロックを設定し、Let’s Encryptをインストールして、proxy_pass でリクエストを http://127.0.0.1:80 に転送するだけです。

実際の効果を確認する

Varnishが動作しているか確認するには、curl コマンドでヘッダーを確認します:

curl -I http://your-domain.com

Via: 1.1 varnish という行が表示されれば、正常に動作しています。より詳細に監視するには、varnishstat コマンドを使用します。このツールはキャッシュのHit/Miss率をリアルタイムで表示し、リクエストの何パーセントがRAMから提供されているかを確認できます。

おわりに

Varnishの導入自体はそれほど難しくありません。ただし、管理画面(wp-adminなど)や決済ページを誤ってキャッシュしないように、default.vcl ファイルを微調整する必要があります。

まずはこの基本設定から始めてみてください。その後、使用しているソースコード(WordPressやLaravelなど)に応じて、Cookieの除外ルールなどを追加していくことになります。NginxとVarnishの強力なコンビがあれば、ハードウェアの追加コストをかけずに、1日あたり数百万件のアクセスをさばくことができるでしょう。

Share: