WordPress 主机托管手册

title: "性能" post_status: publish comment_status: open taxonomy: category: - hosting-handbook post_tag: - Repos - Data - Docs Translate


性能

本节将介绍为 WordPress 配置服务以提升性能的基础知识。

缓存

WordPress 具有丰富的动态功能,但这需要付出代价。处理 PHP、查询数据库以及从外部 API 收集信息等任务都会消耗资源和时间。

缓存通过重用先前计算的结果来节省潜在繁重任务的时间,而不是为每个页面视图重新计算。

缓存通常在一定时间后过期并重新生成,以显示最新内容。当项目从缓存中提供时,响应时间更快(通常来自内存),并减轻服务器负载。

在典型的页面加载过程中,可能会按以下顺序检查各种缓存:

  1. 本地浏览器缓存 / 本地存储 / Web 应用清单
  2. 内容分发网络 (CDN)
  3. 全页缓存(反向代理 - Varnish 或 NGINX)
  4. 全页缓存(基于插件的文件式全页缓存)
  5. 静态缓存(JS、CSS、图像,使用静态缓存服务、NGINX tryfiles 等)
  6. 操作码缓存
  7. 对象缓存(wp_options、瞬态 API)
  8. 片段缓存(数据库、静态文件、瞬态 API)

每个缓存实例可能位于不同的域、服务器或计算实例上,由本地机器、远程服务器集群或请求链中的任何中间计算机路由。建议咨询您的主机提供商,了解服务器端解决方案(如 Varnish 和 NGINX),这些方案通常比插件和基于文件的全页缓存更快。

每个缓存可能具有以下任意配置:
数据存储:RAM、SSD 或机械硬盘。物理连接或网络数据传输。
输入/输出延迟:从本地或远程服务器主板到 RAM、数据 I/O 或网络 I/O 的连接。

对于任何给定的页面加载,速度和用户体验将取决于所有服务的综合延迟,以及用户与 Web 应用程序交互时这些服务的处理顺序。

示例:CSS;由 JavaScript、PHP 或预处理器生成。通过网络发送。最早显示:在第一个 HTML 响应的第一个 HTTP 数据包中的内联脚本。典型情况:由许多插件在多个请求中加载多个文件。折中方案:合并文件,缓存在本地、CDN 或服务器 RAM 或 SSD 中。)

内容分发网络(CDN)缓存

内容分发网络旨在优化服务器与来自不同地理位置的访客之间的网络延迟。数据分布在各个端点之间,访客会从距离他们最近的端点获取服务。

除了优化网络延迟外,CDN 还可以作为另一层静态缓存和/或全页缓存,运行在所有端点上。

确保 CDN 与所有其他缓存系统良好协作,并且当您从主服务器请求时,它能清除所有端点的缓存,这一点非常重要。否则,某些地区的用户可能会得到过时的结果,这通常是一个难以排查的问题。

请注意,如果在 CDN 边缘节点上没有启用全页缓存,可能会增加 TTFB(首字节时间),因为节点必须先从源服务器获取数据,然后才能将其提供给最终用户。

Full Page Cache

In order to display your content, WordPress does a lot of work under the hood, and all those calculations require server resources and time to complete. For starters, the PHP service on the server has to process the request, load WordPress core, your theme PHP files and all PHP scripts coming from your plugins. The majority of those PHP files make requests to your database, too, which adds to the overall resource footprint of your site.

The best way to cache these requests is to use a reverse proxy like NGINX or Varnish which stores the output directly into the server memory or hard disk. That saves a lot of processing power because cached content is served straight out of the reverse proxy without hitting your web server, the PHP service, or your database service at all. If a reverse proxy is not available on your current server setup, you can fallback to storing cached content into your file system. It's slower than reverse proxies and a hit reaches your web server and your PHP service at least once, so it can direct the request to the proper cached file but still - it's much faster than doing all the computing for every request.

Full Page Caching stores the HTML output of a request, but all the CSS, JS, images and font files will have to be loaded separately too. They are handled separately and optimizing them is worth investing the time and effort. Static caching can have great effect on those resources. You can often use the same reverse proxy to static resources in the server memory - CSS, JS, Fonts, Images and serve them directly.

It's important to have the ability to expire caches when necessary to avoid serving visitors old data. When available, selective caching is preferred over purging the entire cache, to avoid the cost of WordPress regenerating every page for the site. Furthermore, it's good practice to exclude certain types of pages from your full page caching completely because they are different for each user. For example, if you have an online store, it's imperative that your cart, checkout and profile pages are completely dynamic. In general, it’s a good idea to exclude all logged in users from the cache because they are supposed to see personalized content. Another important aspect is the default caching period, which can be different for each website depending on how often data is changed.

