2026年5月26日
2026年5月26日
WordPressへの突然のトラフィックスパイクを対処する方法
はじめに
SNSで記事がバズったり、メディアに掲載されたりして突然大量のアクセスが集中すると、準備のできていないWordPressサイトは簡単にダウンします。このようなトラフィックスパイクを生き残るには、事前の準備と即座に実行できる対応手順が不可欠です。本記事では、キャッシュ・CDN・データベース接続プールを活用してスパイクに耐えるWordPress環境の構築方法を解説します。
症状・原因
- 急激なアクセス増加でサーバーのCPUが100%に達し500エラーが多発する
- MySQLの接続数が上限(
max_connections)に達し「Too many connections」エラーが発生する - 管理画面(wp-admin)にもアクセスできずメンテナンス操作ができない
- PHPプロセスが枯渇してFast CGI queue overflowが発生する
- 普段はキャッシュが機能しているがログイン済みユーザーや特定URLでキャッシュが無効になっている
解決手順
ステップ1:WP Super Cacheでページキャッシュを有効化
最も即効性の高い対策として、ページキャッシュを有効にします。
<?php
// wp-config.php に追加
define( 'WP_CACHE', true );
// WP Super Cache のカスタム設定(wp-content/wp-cache-config.php)
// インストール後に以下の設定を確認・変更
$cache_enabled = TRUE;
$super_cache_enabled = TRUE; // mod_rewrite を使う高速キャッシュ
$cache_compression = TRUE;
$cache_max_time = 3600; // 1時間キャッシュ
$cache_rejected_uri = [
'/wp-admin/',
'/wp-login.php',
'/wp-comments-post.php',
'/cart/', // WooCommerce カート
'/checkout/', // WooCommerce チェックアウト
'/my-account/', // ログイン済みページ
];
// ログイン済みユーザーはキャッシュしない
$cache_not_logged_in = FALSE; // ログインユーザーにはキャッシュを返さない
// .htaccess で mod_rewrite によるキャッシュ配信を設定
// (WP Super Cache が自動生成するが手動で確認)
# Apache mod_rewrite キャッシュルール確認
grep -A 30 "WP Super Cache" /var/www/html/.htaccess
# キャッシュファイルが生成されているか確認
ls -la /var/www/html/wp-content/cache/supercache/
find /var/www/html/wp-content/cache/supercache/ -name "*.html" | wc -l
ステップ2:CDNへのトラフィック分散
Cloudflareを使って静的アセットとページキャッシュをエッジで配信します。
# Cloudflare APIを使ってキャッシュルールを設定
CLOUDFLARE_TOKEN="your_api_token"
ZONE_ID="your_zone_id"
# 静的ファイルのキャッシュルールを作成
curl -X POST \
"https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/cache/rules" \
-H "Authorization: Bearer ${CLOUDFLARE_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"rules": [{
"expression": "(http.request.uri.path matches \"\\.(css|js|png|jpg|gif|ico|woff2)$\")",
"action": "set_cache_settings",
"action_parameters": {
"cache": true,
"edge_ttl": {
"mode": "override_origin",
"default": 86400
},
"browser_ttl": {
"mode": "override_origin",
"default": 3600
}
}
}]
}'
# WordPress の wp-config.php でCDN URLを設定
# define('WP_CONTENT_URL', 'https://cdn.example.com/wp-content');
ステップ3:ProxySQLによるデータベース接続プール
高トラフィック時のDB接続枯渇をProxySQLで解決します。
# ProxySQL のインストール(Ubuntu)
wget https://github.com/sysown/proxysql/releases/download/v2.5.5/proxysql_2.5.5-ubuntu22_amd64.deb
sudo dpkg -i proxysql_2.5.5-ubuntu22_amd64.deb
sudo systemctl start proxysql
# ProxySQL Admin に接続して設定
mysql -u admin -padmin -h 127.0.0.1 -P 6032 << 'EOF'
-- バックエンドのMySQLサーバーを追加
INSERT INTO mysql_servers (hostgroup_id, hostname, port, max_connections)
VALUES (10, '127.0.0.1', 3306, 200);
-- 読み取りグループの設定
INSERT INTO mysql_servers (hostgroup_id, hostname, port, max_connections)
VALUES (20, '192.168.1.20', 3306, 400); -- レプリカ
-- 接続プールの設定
UPDATE global_variables
SET variable_value = '100'
WHERE variable_name = 'mysql-max_connections';
UPDATE global_variables
SET variable_value = '3000'
WHERE variable_name = 'mysql-connection_max_age_ms';
-- 設定を適用
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
LOAD MYSQL VARIABLES TO RUNTIME;
SAVE MYSQL VARIABLES TO DISK;
EOF
# wp-config.php の DB_HOST を ProxySQL に向ける
# define('DB_HOST', '127.0.0.1:6033'); // ProxySQLのポートは6033
ステップ4:PHPプロセスとサーバーのオートスケール設定
PHP-FPMのプロセス数を動的に調整してスパイクに対応します。
# /etc/php/8.2/fpm/pool.d/www.conf の設定
[www]
pm = dynamic
pm.max_children = 100 # 最大プロセス数
pm.start_servers = 20 # 起動時プロセス数
pm.min_spare_servers = 10 # 最小待機プロセス数
pm.max_spare_servers = 40 # 最大待機プロセス数
pm.process_idle_timeout = 30s # アイドルタイムアウト
pm.max_requests = 500 # 各プロセスの最大リクエスト数(メモリリーク対策)
# nginx のワーカー設定
# /etc/nginx/nginx.conf
worker_processes auto; # CPUコア数に合わせる
worker_rlimit_nofile 65535;
events {
worker_connections 4096;
use epoll;
multi_accept on;
}
# 設定反映
sudo php-fpm8.2 -t && sudo systemctl reload php8.2-fpm
sudo nginx -t && sudo systemctl reload nginx
ステップ5:過負荷時のメンテナンスモード設定
緊急時にWordPressをメンテナンスモードに切り替えて管理者だけが操作できるようにします。
<?php
// mu-plugins/emergency-maintenance.php
/**
* 緊急メンテナンスモード
* 環境変数 WP_MAINTENANCE=true でアクティブ化
*/
add_action( 'init', function () {
// 環境変数でメンテナンスモードを制御
if ( 'true' !== getenv( 'WP_MAINTENANCE' ) ) {
return;
}
// 管理者とローカルIPは通過させる
$allowed_ips = [ '127.0.0.1', '::1', '203.0.113.10' ]; // 管理者のIP
$client_ip = $_SERVER['REMOTE_ADDR'] ?? '';
if ( in_array( $client_ip, $allowed_ips, true ) ) {
return;
}
// ログイン済み管理者は通過
if ( function_exists( 'is_user_logged_in' ) && is_user_logged_in() ) {
$user = wp_get_current_user();
if ( in_array( 'administrator', (array) $user->roles, true ) ) {
return;
}
}
// 503 メンテナンスページを返す
http_response_code( 503 );
header( 'Retry-After: 3600' );
header( 'Content-Type: text/html; charset=UTF-8' );
echo '<!DOCTYPE html><html lang="ja"><head><meta charset="UTF-8">';
echo '<title>メンテナンス中</title></head><body>';
echo '<h1>只今メンテナンス中です</h1>';
echo '<p>大変ご不便をおかけします。しばらくお待ちください。</p>';
echo '</body></html>';
exit;
} );
// メンテナンスモードの有効化コマンド(WP-CLI)
// export WP_MAINTENANCE=true && sudo systemctl reload php8.2-fpm
注意事項
- WP Super CacheのSuper Cacheモード(mod_rewrite)はPHPを経由しないため最速だが、設定ミスでキャッシュが効かない場合がある。
curl -I https://example.com/ | grep X-Cacheでキャッシュヒットを確認すること - ProxySQLの
max_connectionsはMySQLのmax_connections以下に設定すること。ProxySQL側で多すぎる接続を許可するとMySQL側でエラーが発生する - オートスケーリング(AWS Auto Scaling等)を使う場合、WordPressのファイルシステムを共有ストレージ(EFS等)に移行しないと各ノードでファイルの不整合が発生する
- PHPのメモリ制限(
memory_limit)を超えるプロセスは即時強制終了されるため、スパイク時にmemory_limit = 256M以上に設定することを検討する - CloudflareのキャッシュはデフォルトでHTMLページをキャッシュしない。「Cache Level: Cache Everything」ページルールを設定する際はログインページ等の除外設定を忘れずに行う
まとめ
トラフィックスパイクへの対応は「キャッシュ→CDN→接続プール→スケールアウト」の順で段階的に実施することで、コストを抑えながら効果を最大化できます。日頃からの監視については「New Relic APMでWordPressのパフォーマンスを監視する方法」を、CDNの選定については「WordPressに最適なCDNを選ぶ方法」も参照してください。