在建站和 web 應用程式交付方面,WordPress 是全球最大的一個平臺。全球大約四分之一 的站點現在正在使用開源 WordPress 軟體,包括 eBay 、 Mozilla 、 RackSpace 、 TechCrunch 、 CNN 、 MTV 、紐約時報、華爾街日報 等等。
最流行的個人部落格平臺 WordPress.com,其也執行在 WordPress 開源軟體上。而 NGINX 則為 WordPress.com 提供了動力。在 WordPress.com 的使用者當中,許多站點起步於 WordPress.com,然後換成了自己執行 WordPress 開源軟體;它們中越來越多的站點也使用了 NGINX 軟體。
WordPress 的吸引力源於其簡單性,無論是對於終端使用者還是安裝架設。然而,當使用量不斷增長時,WordPress 站點的體系結構也存在一定的問題 - 這裡有幾個方法,包括使用快取,以及將 WordPress 和 NGINX 組合起來,可以解決這些問題。
在這篇部落格中,我們提供了九個提速技巧來幫助你解決 WordPress 中一些常見的效能問題:
- 快取靜態資源
- 快取動態檔案
- 遷移到 NGINX
- 新增 NGINX 靜態連結支援
- 為 NGINX 配置 FastCGI
- 為 NGINX 配置 W3TotalCache
- 為 NGINX 配置 WP-Super-Cache
- 為 NGINX 配置安全防範措施
- 配置 NGINX 支援 WordPress 多站點

