減少 Nginx、WordPress 和 MySQL 在 Windows 環境下的等待伺服器回應時間(TTFB),最核心的手段是升級 PHP 執行緒處理機制、啟用 Nginx 頁面快取,並增加 MySQL 記憶體快取。以下是具體且針對 Windows 系統的優化步驟:
設定 Nginx 與 PHP 之間使用本地 IP
Windows 的網路機制(TCP/IP)在解析 localhost 時有時候會卡頓 1~2 秒。
- 檢查 Nginx 設定:打開
nginx.conf,找到fastcgi_pass的地方。 - 修改寫法:將
fastcgi_pass localhost:9000;改為fastcgi_pass 127.0.0.1:9000;。直接使用 IP 可以跳過 Windows 的主機名稱解析,現賺 0.5 秒回應時間。
啟用 Nginx FastCGI 頁面快取 (FastCGI Cache)
Windows 無法運行原生的 Linux PHP-FPM,多數情況下使用 php-cgi.exe 處理效能較弱,最有效降低回應時間的方式是讓 Nginx 直接把 PHP 算好的網頁存成靜態 HTML。
- 設定方法:在
nginx.conf的http區塊加入快取路徑(例如:fastcgi_cache_path c:/nginx/cache levels=1:2 keys_zone=WORDPRESS:100m inactive=60m;)。 - 套用快取:在
location ~ \.php$區塊中掛載此快取設定,以避免每次載入頁面都重新執行複雜的 PHP 與資料庫查詢。
在 Nginx 中,設定 FastCGI 快取(FastCGI Cache)必須分為兩個部分:
- 全域區塊 (
http):使用fastcgi_cache_path定義快取的儲存路徑與記憶體大小。 - 伺服器區塊 (
location ~ \.php$):使用fastcgi_cache啟用並套用剛剛定義的快取規則。
完整的 nginx.conf 檔如下
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
gzip on;
# Sets the maximum allowed size of the client request body.
client_max_body_size 13M;
# 程式可執行的最長時間 (秒)
fastcgi_read_timeout 60s;
fastcgi_connect_timeout 60s;
# ==========================================
# 設定 FastCGI Cache 快取 (全域設定)
# ==========================================
# 定義快取:路徑設在 W 碟,快取名稱為 WORDPRESS,記憶體給 100M,7天沒人訪問就自動刪除
# ※請確保 Windows 中已手動建立 W:/nginx/nginx-cache 資料夾
fastcgi_cache_path W:/nginx/nginx-cache levels=1:2 keys_zone=WORDPRESS:100m inactive=7d max_size=1g;
# 定義快取的唯一識別 key 格式
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout invalid_header http_500 http_503;
# ==========================================
# WordPress 專用:定義哪些狀況要「跳過快取」
# ==========================================
map $request_method $skip_cache {
POST 1;
default 0;
}
map $query_string $skip_cache_query {
"" 0;
default 1;
}
# 結合多種條件判斷是否跳過快取
# (後台、登入 Cookie、評論者、購物車等不快取)
# 這裡在下方 server 區塊內會用 if 補強,確保後台安全
# 1. 預設的 Localhost 伺服器
server {
listen 80;
listen [::]:80;
server_name localhost;
charset utf-8;
root html;
access_log logs/localhost.access.log;
error_log logs/localhost.error.log;
location / {
index index.php index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
location ~ \.php$ {
include fastcgi.conf;
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_read_timeout 60s;
fastcgi_connect_timeout 60s;
}
}
# 2. HTTP server: http://your_domain_name (純轉址)
server {
listen 80;
server_name your_domain_name;
root html/your_domain_name;
# 修正:純轉址即可,不需要在這裡放 fastcgi_cache 參數,否則會報錯
return 301 https://$host$request_uri;
}
# 3. HTTPS server: https://your_domain_name (WordPress 主體)
server {
listen 443 ssl;
charset utf-8;
root html/your_domain_name;
access_log logs/your_domain_name.access.log;
error_log logs/your_domain_name.error.log;
index index.php index.html index.htm;
server_name your_domain_name;
# Windows 環境下,建議憑證路徑使用正斜線 /,避免 \ 被誤判為跳脫字元
ssl_certificate cert/://your_domain_name;
ssl_certificate_key cert/://your_domain_name;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# ------------------------------------------
# WordPress 快取排除邏輯 (必加,否則無法登入後台)
# ------------------------------------------
set $custom_skip_cache 0;
# POST 請求與帶有參數的網址不快取
if ($request_method = POST) { set $custom_skip_cache 1; }
if ($query_string != "") { set $custom_skip_cache 1; }
# 後台與特定頁面不快取
if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
set $custom_skip_cache 1;
}
# 排除 WordPress 的 REST API,避免編輯器存檔時 JSON 出錯
if ($request_uri ~* "/wp-json/") {
set $custom_skip_cache 1;
}
# 已登入的使用者或留言者不快取
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
set $custom_skip_cache 1;
}
location / {
try_files $uri $uri/ /index.php?$args;
}
location = /favicon.ico {
log_not_found off;
access_log off;
}
# 靜態檔案快取(直接由 Nginx 處理,極速)
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# 處理 WordPress PHP 並啟用 FastCGI 快取
location ~ \.php$ {
include fastcgi.conf;
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# 啟用快取
fastcgi_cache WORDPRESS;
# 套用上面設定的排除邏輯
fastcgi_cache_bypass $custom_skip_cache;
fastcgi_no_cache $custom_skip_cache;
# 快取時間設定
fastcgi_cache_valid 200 301 302 1d;
fastcgi_cache_valid 404 1m;
# 【核心關鍵:修正 MISS 的必加指令】
# 告訴 Nginx 忽略 WordPress 或 WP-Optimize 塞進來的「不可快取」標頭
# 這能強制將未登入訪客的 HTML 存進 W:/nginx/nginx-cache
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
# 在瀏覽器標頭加入快取狀態,方便 F12 檢驗
add_header X-FastCGI-Cache $upstream_cache_status;
fastcgi_read_timeout 60s;
fastcgi_connect_timeout 60s;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
}核心參數重點解析(Windows 專屬注意)
- W:/nginx/nginx-cache:這是快取檔案在 Windows 硬碟中的實體資料夾。請務必手動先去 W 碟建立好
nginx和cache這兩個資料夾,Nginx 不會自動建立多層目錄,如果找不到路徑會啟動失敗。 keys_zone=WORDPRESS:100m:這是幫這個快取取名字。100m代表在記憶體(RAM)中開闢 100MB 的空間來存放「快取索引/金鑰」,100MB 足夠存放幾十萬個網頁的索引。levels=1:2:建立兩層目錄結構來存放快取檔案,防止 Windows 單一資料夾內檔案太多導致檔案系統讀取變慢。
WordPress 必加的「跳過快取」設定(選用,但強烈建議)
如果您直接啟用快取,會導致一個嚴重問題:當您登入 WordPress 後台修改文章時,看到的還是舊的快取畫面;或者購物車、評論功能會出錯。
為了避免這種狀況,建議在 server 區塊內、location ~ \.php$ 之前,加入以下排除登入者與後台快取的邏輯:
//nginx.conf
# 預設不跳過快取
set $skip_cache 0;
# POST 請求(送出表單、留言)不快取
if ($request_method = POST) {
set $skip_cache 1;
}
# 帶有參數的網址(搜尋、分頁等)不快取
if ($query_string != "") {
set $skip_cache 1;
}
# 後台網址、特定頁面不快取
if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
set $skip_cache 1;
}
# 已經登入的會員、有留言過的人、有購物車的人不快取
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
set $skip_cache 1;
}
# 然後在 location ~ \.php$ 區塊內,加入這兩行:
location ~ \.php$ {
# ...(原有的 FastCGI 設定)...
# 【核心關鍵:修正 MISS 的必加指令】
# 告訴 Nginx 忽略 WordPress 或 WP-Optimize 塞進來的「不可快取」標頭
# 這能強制將未登入訪客的 HTML 存進 W:/nginx/nginx-cache
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
# 套用上面設定的排除邏輯(已登入、POST 等不快取)
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
}
套用此設定檔並重啟 Nginx 後,請嘗試用無痕視窗(未登入狀態)連續重新整理首頁兩次:
- 第一次應該會顯示
X-FastCGI-Cache: MISS,第二次之後應該要顯示X-FastCGI-Cache: HIT。 - 若有登入時, 顯示
X-FastCGI-Cache:BYPASS - 按下 F12 開啟開發者工具,切換到 Network (網路) 標籤頁。
- 點擊第一個網頁請求(
polinwei.com),查看 Response Headers。
原理分析
- WP-Optimize 的過度保護:許多優化外掛為了避免未登入的訪客「不小心看到別人的頁面」,會預設對網頁輸出
Cache-Control: private, must-revalidate標頭。 - Nginx 讀懂了它:Nginx 一旦看到後端 PHP 送來這個標頭,就會判定「這是不安全、不應該被快取的頁面」,因此不管您點幾次,Nginx 都會老老實實地去問 PHP(顯示
MISS)。 - 解決之道:加入
fastcgi_ignore_headers之後,Nginx 會把這些保護標頭「裝作沒看到」,並依照我們設定的fastcgi_cache_valid 200 1d強制將頁面寫入快取。因為我們前面有設定$custom_skip_cache,所以已登入的管理者一樣很安全,不用擔心後台被快取到。
解決 Windows 獨有的 PHP-CGI 堵塞問題
在 Windows 上,Nginx 通常透過 php-cgi.exe 處理網頁。預設情況下,php-cgi.exe 一次只能處理一個請求,若同時有兩個人點擊網站,第二個人就必須「等待伺服器回應」。
- 設定環境變數:在啟動 PHP 的批次檔(.bat)或系統環境變數中,加入
SET PHP_FCGI_CHILDREN=32(這會讓 PHP 允許最多 32 個平行緒)。 - 防止自動崩潰:加入
SET PHP_FCGI_MAX_REQUESTS=2000(避免 PHP 記憶體洩漏崩潰,達到 2000 次請求後會自動重啟)。
優化 PHP-CGI 與連線數(php.ini)
因為 PHP 運行於 Windows 環境,需確保不會因為處理程序耗盡而讓瀏覽器排隊等待。
- 開啟持久連線:修改
php.ini,設定mysqli.allow_persistent = On和mysqli.max_persistent = -1,並允許cgi.force_redirect = 1。 - 排程多程序:如果網站併發請求高,可利用 Nginx 的
upstream功能,同時指向多個php-cgi.exe進行負載平衡來減少等待時間。
調整 MySQL 快取與記憶體設定 (my.ini)
MySQL 在 Windows 預設的記憶體分配極少,這會導致硬碟 I/O 頻繁,大幅增加讀取資料庫的時間。
- InnoDB Buffer Pool:在
my.ini的[mysqld]區塊,將innodb_buffer_pool_size設置為您系統可用記憶體的 50% 左右(例如 8G 記憶體則設4G),讓資料表與索引常駐 RAM。 - 關閉查詢快取:較新版本的 MySQL 建議確保
query_cache_type = 0,以防多核心環境下因 Query Cache 產生的鎖定反而拖慢速度。
修改 MySQL my.ini 設定(直接吃滿記憶體)
Windows 預設的 MySQL 配置完全沒有發揮 16G 記憶體的優勢。請找到您的 my.ini 檔案,在 [mysqld] 區段下,將以下參數直接覆蓋或新增(建議先備份原檔案):
[mysqld]
# 16G 記憶體,撥出 6G 專門給 MySQL 快取資料與索引
innodb_buffer_pool_size = 6G
# 增加日誌緩衝區,減少硬碟寫入頻率
innodb_log_buffer_size = 64M
innodb_log_file_size = 1G
innodb_flush_log_at_trx_commit = 2
# 調整每條連線使用的暫存記憶體(適度加大,避免寫入硬碟)
tmp_table_size = 64M
max_heap_table_size = 64M
read_buffer_size = 2M
read_rnd_buffer_size = 4M
sort_buffer_size = 4M
# 關閉效能低落的舊版查詢快取(MySQL 8.0 以下適用,8.0 以上可忽略此兩行)
query_cache_type = 0
query_cache_size = 0修改後請務必重啟 MySQL 服務。
清理與優化 WordPress 自身資料庫
隨著網站運行時間拉長,過多的暫存資料會延長資料庫回應時間。
- 清理無用資料:定期刪除舊文章修訂版、暫存資料(Transient)以及未使用的 Autoload 資料。
- 最佳化資料表:進入 phpMyAdmin,全選 WordPress 資料表並執行「最佳化資料表 (Optimize Table)」動作。
外掛檢測與診斷
- 安裝效能分析外掛:在 WordPress 網站安裝並啟用 Query Monitor,可以快速抓出是哪一個外掛、佈景主題或資料庫查詢導致伺服器回應遲緩。
優化 WP-Optimize 設定
WP-Optimize 是一個很好的整合型工具,請確保您開啟了以下關鍵核心功能:
- 頁面快取 (Page Caching):進入
WP-Optimize > Cache,勾選 Enable page caching。這可以讓大部分訪客直接讀取快取檔案,不需要經過 MySQL 和 PHP 運算。 - 資料庫自動清理:進入
WP-Optimize > Database,勾選「清除所有文章修訂版本」與「清除所有過期暫存資料 (Transients)」,並設定每週自動清理。
新文章發佈後, 未登入的用戶看不見新文章
這正是啟用 Nginx FastCGI 快取後最常遇到的「快取過期/未同步」問題。因為 Nginx 已經把舊的首頁與文章列表存成靜態 HTML(儲存在您的 W 碟),所以當您發布新文章時,未登入的訪客讀取的依然是 Nginx 舊的快取檔案,必須等到 1 天(1d)快取過期後才會看到新文章。
要徹底解決這個問題,有兩種最主流且推薦的解法:
解法一:安裝 WordPress 外掛,自動通知 Nginx 清理快取(最推薦、一勞永逸)
只要在 WordPress 安裝專門的快取清理外掛,每當您發布文章、修改文章、有新評論時,外掛就會自動刪除 Nginx 對應的快取檔案,未登入用戶就能瞬間看到更新。
- 安裝外掛:在 WordPress 後台搜尋並安裝 Nginx Helper。
- 啟用與設定:
- 進入外掛設定頁面,勾選 Enable Purge。
- Purge Method (清理方式):請選擇 Using a Filesystem method(檔案系統直接刪除法)。
- Cache Path (快取路徑):請填入您在
nginx.conf設定的實體路徑:W:/nginx/nginx-cache。 - 下方的清理條件(Purge Conditions),建議勾選:發布新文章(Create)、修改文章(Update)、有新評論(Comment)。
- 成果:未來只要您一按「發布」,WordPress 就會直接去
W:碟把受影響的快取檔案刪除,未登入訪客再次重新整理,Nginx 就會觸發MISS並重新抓取新文章變成全新的HIT。
解法二:如果您不想加外掛,縮短 Nginx 的快取有效時間
如果您不希望網站安裝太多外掛,可以透過修改 nginx.conf,將高頻率變動的頁面快取時間縮短(例如改為 10 分鐘或 1 小時),讓誤差縮小到使用者可接受的範圍。
請在 location ~ \.php$ 區塊中,修改原本的 fastcgi_cache_valid:
location ~ \.php$ {
# ... 其他設定保持不變 ...
# 將原本的 1d (一天) 改為 10m (10分鐘) 或 1h (1小時)
# 這樣就算不裝外掛,未登入用戶最慢 10 分鐘內一定能看到新文章
fastcgi_cache_valid 200 301 302 10m;
fastcgi_cache_valid 404 1m;
# ... 其他設定保持不變 ...
}修改後記得重啟 Nginx 服務。
在還沒設定好上述自動化機制前,若急著讓訪客看到新文章,可以直接進入 Windows 的檔案總管,手動將 W:/nginx/nginx-cache/ 資料夾裡面的所有子資料夾與檔案全部刪除。這相當於手動清空 Nginx 全站快取,訪客重新整理就會立刻看到新文章。
建議可以先嘗試安裝 Nginx Helper,因為這是最不犧牲網站速度(依然維持高時效快取)又能解決同步問題的標準做法。
Nginx Helper 的最佳設定指南(Windows 專用)
安裝 Nginx Helper 後,請進入設定畫面並勾選以下核心選項:
- Enable Purge:勾選啟用。
- Purge Method:務必選擇
Using a Filesystem method(不要選 nginx fastcgi_cache_purge,因為 Windows Nginx 不支援)。 - Cache Path:輸入您在
nginx.conf寫的絕對路徑:W:/nginx/nginx-cache。 - Purge Conditions (自動清理條件):
- 勾選
Modify post(修改文章) - 勾選
Create comment(有新留言時,讓未登入訪客看得見新留言) - 勾選
Delete post(刪除文章)
- 勾選
這樣一來,您一發布文章,外掛就會自動去 W 碟精準刪除首頁與該文章的快取,未登入的用戶就能在一秒內看到最新的文章,且完全不影響其他沒變動網頁的「超低回應時間(HIT)」。
您可以直接在 WordPress 後台搜尋並安裝 Nginx Helper。
如果在啟用 Filesystem 模式時,外掛畫面上方出現紅色的「路徑無法寫入」或「找不到資料夾」的錯誤警告,這通常與 Windows 的斜線方向(/ 或 \)或系統權限有關。
Nginx Helper 檢查 RT_WP_NGINX_HELPER_CACHE_PATH 常數定義路徑中相符的快取檔案
這段文字是 Nginx Helper 外掛在設定畫面中,對於 Using a Filesystem method (檔案系統直接刪除法) 的官方繁體中文說明。它完美證實了這就是最適合您目前架構的方案。
既然您看到了這段說明,代表您已經進入了 Nginx Helper 的設定後台。請按照以下步驟完成最終對接,即可完美解決「未登入用戶看不到新文章」的問題:
修改 WordPress 的 wp-config.php
如說明所述,外掛需要讀取一個叫做 RT_WP_NGINX_HELPER_CACHE_PATH 的常數。請打開您 WordPress 根目錄底下的 wp-config.php 檔案,在 /* That's all, stop editing! Happy publishing. */ 這行字之前,加入以下這行程式碼:
/* Add any custom values between this line and the "stop editing" line. */
// 定義 Nginx Helper 尋找快取檔案的 Windows 實體路徑
define( 'RT_WP_NGINX_HELPER_CACHE_PATH', 'W:/nginx/nginx-cache' );
/* That's all, stop editing! Happy publishing. */註:請確保路徑與您 nginx.conf 中的 fastcgi_cache_path 完全一致(建議使用正斜線 /)。
回到 WordPress 後台勾選設定
完成上述常數定義後,回到 Nginx Helper 設定頁面:
- Purge Method:勾選您剛剛讀到說明的那個選項(Using a Filesystem method)。
- Purge Conditions(清理條件):勾選
When a post is published(發布文章時)、When a post is edited(修改文章時)。 - 點擊 Save All Changes(儲存所有變更)。

設定能完美對接您的 Nginx
這段說明提到了兩個非常關鍵的條件,而您目前的 nginx.conf 已經全部完美命中:
- 條件一:
levels=1:2
檢查nginx.conf:fastcgi_cache_path W:/nginx/nginx-cache levels=1:2 ...(符合 ✅) - 條件二:
fastcgi_cache_key "$scheme$request_method$host$request_uri"
檢查nginx.conf:fastcgi_cache_key "$scheme$request_method$host$request_uri";(符合 ✅)
因為 Nginx 快取金鑰規格與外掛預設演算法完全相同,Nginx Helper 只要拿到 W:/nginx/nginx-cache 的路徑,它就能在您按下「發布文章」的瞬間,精準算出該文章在 W 碟裡的 MD5 快取檔名並直接將其刪除。




