Nginx + PHP + WordPress サーバーの管理
proxy_cache + fastcgi_cache
キャッシュの 【HIT】率向上 コマンドとシェルスクリプト
proxy_cache + fastcgi_cache
キャッシュの 【HIT】率向上 コマンドとシェルスクリプト
リバースプロキシをフロントエンドに配置し、バックエンドのWebサーバーへリクエストを中継する構成では、各サーバーが保持するキャッシュを活用することで、Webサーバーの処理負荷を軽減し、且つ、ユーザーへの応答速度が向上できる。
但し、システム全体のパフォーマンスを最大化するためには、キャッシュのヒット率を高めることが重要となる。
但し、システム全体のパフォーマンスを最大化するためには、キャッシュのヒット率を高めることが重要となる。
proxy と fastcgi の「パターン別」ヒット率。(ヒット率を改善する前の状態)
以下、キャッシュの状態を調査/分析するための「コマンド と シェルスクリプト」を、使用する局面に合わせ、事例と共に記載した。
スポンサー リンク
目 次
1. 環境情報
ミドルウェアは Nginx + PHP で、バックエンドのWebサーバーでは「WordPress」が稼働している。
フロントエンドの リバースプロキシサーバーで proxy_cache を設定し、バックエンドのWebサーバーでは fastcgi_cache が使われる設定となっている。
SSDの状態を確認するコマンド。
# SSDの状態確認コマンド
sudo smartctl -a /dev/sda
sudo smartctl -a /dev/sda 2>/dev/null | grep -E "Device Model|Rotation Rate|SSD"
$ sudo smartctl -a /dev/sda 2>/dev/null | grep -E "Device Model|Rotation Rate|SSD"
Model Family: Samsung based SSDs
Device Model: Samsung SSD 860 EVO 250GB
Rotation Rate: Solid State Device✅ proxy_cache:SSDに作成
元は tmpfs にしていたが、容量不足が判明した為 SSD に変更。
# SSDにキャッシュディレクトリを作成
sudo mkdir -p /var/cache/nginx_disk/arakoki70
# オーナー設定
sudo chown -R www-data:www-data /var/cache/nginx_disk/
# nginx.conf の設定を変更(SSDなのでmax_sizeを大きく取れる)
proxy_cache_path /var/cache/nginx_disk/arakoki70 levels=1:2 keys_zone=arakoki70:10m max_size=10g inactive=30d use_temp_path=off;✅ fastcgi_cache:SSDに作成
# SSDにキャッシュディレクトリを作成
sudo mkdir -p /var/cache/nginx_disk/farakoki70
# オーナー設定
sudo chown -R www-data:www-data /var/cache/nginx_disk/
# nginx.conf のキャッシュパスを変更
fastcgi_cache_path /var/cache/nginx_disk/farakoki70 levels=1:2 keys_zone=farakoki70:10m max_size=10g inactive=30d use_temp_path=off;2. URLからキャッシュの状態を確認するコマンド
キャッシュが有効になっているかどうかは、URLから簡単に確認することが出来る。
以下、URLから確認するコマンドのサンプルを列挙。
# ヘッダー全体を見る
# 実行結果サンプル
$ curl -I https://arakoki70.com/
HTTP/2 200
server: nginx
date: Sat, 23 May 2026 11:53:22 GMT
content-type: text/html; charset=UTF-8
vary: Accept-Encoding
vary: Accept-Encoding
link: <https://arakoki70.com/index.php?rest_route=/>; rel="https://api.w.org/"
x-fastcgi-cache: HIT
x-proxy-cache: HIT
# キャッシュの状態を確認するコマンド
# 実行結果サンプル
$ curl -I https://arakoki70.com/ | grep -i "cache"
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
x-fastcgi-cache: HIT
x-proxy-cache: HIT
# 特定ページのキャッシュ状況を確認するコマンド
curl -I https://arakoki70.com/ | grep -i "cache"
curl -I https://arakoki70.com/ | grep x-proxy-cache
curl -I https://arakoki70.com/ | grep x-fastcgi-cache
# 実行結果サンプル
$ curl -I https://arakoki70.com/?p=12022
HTTP/2 200
server: nginx
date: Sat, 23 May 2026 11:59:18 GMT
content-type: text/html; charset=UTF-8
vary: Accept-Encoding
vary: Accept-Encoding
link: <https://arakoki70.com/index.php?rest_route=/>; rel="https://api.w.org/"
link: <https://arakoki70.com/index.php?rest_route=/wp/v2/posts/12022>; rel="alternate"; title="JSON"; type="application/json"
link: <https://arakoki70.com/?p=12022>; rel=shortlink
x-fastcgi-cache: HIT
x-proxy-cache: HIT
# 画像ファイルへのアクセスがキャッシュされているか確認
curl -I https://arakoki70.com/wp-content/uploads/2019/10/clicksuu_0012.jpg \
| grep -i cache
# 実行結果サンプル
$ curl -I https://arakoki70.com/wp-content/uploads/2019/10/clicksuu_0012.jpg | grep -i cache
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 36779 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
cache-control: max-age=2592000
cache-control: public, max-age=2592000, no-transform
x-proxy-cache: HIT3. キャッシュのファイル数とディスクの使用量を確認するスクリプト
どの程度キャッシュされているか、キャッシュのファイル件数とディスクの使用量を確認するスクリプト。
🔹 proxy_cache のファイル数とディスクの使用量を表示するスクリプト。
#!/bin/bash
# 変数に日時を代入
CURRENT_TIME=$(date "+%Y-%m-%d %H:%M:%S")
echo "${CURRENT_TIME}:proxy_cache のファイル数と使用量"
for site in arakan60 arakoki70 treksite; do
count=$(sudo find /var/cache/nginx_disk/$site -type f | wc -l)
size=$(sudo du -sh /var/cache/nginx_disk/$site | cut -f1)
echo "$site : ${count}ファイル / ${size}"
done
# スクリプトの登録
sudo nano proxy-usage.sh
# スクリプトに実行権限を付与
sudo chmod +x proxy-usage.sh
# スクリプトの実行
./proxy-usage.sh
# 実行結果サンプル
$ ./proxy-usage.sh
2026-05-23 21:08:08:proxy_cache のファイル数と使用量
arakan60 : 23483ファイル / 1.9G
arakoki70 : 30864ファイル / 1.7G
treksite : 1015ファイル / 38M4. キャッシュのヒット率を集計するためのアクセスログ
キャッシュのヒット率を調べるために、アクセスログにキャッシュステータスを出力する。
# nginx アクセスログフォーマット
log_format cache_log '$remote_addr "$request" $status '
'proxy=$upstream_cache_status '
'fastcgi=$sent_http_x_fastcgi_cache '
'$time_local';
# 最新アクセスログを3行表示コマンド
tail -n 3 /var/log/nginx/cache_access.log
# アクセスログの例
162.120.184.20 "GET /?p=10158 HTTP/2.0" 200 proxy=HIT fastcgi=HIT 23/May/2026:17:58:11 +0900アクセスログの項目は「フィールド」と呼ばれ、先頭から番号が付され「$n」で参照できる(awkコマンド)。
5. キャッシュヒット率を proxyとfastcgiの組合せで集計するスクリプト
キャッシュステータスが出力されたアクセスログを使用し、proxy と fastcgi の組合せパターンでキャッシュのヒット率を集計するスクリプト。集計する過去の「時間範囲」を指定可能(デフォルトは 1時間)。
#!/bin/bash
LOG=${1}
HOURS=${2:-1} # 第2引数で時間指定、デフォルト1時間
# 引数チェック
if [ -z "$LOG" ]; then
echo "使い方: bash cache-hitrate_2.sh /var/log/nginx/cache_access.log [時間数]"
echo "例: bash cache-hitrate_2.sh /var/log/nginx/cache_access.log 1 # 過去1時間"
echo "例: bash cache-hitrate_2.sh /var/log/nginx/cache_access.log 24 # 過去24時間"
echo "例: bash cache-hitrate_2.sh /var/log/nginx/cache_access.log 0 # 全件"
exit 1
fi
if [ ! -f "$LOG" ]; then
echo "エラー: ファイルが見つかりません: $LOG"
exit 1
fi
# 集計対象の開始時刻を算出
if [ "$HOURS" -eq 0 ]; then
SINCE=""
echo "集計範囲: 全件"
else
SINCE=$(LC_ALL=C date -d "${HOURS} hours ago" "+%d/%b/%Y:%H:%M:%S")
echo "集計範囲: 過去 ${HOURS} 時間 (${SINCE} JST 以降)"
fi
awk -v since="$SINCE" '
function parse_time(ts, months, a) {
# "17/May/2026:14:53:12" → "20260517145312" に変換して文字列比較
months["Jan"]="01"; months["Feb"]="02"; months["Mar"]="03"
months["Apr"]="04"; months["May"]="05"; months["Jun"]="06"
months["Jul"]="07"; months["Aug"]="08"; months["Sep"]="09"
months["Oct"]="10"; months["Nov"]="11"; months["Dec"]="12"
split(ts, a, "[/:]")
return a[3] months[a[2]] sprintf("%02d", a[1]) a[4] a[5] a[6]
}
{
# 時間フィルタリング
if (since != "") {
ts = ""
for (i=1; i<=NF; i++) {
# "17/May/2026:14:53:12" 形式を検出(+0900 の手前のフィールド)
if ($i ~ /^[0-9]{2}\/[A-Za-z]{3}\/[0-9]{4}:[0-9]{2}:[0-9]{2}:[0-9]{2}$/) {
ts = $i
break
}
}
if (ts == "") next
if (parse_time(ts) < parse_time(since)) next
}
proxy = "-"
fastcgi = "-"
for (i=1; i<=NF; i++) {
if ($i ~ /^proxy=/) proxy = substr($i, 7)
if ($i ~ /^fastcgi=/) fastcgi = substr($i, 9)
}
combo[proxy "|" fastcgi]++
total++
}
END {
if (total == 0) {
print "\n該当するログが見つかりませんでした。\n"
exit
}
printf "\n=== 総アクセス数: %d ===\n\n", total
printf "%-12s %-12s %8s %8s\n", "proxy_cache", "fastcgi_cache", "件数", "割合"
printf "%-12s %-12s %8s %8s\n", "------------", "-------------", "--------", "--------"
n = asorti(combo, sorted)
for (i=1; i<=n; i++) {
split(sorted[i], parts, "|")
printf "%-12s %-13s %8d %7.1f%%\n",
parts[1], parts[2], combo[sorted[i]], combo[sorted[i]]/total*100
}
printf "\n"
}
' "$LOG"
# スクリプトの登録
sudo nano cache-hitrate.sh
# スクリプトに実行権限を付与
sudo chmod +x cache-hitrate.sh
# スクリプトの実行(デフォルト過去1時間)
./cache-hitrate.sh /var/log/nginx/cache_access.log
# 過去3時間
./cache-hitrate.sh /var/log/nginx/cache_access.log 3
# アクセスログ全件を対象
./cache-hitrate.sh /var/log/nginx/cache_access.log 0
# 過去1時間での集計サンプル
$ ./cache-hitrate_3.sh /var/log/nginx/cache_access.log 1
集計範囲: 過去 1 時間 (24/May/2026:12:08:48 JST 以降)
=== 総アクセス数: 2088 ===
proxy_cache fastcgi_cache 件数 割合
------------ ------------- -------- --------
- - 280 13.4%
BYPASS - 9 0.4%
BYPASS BYPASS 1 0.0%
EXPIRED EXPIRED 1 0.0%
EXPIRED HIT 3 0.1%
HIT - 1474 70.6%
HIT BYPASS 1 0.0%
HIT EXPIRED 2 0.1%
HIT HIT 118 5.7%
HIT MISS 14 0.7%
MISS - 100 4.8%
MISS BYPASS 14 0.7%
MISS EXPIRED 4 0.2%
MISS HIT 21 1.0%
MISS MISS 45 2.2%
STALE MISS 1 0.0%✅ 活用ポイント。
| proxy | fastcgi | 件数 | 割合 | コメント |
| - | - | 923 | 8.8% | |
| BYPASS | - | 9 | 0.1% | ログイン中ユーザー等:正常なので問題なし |
| BYPASS | BYPASS | 2 | 0.0% | |
| HIT | - | 4,291 | 40.8% | 最も効率的な状態:このパターンが多いほど理想 |
| HIT | BYPASS | 4 | 0.0% | |
| HIT | EXPIRED | 9 | 0.1% | |
| HIT | HIT | 286 | 2.7% | |
| HIT | MISS | 11 | 0.1% | |
| MISS | - | 3,843 | 36.5% | |
| MISS | BYPASS | 36 | 0.3% | |
| MISS | EXPIRED | 26 | 0.2% | |
| MISS | HIT | 875 | 8.3% | proxy_cacheが機能していない |
| MISS | MISS | 208 | 2.0% | 両方ミス・PHP実行:サーバー負荷が高い・要注意 |
| 10,523 | 99.9% |
😊 HIT / - の割合が高い状態を維持できていれば、キャッシュが順調に機能している証拠となる。
6. 「ヒット率パターン」でアクセスログを抽出するスクリプト
🔎 上記の表から問題となるパターンを見つけて、該当のURLを抽出して対策を講じて行く。
➡️ - / - パターン:proxyもfastcgiもキャッシュ対象外になっているURLを確認。
awk '{
proxy="-"; fastcgi="-"
for(i=1;i<=NF;i++){
if($i~/^proxy=/) proxy=substr($i,7)
if($i~/^fastcgi=/) fastcgi=substr($i,9)
}
if(proxy=="-" && fastcgi=="-") print $3, $5
}' /var/log/nginx/cache_access.log | sort | uniq -c | sort -rn | head -20
# スクリプトの登録
sudo nano pat--url.sh
# スクリプトに実行権限を付与
sudo chmod +x pat--url.sh
# スクリプトの実行
./pat--url.sh
$ ./pat--url.sh # 実行結果サンプル
221 /wp-login.php 403
173 /trek/wp-admin/admin-ajax.php 403
110 / 301
59 /robots.txt 301
31 400 fastcgi=-
28 /wp-comments-post.php 302
24 / 200
22 /.well-known/traffic-advice 404
18 /xmlrpc.php 301
18 /wp-content/plugins/hellopress/wp_filemanager.php 301
18 /ads.txt 301
18 / 400
14 /wp-login.php 301
14 /wp-content/plugins/hellopress/wp_filemanager.php 404
13 /robots.txt 403
11 /wp-good.php 301
11 /administrator/ 301
10 /favicon.ico 301
10 /edit.php 404
9 /wp-json/wp/v2/posts 301➡️ MISS / - パターン:proxyがMISSでfastcgiがキャッシュ対象外になっているURLを確認。
awk '{
proxy="MISS"; fastcgi="-"
for(i=1;i<=NF;i++){
if($i~/^proxy=/) proxy=substr($i,7)
if($i~/^fastcgi=/) fastcgi=substr($i,9)
}
if(proxy=="MISS" && fastcgi=="-") print $3, $5
}' /var/log/nginx/cache_access.log | sort | uniq -c | sort -rn | head -20
sudo nano patmiss-url.sh
sudo chmod +x patmiss-url.sh
./patmiss-url.sh
$ ./patmiss-url.sh
12 /webfonts/fa-solid-900.woff2 404
12 /webfonts/fa-solid-900.woff 404
12 /webfonts/fa-solid-900.ttf 404
10 /apple-touch-icon.png 404
10 /apple-touch-icon-precomposed.png 404
7 /.env 403
6 /wp-content/cache/autoptimize/js/autoptimize_c2914f7cc11a5688a2f11c63f03ad776.js 200
4 /apple-touch-icon-120x120.png 404
4 /apple-touch-icon-120x120-precomposed.png 404
4 /.git/config 403
3 /wp-content/uploads/2025/07/pix_3993.png 200
3 /backend/.env 403
3 /api/.env 403
3 /.env.production 403
3 /.env.local 403
2 /xxl.php 404
2 /xmlrpc.php?rsd 403
2 /xmlrpc.php 403
2 /wpm.php 404
2 /wp-logout.php 404🔹 MISS/- のパターンでリクエストURLを抽出して集計するコマンド。
grep "proxy=MISS" /var/log/nginx/cache_access.log | grep "fastcgi=-" \
| awk '{print $3}' | sort | uniq -c | sort -rn | head -20🔹 MISS/- のパターンでリクエストURLを抽出して集計するコマンド。
grep "proxy=MISS" /var/log/nginx/cache_access.log | grep "fastcgi=-" \
| awk '{print $3}' | grep -oE '\.[a-zA-Z0-9]+$' | sort | uniq -c | sort -rn
# 実行結果サンプル
$ grep "proxy=MISS" /var/log/nginx/cache_access.log | grep "fastcgi=-" \
| awk '{print $3}' | grep -oE '\.[a-zA-Z0-9]+$' | sort | uniq -c | sort -rn
972 .jpg
876 .png
379 .webp
294 .php
185 .env
39 .js
38 .css
12 .woff2
12 .woff
12 .ttf
5 .txt
3 .production7. キャッシュの【HIT】率向上対策-事例
💎 MISS/- のパターンでアクセスしてきたIPアドレスを抽出して集計するコマンドを実行したところ・・・。
$ grep "proxy=MISS" /var/log/nginx/cache_access.log | grep "fastcgi=-" \
| awk '{print $1}' | sort | uniq -c | sort -rn | head -20
# 実行結果
IPアドレス 正体
66.249.73.xx 66.249.74.xx Googlebot
216.244.66.250 DotBot(SEOクローラー)
51.15.xx 51.158.xx 51.159.xx Scaleway系クローラー
126.xx.xx.xx 153.xx.xx.xx 118.xx.xx.xx 日本国内の一般ユーザー🧰 クローラーが大量にアクセスしているのが明確だったので、問題のクローラーをブロックする。
if ($http_user_agent ~* "DotBot|MJ12bot|AhrefsBot|SemrushBot") {
return 403;
}💎 tmpfs(RAM)にキャッシュを配置→ SSDに移行。
→ キャッシュの容量拡大でHIT率が大幅に向上。
→ キャッシュの容量拡大でHIT率が大幅に向上。
💎 キャッシュ対象外URLの調査から .txt をキャッシュ対象に追加。
# 既存の静的ファイルブロックの拡張子に txt を追加
location ~* \.(jpg|jpeg|png|gif|webp|css|js|ico|svg|woff|woff2|ttf|txt)$ {💎 大量の404リクエストがバックエンドに到達している。
# 404をキャッシュ
proxy_cache_valid 404 1h; 💎 fastcgi_cache_valid のリダイレクト期間短縮。
fastcgi_cache_valid のリダイレクト期間短縮
fastcgi_cache_valid 200 7d;
fastcgi_cache_valid 301 302 1h; # 7d → 1h
fastcgi_cache_valid 404 10m;🔴 末尾に wp-login.php が付いたアクセスをブロック。
# ----------------------------------
# 危険Query遮断 y2026.05.21
# ----------------------------------
if ($query_string ~* "wp-login\.php") {
return 444;その他細かい設定の修正を行い、キャッシュのヒット率を大幅に改善❗❗。
以上。
(2026.05.24)
(2026.05.24)
スポンサー リンク