深入淺出講述提升 WordPress 效能的九大秘笈
在 LAMP 架構下 WordPress 的效能
大多數 WordPress 站點都執行在傳統的 LAMP 架構下:Linux 作業系統,Apache Web 伺服器軟體,MySQL 資料庫軟體 (通常是一個單獨的資料庫伺服器) 和 PHP 程式語言。這些都是非常著名的,廣泛應用的開源工具。在 WordPress 世界裡,很多人都用的是 LAMP,所以很容易尋求幫助和支援。
當使用者訪問 WordPress 站點時,瀏覽器為每個使用者建立六到八個連線來連線到 Linux/Apache 上。當使用者請求連線時,PHP 即時生成每個頁面,從 MySQL 資料庫獲取資源來響應請求。
LAMP 或許對於數百個併發使用者依然能照常工作。然而,流量突然增加是常見的,並且通常這應該算是一件好事。
但是,當 LAMP 站點變得繁忙時,當同時線上的使用者達到數千個時,它的瓶頸就會被暴露出來。瓶頸存在主要是兩個原因:
- Apache Web 伺服器 - Apache 的每個/每次連線需要消耗大量資源。如果 Apache 接受了太多的併發連線,記憶體可能會耗盡,從而導致效能急劇降低,因為資料必須交換到磁碟了。如果以限制連線數來提高響應時間,新的連線必須等待,這也導致了使用者體驗變得很差。
- PHP/MySQL 的互動 - 一個執行 PHP 和 MySQL 資料庫伺服器的應用伺服器上每秒的請求量有一個最大限制。當請求的數量超過這個最大限制時,使用者必須等待。超過這個最大限制時也會增加所有使用者的響應時間。超過其兩倍以上時會出現明顯的效能問題。
LAMP 架構的網站出現效能瓶頸是常見的情況,這時就需要升級硬體了 - 增加 CPU,擴大磁碟空間等等。當 Apache 和 PHP/MySQL 的架構超載後,在硬體上不斷的提升卻跟不上系統資源指數增長的需求。
首選替代 LAMP 架構的是 LEMP 架構 – Linux, NGINX, MySQL, 和 PHP 。 (這是 LEMP 的縮寫,E 代表著 「engine-x.」 的發音。) 我們在 技巧 3 中會描述 LEMP 架構。
技巧 1. 快取靜態資源
靜態資源是指不變的檔案,像 CSS,JavaScript 和圖片。這些檔案往往在網頁的資料中佔半數以上。頁面的其餘部分是動態生成的,像在論壇中評論,效能儀表盤,或個性化的內容 (可以看看 Amazon.com 產品) 。
快取靜態資源有兩大好處:
- 更快的交付給使用者 - 使用者可以從它們瀏覽器的快取或者從網際網路上離它們最近的快取伺服器獲取靜態檔案。有時候檔案較大,因此減少等待時間對它們來說幫助很大。
- 減少應用伺服器的負載 - 從快取中檢索到的每個檔案會讓 web 伺服器少處理一個請求。你的快取越多,使用者等待的時間越短。
要讓瀏覽器快取檔案,需要在靜態檔案中設定正確的 HTTP 首部。看看 HTTP Cache-Control 首部,特別是設定了 max-age 引數,Expires 首部,以及 Entity 標記。這裡 有詳細的介紹。
當啟用本地快取,然後使用者請求以前訪問過的檔案時,瀏覽器首先檢查該檔案是否在快取中。如果在,它會詢問 Web 伺服器該檔案是否改變過。如果該檔案沒有改變,Web 伺服器將立即響應一個 304 狀態碼 (未改變),這意味著該檔案沒有改變,而不是返回狀態碼 200 OK 並檢索和傳送已改變的檔案。
要在瀏覽器之外支援快取,可以考慮下面講到的技巧,以及考慮使用內容分發網路 (CDN) 。 CDN 是一種流行且強大的快取工具,但我們在這裡不詳細描述它。在你實現了這裡講到的其它技術之後可以考慮 CDN 。此外,當你的站點從 HTTP/1.x 過渡到 HTTP/2 協議時,CDN 的用處可能不太大;根據需要調查和測試,找到你網站需要的正確方法。
如果你轉向 NGINX Plus 或將開源的 NGINX 軟體作為架構的一部分,建議你考慮 技巧 3,然後配置 NGINX 快取靜態資源。使用下面的配置,用你 Web 伺服器的 URL 替換 www.example.com 。
server {### 將 www.example.com 替換為你的 URLserver_name www.example.com;root /var/www/example.com/htdocs;index index.php;access_log /var/log/nginx/example.com.access.log;error_log /var/log/nginx/example.com.error.log;location / {try_files $uri $uri/ /index.php?$args;}location ~ \.php$ {try_files $uri =404;include fastcgi_params;### 使用你 WordPress 伺服器的套接字,地址和埠來替換fastcgi_pass unix:/var/run/php5-fpm.sock;#fastcgi_pass 127.0.0.1:9000;}location ~* .(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {expires max;log_not_found off;access_log off;}}
技巧 2. 快取動態檔案
WordPress 動態地生成網頁,這意味著每次請求時它都要生成一個給定的網頁 (即使和前一次的結果相同) 。這意味著使用者隨時獲得的是最新內容。
想一下,當使用者訪問一個帖子時,並在文章底部有使用者的評論時。你希望使用者能夠看到所有的評論 - 即使評論剛剛釋出。動態內容就是處理這種情況的。
但現在,當帖子每秒出現十幾二十幾個請求時。應用伺服器可能每秒需要頻繁生成頁面導致其壓力過大,造成延誤。為了給使用者提供最新的內容,每個訪問理論上都是新的請求,因此它們不得不在原始出處等待很長時間。
為了防止頁面由於不斷提升的負載而變得緩慢,需要快取動態檔案。這需要減少檔案的動態內容來提高整個系統的響應速度。
要在 WordPress 中啟用快取中,需要使用一些流行的外掛 - 如下所述。 WordPress 的快取外掛會請求最新的頁面,然後將其快取短暫時間 - 也許只有幾秒鐘。因此,如果該網站每秒中會有幾個請求,那大多數使用者獲得的頁面都是快取的副本。這也有助於提高所有使用者的檢索時間:
- 大多數使用者獲得頁面的快取副本。應用伺服器沒有做任何工作。
- 使用者會得到一個之前的嶄新副本。應用伺服器只需每隔一段時間生成一個嶄新頁面。當伺服器產生一個嶄新頁面 (對於快取過期後的第一個使用者訪問),它這樣做要快得多,因為它的請求並沒有超載。
你可以快取執行在 LAMP 架構或者 LEMP 架構 上 WordPress 的動態檔案 (在 技巧 3 中說明瞭) 。有幾個快取外掛,你可以在 WordPress 中使用。運用到了最流行的快取外掛和快取技術,從最簡單到最強大的:
- Hyper-Cache 和 Quick-Cache – 這兩個外掛為每個 WordPress 頁面建立單個 PHP 檔案。它支援繞過多個 WordPress 與資料庫的連線核心處理的一些動態功能,建立一個更快的使用者體驗。它們不會繞過所有的 PHP 處理,所以並不會如下面那些取得同樣的效能提升。它們也不需要修改 NGINX 的配置。
- WP Super Cache – 最流行的 WordPress 快取外掛。在它易用的介面易用上提供了許多功能,如下所示。我們在 技巧 7 中展示了一個簡單的 NGINX 配置例項。
- W3 Total Cache – 這是第二流行的 WordPress 快取外掛。它比 WP Super Cache 的功能更強大,但它有些配置選項比較複雜。樣例 NGINX 配置,請看 技巧 6 。
- FastCGI – CGI 的意思是通用閘道器介面 ,在因特網上傳送請求和接收檔案的一種通用方式。它不是一個外掛,而是一種與快取互動快取的方法。 FastCGI 可以被用在 Apache 和 Nginx 上,它也是最流行的動態快取方法;我們在 技巧 5 中描述瞭如何配置 NGINX 來使用它。
這些外掛和技術的檔案解釋瞭如何在典型的 LAMP 架構中配置它們。配置方式包括資料庫和物件快取;最小化 HTML 、 CSS 和 JavaScript;整合流行的 CDN 整合環境。對於 NGINX 的配置,請看列表中的提示技巧。
注意:快取不會用於已經登入的 WordPress 使用者,因為他們的 WordPress 頁面都是不同的。 (對於大多數網站來說,只有一小部分使用者可能會登入) 此外,大多數快取不會對剛剛評論過的使用者顯示快取頁面,因為當使用者重新整理頁面時希望看到他們的評論。若要快取頁面的非個性化內容,如果它對整體效能來說很重要,可以使用一種稱為 碎片快取 (fragment caching) 的技術。
技巧 3. 使用 NGINX
如上所述,當併發使用者數超過某一數量時 Apache 會導致效能問題 – 可能是數百個使用者同時使用。 Apache 對於每一個連線會消耗大量的資源,因而容易耗盡記憶體。 Apache 可以配置連線數的值來避免耗盡記憶體,但是這意味著,超過限制時,新的連線請求必須等待。
此外,Apache 為每個連線載入一個 mod_php 模組副本到記憶體中,即使只有服務於靜態檔案 (圖片,CSS,JavaScript 等) 。這使得每個連線消耗更多的資源,從而限制了伺服器的效能。
要解決這些問題,從 LAMP 架構遷到 LEMP 架構 – 使用 NGINX 取代 Apache 。 NGINX 在一定的記憶體之下就能處理成千上萬的併發連線數,所以你不必經歷顛簸,也不必限制併發連線數到很小的數量。
NGINX 處理靜態檔案的效能也較好,它有內建的,容易調整的 快取 控制策略。減少應用伺服器的負載,你的網站的訪問速度會更快,使用者體驗更好。
你可以在部署環境的所有 Web 伺服器上使用 NGINX,或者你可以把一個 NGINX 伺服器作為 Apache 的 「前端」 來進行反向代理 - NGINX 伺服器接收客戶端請求,將請求的靜態檔案直接返回,將 PHP 請求轉發到 Apache 上進行處理。
對於動態頁面的生成,這是 WordPress 核心體驗,可以選擇一個快取工具,如 技巧 2 中描述的。在下面的技巧中,你可以看到 FastCGI,W3_Total_Cache 和 WP-Super-Cache 在 NGINX 上的配置示例。 (Hyper-Cache 和 Quick-Cache 不需要改變 NGINX 的配置。)
技巧 快取通常會被儲存到磁碟上,但你可以用 tmpfs 將快取放在記憶體中來提高效能。
為 WordPress 配置 NGINX 很容易。僅需四步,其詳細的描述在指定的技巧中:
- 新增永久連結的支援 - 讓 NGINX 支援永久連結。此步消除了對 .htaccess 配置檔案的依賴,這是 Apache 特有的。參見 技巧 4 。
- 配置快取 - 選擇一個快取工具並安裝好它。可選擇的有 FastCGI cache,W3 Total Cache, WP Super Cache, Hyper Cache, 和 Quick Cache 。請看技巧 5 、 6 和 7 。
- 落實安全防範措施 - 在 NGINX 上採用對 WordPress 最佳安全的做法。參見 技巧 8 。
- 配置 WordPress 多站點 - 如果你使用 WordPress 多站點,在 NGINX 下配置子目錄,子域,或多域名架構。見 技巧 9 。
技巧 4. 讓 NGINX 支援永久連結
許多 WordPress 網站依賴於 .htaccess 檔案,此檔案為 WordPress 的多個功能所需要,包括永久連結支援、外掛和檔案快取。 NGINX 不支援 .htaccess 檔案。幸運的是,你可以使用 NGINX 的簡單而全面的配置檔案來實現大部分相同的功能。
你可以在你的主 server 塊下新增下面的 location 塊中為使用 NGINX 的 WordPress 啟用 永久連結。 (此 location 塊在其它程式碼示例中也會被包括) 。
try_files 指令告訴 NGINX 檢查請求的 URL 在檔案根目錄 (/var/www/example.com/htdocs) 下是作為檔案 ($uri) 還是目錄 ($uri/) 存在的。如果都不是,NGINX 將重定向到 /index.php,並傳遞查詢字串引數作為引數。
server {server_name example.com www.example.com;root /var/www/example.com/htdocs;index index.php;access_log /var/log/nginx/example.com.access.log;error_log /var/log/nginx/example.com.error.log;location / {try_files $uri $uri/ /index.php?$args;}}
技巧 5. 在 NGINX 中配置 FastCGI
NGINX 可以快取來自 FastCGI 應用程式的響應,如 PHP 響應。此方法可提供最佳的效能。
對於開源的 NGINX,編譯入第三方模組 ngx_cache_purge 可以提供快取清除能力,配置程式碼如下所示。 NGINX Plus 已經包含了它自己實現此程式碼。
當使用 FastCGI 時,我們建議你安裝 NGINX 輔助外掛 並使用下面的配置檔案,尤其是要注意 fastcgi_cache_key 的使用和包括 fastcgi_cache_purge 的 location 塊。當頁面釋出或有改變時,有新評論被髮布時,該外掛會自動清除你的快取,你也可以從 WordPress 管理控制檯手動清除。
NGINX 的輔助外掛還可以在你網頁的底部新增一個簡短的 HTML 程式碼,以確認快取是否正常並顯示一些統計資料。 (你也可以使用 $upstreamcachestatus 確認快取功能是否正常。)
fastcgi_cache_path /var/run/nginx-cache levels=1:2keys_zone=WORDPRESS:100m inactive=60m;fastcgi_cache_key "$scheme$request_method$host$request_uri";server {server_name example.com www.example.com;root /var/www/example.com/htdocs;index index.php;access_log /var/log/nginx/example.com.access.log;error_log /var/log/nginx/example.com.error.log;set $skip_cache 0;### POST 請求和帶有查詢引數的網址應該交給 PHPif ($request_method = POST) {set $skip_cache 1;}if ($query_string != "") {set $skip_cache 1;}### 以下 uris 中包含的部分不快取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 / {try_files $uri $uri/ /index.php?$args;}location ~ \.php$ {try_files $uri /index.php;include fastcgi_params;fastcgi_pass unix:/var/run/php5-fpm.sock;fastcgi_cache_bypass $skip_cache;fastcgi_no_cache $skip_cache;fastcgi_cache WORDPRESS;fastcgi_cache_valid 60m;}location ~ /purge(/.*) {fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";}location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {access_log off;log_not_found off;expires max;}location = /robots.txt {access_log off;log_not_found off;}location ~ /\. {deny all;access_log off;log_not_found off;}}技巧 6. 為 NGINX 配置 W3_Total_Cache
W3 Total Cache, 是 W3-Edge 的 Frederick Townes 出品的, 是一個支援 NGINX 的 WordPress 快取框架。其有眾多選項配置,可以替代 FastCGI 快取。
這個快取外掛提供了各種快取配置,還包括資料庫和物件的快取,最小化 HTML 、 CSS 和 JavaScript,並可選與流行的 CDN 整合。
這個外掛會透過寫入一個位於你的域的根目錄的 NGINX 配置檔案來控制 NGINX 。
server {server_name example.com www.example.com;root /var/www/example.com/htdocs;index index.php;access_log /var/log/nginx/example.com.access.log;error_log /var/log/nginx/example.com.error.log;include /path/to/wordpress/installation/nginx.conf;location / {try_files $uri $uri/ /index.php?$args;}location ~ \.php$ {try_files $uri =404;include fastcgi_params;fastcgi_pass unix:/var/run/php5-fpm.sock;}}
技巧 7. 為 NGINX 配置 WP Super Cache
WP Super Cache 是由 Donncha O Caoimh 開發的, 他是 Automattic 的一個 WordPress 開發者, 這是一個 WordPress 快取引擎,它可以將 WordPress 的動態頁面轉變成靜態 HTML 檔案,以使 NGINX 可以很快的提供服務。它是第一個 WordPress 快取外掛,和其它的相比,它更專注於某一特定的領域。
配置 NGINX 使用 WP Super Cache 可以根據你的喜好而進行不同的配置。以下是一個示例配置。
在下面的配置中,帶有名為 supercache 的 location 塊是 WP Super Cache 特有的部分。 WordPress 規則的其餘程式碼用於不快取已登入使用者的資訊,不快取 POST 請求,並對靜態資源設定過期首部,再加上標準的 PHP 處理;這部分可以根據你的需求進行定製。
server {server_name example.com www.example.com;root /var/www/example.com/htdocs;index index.php;access_log /var/log/nginx/example.com.access.log;error_log /var/log/nginx/example.com.error.log debug;set $cache_uri $request_uri;### POST 請求和帶有查詢字串的網址應該交給 PHPif ($request_method = POST) {set $cache_uri 'null cache';}if ($query_string != "") {set $cache_uri 'null cache';}### 以下 uris 中包含的部分不快取if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php |sitemap(_index)?.xml|[a-z0-9_-]+-sitemap([0-9]+)?.xml)") {set $cache_uri 'null cache';}### 不對已登入使用者和最近的評論者使用快取if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in") {set $cache_uri 'null cache';}### 當請求的檔案存在時使用快取,否則將請求轉發給 WordPresslocation / {try_files /wp-content/cache/supercache/$http_host/$cache_uri/index.html$uri $uri/ /index.php;}location = /favicon.ico {log_not_found off;access_log off;}location = /robots.txt {log_not_found offaccess_log off;}location ~ .php$ {try_files $uri /index.php;include fastcgi_params;fastcgi_pass unix:/var/run/php5-fpm.sock;#fastcgi_pass 127.0.0.1:9000;}### 儘可能的快取靜態檔案location ~*.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {expires max;log_not_found off;access_log off;}}
技巧 8. 為 NGINX 配置安全防範措施
為了防止攻擊,可以控制對關鍵資源的訪問並限制機器人對登入功能的過量攻擊。
只允許特定的 IP 地址訪問 WordPress 的儀表盤。
### 對訪問 WordPress 的儀表盤進行限制location /wp-admin {deny 192.192.9.9;allow 192.192.1.0/24;allow 10.1.1.0/16;deny all;}
只允許上傳特定型別的檔案,以防止惡意程式碼被上傳和執行。
### 當上傳的不是影像,影片,音樂等時,拒絕訪問。location ~* ^/wp-content/uploads/.*.(html|htm|shtml|php|js|swf)$ {deny all;}
拒絕其它人訪問 WordPress 的配置檔案 wp-config.php 。拒絕其它人訪問的另一種方法是將該檔案的一個目錄移到域的根目錄之上的目錄。
### 拒絕其它人訪問 wp-config.phplocation ~* wp-config.php {deny all;}
對 wp-login.php 進行限速來防止暴力破解。
### 拒絕訪問 wp-login.phplocation = /wp-login.php {limit_req zone=one burst=1 nodelay;fastcgi_pass unix:/var/run/php5-fpm.sock;#fastcgi_pass 127.0.0.1:9000;}
技巧 9. 配置 NGINX 支援 WordPress 多站點
WordPress 多站點 ,顧名思義,這個版本 WordPress 可以讓你以單個例項管理兩個或多個網站。 WordPress.com 執行的就是 WordPress 多站點,其主機為成千上萬的使用者提供部落格服務。
你可以從單個域的任何子目錄或從不同的子域來執行獨立的網站。
使用此程式碼塊新增對子目錄的支援。
### 在 WordPress 多站點中新增對子目錄結構的支援if (!-e $request_filename) {rewrite /wp-admin$ $scheme://$host$uri/ permanent;rewrite ^(/[^/]+)?(/wp-.*) $2 last;rewrite ^(/[^/]+)?(/.*\.php) $2 last;}
使用此程式碼塊來替換上面的程式碼塊以新增對子目錄結構的支援,替換為你自己的子目錄名。
### 新增支援子域名server_name example.com *.example.com;
舊版本 (3.4 以前) 的 WordPress 多站點使用 readfile() 來提供靜態內容。然而,readfile() 是 PHP 程式碼,它會導致在執行時效能會顯著降低。我們可以用 NGINX 來繞過這個非必要的 PHP 處理。該程式碼片段在下面被 (==============) 線分割出來了。
### 避免對子目錄中 /blogs.dir/ 結構執行 PHP readfile()location ^~ /blogs.dir {internal;alias /var/www/example.com/htdocs/wp-content/blogs.dir;access_log off;log_not_found off;expires max;}============================================================### 避免對子目錄中 /files/ 結構執行 PHP readfile()location ~ ^(/[^/]+/)?files/(?.+) {try_files /wp-content/blogs.dir/$blogid/files/$rt_file /wp-includes/ms-files.php?file=$rt_file;access_log off;log_not_found off;expires max;}============================================================### 子域路徑的 WPMU 檔案結構location ~ ^/files/(.*)$ {try_files /wp-includes/ms-files.php?file=$1 =404;access_log off;log_not_found off;expires max;}============================================================### 對映部落格 ID 到特定的目錄map $http_host $blogid {default 0;example.com 1;site1.example.com 2;site1.com 2;}
結論
可擴充套件性對許多要讓他們的 WordPress 站點取得成功的開發者來說是一項挑戰。 (對於那些想要跨越 WordPress 效能門檻的新站點而言。) 為 WordPress 新增快取,並將 WordPress 和 NGINX 結合,是不錯的答案。
NGINX 不僅用於 WordPress 網站。世界上排名前 1000 、 10000 和 100000 網站中 NGINX 也是 遙遙領先的 web 伺服器。
欲瞭解更多有關 NGINX 的效能,請看我們最近的部落格,讓應用效能提升 10 倍的 10 個技巧。
NGINX 軟體有兩個版本:
- NGINX 開源軟體 - 像 WordPress 一樣,此軟體你可以自行下載,配置和編譯。
- NGINX Plus - NGINX Plus 包括一個預構建的參考版本的軟體,以及服務和技術支援。
想要開始,先到 nginx.org 下載開源軟體並瞭解下 NGINX Plus 。