WordPress 是全球最大的网站创建和 Web 应用程序交付平台。现在,大约四分之一的网站都是基于开源 WordPress 软件构建的,包括 eBay、Mozilla、RackSpace、TechCrunch、CNN、MTV、纽约时报、华尔街日报的网站。
WordPress.com 是最受欢迎的用户创建博客网站,它本身在 WordPress 开源软件上运行。NGINX 为 WordPress.com 提供支持。在 WordPress 客户中,许多网站从 WordPress.com 开始,然后转向托管 WordPress 开源软件;越来越多的这些站点也使用 NGINX 软件。FastCGI
WordPress 的吸引力在于其简单性,无论是对最终用户还是对实施而言。然而,当使用率上升时,WordPress 网站的架构会出现问题——包括缓存和组合 WordPress 和 NGINX 在内的几个步骤可以解决这些问题。
在这篇博文中,我们提供了九个性能技巧来帮助克服典型的 WordPress 性能挑战:
- 缓存静态资源
- 缓存动态文件
- 迁移到 NGINX
- 为 NGINX 添加永久链接支持
- 为 FastCGI 配置 NGINX
- 为 W3 总缓存配置 NGINX
- 为 WP 超级缓存配置 NGINX
- 为您的 NGINX 配置添加安全预防措施
- 配置 NGINX 以支持 WordPress 多站点
LAMP 网站上的 WordPress 性能
大多数 WordPress 站点都在传统的 LAMP 软件堆栈上运行:Linux 作为操作系统,Apache HTTP Server 作为 Web 服务器,MySQL 作为数据库软件——通常在单独的数据库服务器上——以及 PHP 作为编程语言。其中每一个都是非常知名的、广泛使用的开源工具。WordPress 世界中的大多数人都会“说”LAMP,因此很容易获得帮助和支持。
当用户访问 WordPress 站点时,运行 Linux/Apache 组合的浏览器会为每位用户创建 6 到 8 个连接。当用户在站点中移动时,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 产品推荐)。
缓存静态资源有两大好处:
- 更快地交付给用户 ——用户从他们的浏览器缓存或 Internet 上离他们更近的缓存服务器获取静态文件。这些有时是大文件,因此减少它们的延迟有很大帮助。
- 减少应用服务器上的负载 ——从缓存中检索到的每个文件都比 Web 服务器需要处理的请求少一个。你缓存的越多,你就越能避免因为资源耗尽而崩溃。
要支持浏览器缓存,请为静态文件设置正确的 HTTP 标头。查看 HTTPCache-Control
标头,特别是max-age
设置、Expires
标头和Entity
标签。您可以在KeyCDN 博客上找到很好的介绍。
当启用本地缓存并且用户请求以前访问过的文件时,浏览器首先检查该文件是否在缓存中。如果是这样,它会询问 Web 服务器文件是否已更改。如果文件没有改变,Web 服务器可以立即响应代码304
(Not
Modified)
,表示文件没有改变,而不是返回代码200
OK
,然后检索和交付改变的文件。
要支持浏览器之外的缓存,请考虑以下提示,并考虑内容交付网络 (CDN)。CDN 是一种流行且强大的缓存工具,但我们不在这里详细描述它们。在实现此处提到的其他技术后,请考虑使用 CDN。此外,当您将站点从 HTTP/1.x 转换到新的 HTTP/2 标准时,CDN 可能不太有用;根据需要进行调查和测试,以找到适合您网站的正确答案。
如果您按照技巧 3中的建议将 NGINX Plus 或 NGINX 开源作为软件堆栈的一部分,然后配置 NGINX 以缓存静态资源。以下配置是一个很好的起点;将www.example.com替换为您的 Web 服务器的 URL,并根据需要修改其他路径名。
server {
# substitute your web server's URL for www.example.com
server_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;
# substitute the socket, or address and port, of your WordPress server
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 – 为每个 WordPress 页面或帖子创建一个 PHP 文件。这支持一些动态功能,同时绕过许多 WordPress 核心处理和数据库连接,从而带来更快的用户体验。它不会绕过所有 PHP 处理,因此它不会提供与以下选项相同的性能提升。另一方面,它也不需要更改 NGINX 配置。
- WP Super Cache – 最流行的 WordPress 缓存插件。它有许多设置,通过易于使用的界面呈现,如下所示。我们在技巧 7中展示了一个示例 NGINX 配置。
- W3 Total Cache – 这是 WordPress 中第二受欢迎的缓存插件。它具有比 WP Super Cache 更多的选项设置,使其成为一个强大但有些复杂的选项。有关 NGINX 配置示例,请参阅技巧 6。
- FastCGI – CGI 代表通用网关接口,一种在 Internet 上请求和接收文件的语言中立方式。FastCGI 不是一个插件,而是一种与缓存交互的方式。FastCGI 可以在 Apache 和 NGINX 中使用,它是最流行的动态缓存方法;我们在技巧 5中描述了如何配置 NGINX 以使用它。
这些插件和技术的文档解释了如何在典型的 LAMP 堆栈中配置它们。配置选项包括数据库和对象缓存;缩小 HTML、CSS 和 JavaScript 文件;和流行 CDN 的集成选项。有关 NGINX 配置,请参阅列表中引用的提示。
注意:缓存不适用于登录 WordPress 的用户,因为他们对 WordPress 页面的视图是个性化的。(对于大多数网站,可能只有一小部分用户可能已登录。)此外,大多数缓存不会向最近发表评论的用户显示缓存页面,因为他们希望在刷新时看到他们的评论出现这页纸。要缓存页面的非个性化内容,您可以使用一种称为片段缓存的技术,如果它对整体性能很重要的话。
技巧 3 – 迁移到 NGINX
如上所述,当同时用户的数量超过某个点(可能是数百个同时用户)时,Apache 可能会导致性能问题。Apache 为每个连接分配大量资源,因此往往会耗尽内存。Apache 可以配置为限制连接以避免耗尽内存,但这意味着当超过限制时,新的连接请求必须等待。
此外,Apache 会mod_php
为每个连接将模块的另一个副本加载到内存中,即使它只提供静态文件(图像、CSS、JavaScript 等)。这会为每个连接消耗更多资源,并进一步限制服务器的容量。
要开始解决这些问题,请从 LAMP 堆栈转移到 LEMP 堆栈——将 Apache 替换为 (e)NGINX。NGINX 在固定内存占用中处理数千个同时连接,因此您不必经历颠簸,也不必将同时连接限制在少量。
NGINX 还可以更好地处理静态文件,具有内置的、易于调整的缓存控件。应用程序服务器上的负载减少了,您的站点可以为用户提供更快、更愉快的体验,从而提供更多流量。
您可以在部署中的所有 Web 服务器上使用 NGINX,或者您可以将 NGINX 服务器放在 Apache 的“前面”作为反向代理 – NGINX 服务器接收客户端请求,提供静态文件,并将 PHP 请求发送到 Apache,Apache处理它们。
对于动态生成的页面(WordPress 体验的核心用例),请选择缓存工具,如提示 2中所述。在下面的 Tips 中,您可以找到有关 FastCGI、W3 Total Cache 和 WP Super Cache 的 NGINX 配置建议。(Hyper-Cache不需要更改 NGINX 配置。)
小费。缓存通常保存到磁盘,但您可以使用它tmpfs
来将缓存存储在内存中并提高性能。
为 WordPress 设置 NGINX 很容易。只需遵循以下四个步骤,这些步骤在指示的提示中进行了更详细的描述:
- 添加永久链接支持——向 NGINX 添加永久链接支持。这消除了对特定于 Apache 的.htaccess配置文件的依赖。请参阅提示 4。
- 配置缓存 – 选择一个缓存工具并实施它。选项包括 FastCGI 缓存、W3 Total Cache、WP Super Cache 和 Hyper Cache。请 参阅技巧 5、6和7。
- 实施安全预防措施——在 NGINX 上采用 WordPress 安全性的最佳实践。见技巧 8。
- 配置 WordPress 多站点 – 如果您使用 WordPress 多站点,请为子目录、子域或多域架构配置 NGINX。见技巧 9。
技巧 4 – 为 NGINX 添加永久链接支持
许多 WordPress 站点依赖于.htaccess文件,这些文件是一些 WordPress 功能所必需的,包括永久链接支持、插件和文件缓存。NGINX 不支持.htaccess文件。幸运的是,您可以使用 NGINX 简单而全面的配置语言来实现大部分相同的功能。
您可以通过在主块中包含以下块来使用 NGINX 在 WordPress中启用永久链接。(此块也包含在下面的其他代码示例中。)location
server
location
该try_files
指令告诉 NGINX 检查请求的 URL 是否作为文件 ( $uri
) 或目录 ( $uri/
) 存在于文档根目录/var/www/example.com/htdocs中。如果没有,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 – 为 FastCGI 配置 NGINX
NGINX 可以缓存来自 PHP 等 FastCGI 应用程序的响应。这种方法提供了最好的性能。
对于 NGINX 开源,在提供缓存清除能力的第三方模块ngx_cache_purge中编译,并使用下面的配置代码。NGINX Plus 有自己的内置代码实现。
使用 FastCGI 时,我们建议您安装 WordPress 的Nginx Helper插件并使用如下配置(其中fastcgi_cache_key
和location
包含的块fastcgi_cache_purge
特别相关)。当发布或修改页面或帖子、发布新评论或从 WordPress 管理仪表板手动清除缓存时,插件会自动清除缓存。
Nginx Helper插件还可以在页面底部添加一个简短的 HTML 片段,确认缓存正在工作并显示一些统计信息。$upstream_cache_status
(您还可以使用该变量确认缓存是否正常运行。)
server { server_name example.com www.example.com; root /var/www/example.com/htdocs; index index.php;
fastcgi_cache_path /var/run/nginx-cache levels=1:2 keys_zone=WORDPRESS:100m inactive=60m; fastcgi_cache_key "$scheme$request_method$host$request_uri";
access_log /var/log/nginx/example.com.access.log; error_log /var/log/nginx/example.com.error.log;
set $skip_cache 0;
# POST requests and URLs with a query string should always go to PHP if ($request_method = POST) { set $skip_cache 1; }
if ($query_string != "") { set $skip_cache 1; }
# Don't cache URIs containing the following segments if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php |sitemap(_index)?.xml") { set $skip_cache 1; }
# Don't use the cache for logged-in users or recent commenters 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 – 为 W3 总缓存配置 NGINX
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 – 为 WP Super Cache 配置 NGINX
WP Super Cache由Automattic的 WordPress 开发人员 Donncha O Caoimh 开发,是一个 WordPress 缓存引擎,可将动态 WordPress 页面转换为 NGINX 可以非常快速地提供服务的静态 HTML 文件。它是 WordPress 的首批缓存插件之一,并且比其他插件具有更小、更集中的选项范围。
NGINX 配置可以根据您的偏好而有所不同。下面是一种可能的配置。
在下面的配置中,第一个location
块(try_files
指令的第一个参数中包含supercache
元素)是特定于 WP Super Cache 的部分,是配置工作所必需的。其余代码由不缓存登录到 WordPress 的用户、不缓存POST
请求、为静态资产设置过期标头以及标准 PHP 实现的 WordPress 规则组成;这些部件可以定制以满足您的需求。
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 requests and URLs with a query string should always go to PHP if ($request_method = POST) { set $cache_uri 'null cache'; } if ($query_string != "") { set $cache_uri 'null cache'; } # Don't cache URIs containing the following segments 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'; } # Don't use the cache for logged-in users or recent commenters if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+ |wp-postpass|wordpress_logged_in") { set $cache_uri 'null cache'; } # Use cached or actual file if it exists, otherwise pass request to WordPress location / { 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 off; access_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; } # Cache static files for as long as possible 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 仪表板。
# Restrict access to WordPress dashboard
location /wp-admin {
deny 192.192.9.9;
allow 192.192.1.0/24;
allow 10.1.1.0/16;
deny all;
}
只允许上传特定类型的文件。以防止恶意程序被上传和运行。
# Deny access to uploads that aren’t images, videos, music, etc.
location ~* ^/wp-content/uploads/.*.(html|htm|shtml|php|js|swf)$ {
deny all;
}
拒绝访问WordPress 配置文件wp-config.php。另一种拒绝访问的方法是将文件移动到域根目录之上的一个目录级别。
# Deny public access to wp-config.php
location ~* wp-config.php {
deny all;
}
限制对wp-login.php的访问以阻止暴力攻击。
# Deny access to wp-login.php
location = /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 Multisite,顾名思义,是 WordPress 软件的一个版本,允许您从单个 WordPress 实例管理两个或多个站点。托管数千个用户博客的WordPress.com服务是从 WordPress Multisite 运行的。
您可以从单个域的子目录或单独的子域运行单独的站点。
使用此代码块添加对子目录结构的支持。
# Add support for subdirectory structure in WordPress Multisite
if (!-e $request_filename) {
rewrite /wp-admin$ $scheme://$host$uri/ permanent;
rewrite ^(/[^/]+)?(/wp-.*) $2 last;
rewrite ^(/[^/]+)?(/.*.php) $2 last;
}
或者使用下面的代码块而不是前面的代码块来添加对子目录结构的支持,替换您自己的子目录名称。
# Add support for subdomains
server_name example.com *.example.com;
旧版本的 WordPress Multisite(3.4 和更早版本)用于readfile()
提供静态内容。但是,readfile()
是 PHP 代码,它在执行时会导致显着的性能下降。我们可以使用 NGINX 绕过这种不必要的 PHP 处理。下面的代码片段由等号行分隔 (==============)。
# Avoid PHP readfile() for /blogs.dir/structure in the subdirectory path. location ^~ /blogs.dir { internal; alias /var/www/example.com/htdocs/wp-content/blogs.dir; access_log off; log_not_found off; expires max; } ============================================================ # Avoid PHP readfile() for /files/structure in the subdirectory path 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 files structure for the subdomain path location ~ ^/files/(.*)$ { try_files /wp-includes/ms-files.php?file=$1 =404; access_log off; log_not_found off; expires max; } ============================================================ # Map blog ID to specific directory map $http_host $blogid { default 0; example.com 1; site1.example.com 2; site1.com 2; }
总结
随着越来越多的网站开发人员在 WordPress 网站上取得成功,可扩展性是他们面临的挑战。(对于那些想在通行证上解决 WordPress 性能问题的新网站。)添加 WordPress 缓存,并结合 WordPress 和 NGINX,是可靠的答案。
NGINX 不仅对 WordPress 网站有用。NGINX 是世界上 1,000、10,000、100,000和 100 万个最繁忙网站的领先 Web 服务器。
有关 NGINX 性能的更多信息,请参阅我们的博客文章10 倍应用程序性能的 10 个技巧。
NGINX 软件有两个版本:
- NGINX 开源 – 与 WordPress 一样,这是您自己下载、配置和编译的软件。
- NGINX Plus – NGINX Plus 包括软件的预构建参考版本,以及服务和技术支持。
要开始使用,请访问nginx.org了解 NGINX 开源或查看NGINX Plus。
评论0 注意:评论区不审核也不处理售后问题!如有售后问题请前往用户中心提交工单以详细说明!