Full Page Cache Example

对象缓存

2005 年,WordPress 引入了其内部对象缓存——一种将数据库中的任何数据(不仅仅是对象)自动存储在 PHP 内存中以防止不必要查询的方法。然而,默认情况下,WordPress 会在请求结束时丢弃所有这些对象,需要在下次页面加载时从头开始重建它们。除此之外,您可以使用像 Redis 或 Memcached 这样的持久对象缓存机制,但这需要额外的插件(drop-ins)来允许 WordPress 使用这些服务。

source: scalewp.io

What does this mean? Think of a standard WordPress homepage displaying the most recent posts. Each of these posts has quite a bit of information associated with it WordPress must look up such as the author, categories, tags, and excerpt.

Support for a persistent object cache gives WordPress, plugins, and themes, a place to store that data for reuse. While these items are cached, PHP execution time is improved while lessening the load on the database. It's particularly helpful in situations where much of the page is difficult to cache from the front-end, like for authenticated traffic or e-commerce applications.

For these reasons, persistent object caching support is commonly offered with managed WordPress hosting.

Object Cache Example

Transients are inherently sped up by caching plugins, where normal Options are not. A memcached plugin, for example, would make WordPress store transient values in fast memory instead of in the database. For this reason, transients should be used to store any data that is expected to expire, or which can expire at any time. Transients should also never be assumed to be in the database, since they may not be stored there at all.

来源:WordPress 通用 API 手册

操作码缓存

Web 服务器必须读取、编译并运行每个 PHP 脚本。操作码缓存会将每个 PHP 脚本的编译副本存储在内存或磁盘中。当 Web 服务器开始处理 WordPress 的 PHP 脚本时,它会检查操作码缓存中是否有该 PHP 脚本的缓存副本。如果存在缓存副本,Web 服务器可以直接使用缓存副本来运行 PHP 脚本,而无需再次读取和编译脚本。跳过 PHP 脚本的读取和编译过程可以显著提升 Web 服务器的资源利用率,并使 WordPress 能够处理比原本多得多的请求。这对于动态内容和认证流量尤其有帮助,因为全页面缓存在这些情况下效果不佳。

与任何缓存一样,操作码缓存可能会阻止更改生效,直到缓存过期或被清除。具体到操作码缓存,这意味着会加载旧版本的编译 PHP 代码。在更新插件、主题或 WordPress 核心时,应从缓存中清除相应的文件,以避免继续加载旧版本。

片段缓存

这种缓存方法允许保存原本不可缓存的动态网站内容片段。它特别适用于页面主体为静态但包含特定动态元素(如购物车)的网站,或会员制网站。

在 WordPress 环境中,开发者通常使用 WordPress 瞬态/对象缓存 API 来存储页面部分内容。这种情况下,提供持久化对象缓存可使这些内容在数据库外部实现缓存。

WordPress 本身不支持在前端缓存中单独存储这些片段,这意味着需要手动配置页面的可缓存部分,并配置前端缓存(无论是 Nginx、Varnish 或其他方案)以支持片段缓存。这通常属于高级技术,仅适用于动态流量需求极高的网站或托管平台。

缓存清理/清除/清空

缓存清理与缓存存储同等重要。必须确保在必要时清除所有缓存层级。

片段缓存是指将高成本或耗时的服务器端操作临时存储,以避免给 Web 服务器带来负担并延迟向访客交付内容。对于生成菜单标记、小部件标记以及缓慢的 MySQL 或 HTTP 响应等操作,这已成为常见做法。核心目前使用瞬态来缓存对 WordPress.org API 的 HTTP 调用,以获取更新和事件信息。

当片段缓存与全页缓存适当搭配时,效果尤为显著。例如,每个页面都显示的统一 <footer> 标记可以临时存储。当服务器需要重建静态缓存文件并找到片段时,可以避免服务器在每个页面上运行菜单/小部件查询来生成页脚标记。

对核心资源进行全局缓存时应格外谨慎。如果网站菜单依赖于动态的 .current-menu-item 类,将菜单标记存储在片段中会“固化”该类,导致用户导航时不再高亮显示正确的页面。任何 WordPress 核心资源的缓存都应选择加入,并集成适当的刷新机制,以便用户在修改资源时进行更新。

片段缓存应始终使用瞬态 API,而不是直接使用 wp_cache_* 函数。在没有持久对象缓存的环境中,set_transient() 会将缓存值存储在数据库的 wp_options 表中。然而,当启用对象缓存时,set_transient() 将包装 wp_cache_set()

PHP

请参阅 PHP 优化