博客 | NGINX

使用 NGINX 最大化 PHP 7 性能,第 1 部分: Web 服务和缓存

NGINX-F5-horiz-black-type-RGB 的一部分
Floyd Smith 缩略图
弗洛伊德·史密斯
2016 年 2 月 26 日发布

简介——NGINX 如何与 PHP 结合使用

PHP 是创建服务器端 Web应用最流行的方式,占有大约80% 的市场份额。 (ASP.net 位居第二,而 Java 位居第三,差距更小。)

PHP 世界包含大量 PHP 框架;最受欢迎的包括 Laravel、Phalcon 和 Symfony 2。 PHP 也是流行内容管理系统 (CMS)(例如WordPressDrupal )的基础。 (Drupal 的最新版本 Drupal 8 包含重要的Symfony 2集成。

现在,PHP 团队发布了新版本PHP 7——距离 PHP 5 推出已有十多年了。 在此期间,网络的使用量和网站的需求都呈指数级增长。 PHP 为这种快速增长做出了贡献 - 但其所实现的增长也凸显了 PHP 的局限性。

PHP 通常被认为功能强大且灵活,但是存在性能问题。 基于 PHP 的网站在流量数量增加几次之后就很容易“陷入困境”。 当一个网站开始实现其业务或运营目标时,只要流量增加,它就会开始崩溃。

对于成千上万个基于 PHP 的应用,一些相对简单的更改就足以提高性能。 这些包括使用memcached等工具进行缓存、调整数据库以及使用NGINX Open SourceNGINX Plus进行反向代理和负载均衡。 NGINX 极大地提高了应用程序的响应能力,支持用户和流量数量级的增加。

这篇博客文章是关于最大限度提高使用 PHP 7 的网站性能的两部分系列文章中的第一篇。 在这里我们专注于升级到 PHP 7,实现 NGINX Open Source 或 NGINX Plus 作为您的 Web 服务器软件,重写 URL(正确处理请求所必需),缓存静态文件,以及缓存动态文件(也称为应用缓存或微缓存)。

在下一篇博文中,我们将重点介绍使用附加服务器可以采取的步骤:添加反向代理服务器、移动到多台应用服务器、在多台服务器之间进行负载均衡、在负载均衡的同时支持会话持久性以及终止安全协议,例如 SSL/TLS 和相关的 HTTP/2 协议。

为什么 PHP 会遇到瓶颈

PHP应用为何会遇到障碍? 由于同样的原因,任何应用服务器软件都会遇到困难。 当用户请求到达时,PHP 及其运行的 Web 服务器软件必须执行以下几件事:

  • 解读请求。 首先,Web 服务器软件,然后 PHP 必须启动进程来接收、解密和处理请求。 例如,Apache HTTP Server 会分配资源来处理每个数据请求,无论其多么简单(检索 JPEG 文件)或复杂(处理嵌套的 CSS 请求)。 这一切都需要时间、系统资源和内存分配——如果操作系统、PHP 或两者在开始处理请求之前必须加载大量库,那么这些资源可能会非常大。
  • 处理支持协议。 如果您运行 SSL/TLS 和/或 HTTP/2,您的 Web 服务器软件必须解码请求,这是一个可能耗时的过程。
  • 根据请求采取行动。 PHP 必须整合资源来处理请求。 这可能需要多次数据库调用、通过互联网调用外部服务以及复杂的内部处理。
  • 回复请求。 PHP 必须将结果返回给 Web 服务器软件,以便作为 HTTP 响应传回给请求者。 请记住,从最初接收到最终确认,Web 服务器软件和 PHP 都为每个请求运行一个活动的专用线程。

对于物理服务器、虚拟机或云服务器实例来说,处理每个请求都需要做很多工作。 当服务器上的物理内存(无论是物理的还是虚拟的)耗尽时,性能就会下降。 然后,当新的请求到达时,服务器就开始将当前会话分页到磁盘。 等待文件请求完成也会引入导致分页的等待状态。 超过某个(非常有限的)点,分页操作和数据请求就会压倒处理操作,性能就会进入死亡螺旋,导致用户长时间等待或彻底终止会话。

解决性能问题

克服 PHP 的性能障碍当然是可能的,并且需要几个互补的步骤。 每个步骤都可以与其他步骤相结合。 大致包括:

  • 使用硬件来解决问题。 更多的内存、更多的内存、更快的磁盘、独立的数据库服务器、内容传送网络、增加的吞吐能力和其他机械解决方案是解决性能问题的快速而粗糙的解决方案。 这些解决方案可以保持正常运行时间或线性扩展性能。
  • 改进 PHP 和应用代码。 新版本的 PHP、新的框架和改进的应用代码可以提供很大帮助。 再次,性能可以提高一倍甚至四倍,而且不需额外花费购买新硬件。
  • 改进的服务器软件。 大多数 Web 服务器和 PHP 会为正在进行的每个打开的请求分配专用资源。 NGINX 服务器软件在收到请求时进行处理,而不会占用资源,从而最大限度地减少服务器占用空间。
  • 多服务器实现。 您可以实现反向代理服务器来处理 Internet 请求并在一个或多个应用服务器之间共享这些请求(负载平衡)。 反向代理服务器还可以处理文件缓存、SSL/TLS 和 HTTP/2 等协议的终止以及多个应用服务器的管理。 即使只有一台应用服务器,这也可以减轻其很大一部分工作量。 负载平衡可保证随着更多服务器的添加,任何服务器都不会因承担超过其份额的负载而陷入困境。

您不必按照任何特定顺序执行这些步骤;例如,即使您保留 Apache 作为您的 Web 服务器并且不将您的应用服务器升​​级到 PHP 7,只需在现有服务器“前面”实现 NGINX 作为反向代理就可以提高性能并使您能够并行实现多个应用服务器。

不管您如何做,要记住的关键事实是,您可以获得多个提高性能的因素,甚至在容量上提高一个数量级,而几乎不需要对当前的应用代码进行任何更改。 请继续阅读,了解人们如何已经实现或正在实现这些非凡的绩效提升。

笔记: 在这些博客文章中我们会忽略多服务器优化。 独立的数据库服务器和内容分发网络 (CDN) 可以减轻应用服务器的负担并大大提高性能;这些类型的变化与此处描述的应用和实施改进是分开的、并行的。

提示 1——升级到 PHP 7

尽早升级到 PHP 7 的主要原因很简单:应用速度(显著节省内存)。 据称,PHP 7 的速度比以前版本的 PHP快两倍,并且占用的内存也少得多。 (在这两个方面,您的里程无疑会有所不同。)

简单来说,响应时间对于 Web应用来说至关重要。 速度更快的网络应用(同时占用更少的内存,从而降低页面交换的可能性以及由此导致的性能问题)可实现以下三个目标:

  1. 让用户更开心,更有可能访问您的网站并完成任务,例如阅读文章、获取产品信息、叫公共汽车、租用空余房间或购买东西。 也就是说,您最初创建该网站或应用程序的原因。
  2. 使给定的服务器能够支持更多用户,而不会面临因用户增加而速度变慢甚至崩溃的风险。 推迟厄运总是一件好事。
  3. 使您的服务器不易受到黑客攻击,从而避免服务器超载并停止生产。 如今每个人都会受到攻击,但弱者受到的攻击更多,而且更具攻击性。 因此,较少的脆弱性比较多的脆弱性要好得多。

这些都是升级的极好理由;综合起来,升级的理由似乎势不可挡。 即使没有明显的性能优势,“升级到最新版本”始终是解决许多问题的首要建议。 那么为什么大家不立即升级呢?

使用 NGINX 最大化 PHP 7 性能
根据 xkcd 更新

很简单:人们讨厌弄乱旧代码,这是有充分理由的。 如果旧应用程序运行良好,并且开发人员从创建新应用程序中获得的结果比升级旧应用程序更好,那么旧应用程序就可以在很长一段时间内保持不变。 (有关如何使用 NGINX 来提高应用程序性能而无需对当前 Web 服务器和应用程序进行任何更改的信息,请参阅本系列的第二篇博客文章。)

但如果可能的话,更有效的做法是通过升级到 PHP 7 来开始追求更高的性能。 不过,除非你有足够的时间完成,否则不要开始,尤其是在不吝惜测试的情况下。

让我们看看升级到 PHP 7 需要做什么:

  • 表达式求值的改变。 您可能需要改变某些表达式的书写方式,以便它们在 PHP 7 中正确计算。 (或者,如果您非常小心并且不会一次升级所有 PHP 服务器,则可以让它们在 PHP 5.6 和 PHP 7 中都得到正确评估。) 如果您有可变变量或可变属性,则需要修改代码以使它们在两个 PHP 版本中以相同的方式进行评估。
  • 语法改变。 PHP 7 不支持 ASP 或脚本标签。 一个 switch 不能有多个 default case。 (我们暂且不论switchif-then-else之间的争议。)
  • 删除已弃用的功能各种各样的事情 在 PHP 5.x 版本中被弃用的 死鹦鹉。 它们根本无法在 PHP 7 中工作。 如果它们在您的代码中,而您尝试将它们全部删除,但失败了,那么您的购物车代码功能肯定会在网络星期一前一天晚上 11:59 消失。
  • 新功能。 PHP 7 添加了许多新功能来吸引任何升级旧代码的人,但在代码清理中添加新功能时要小心。 新功能通常都很棒,否则就不会被添加,但随着 PHP 的进一步升级,它们也会吸引错误(您和其他人的)和未来的修订。
  • 一般代码审查。 每当你接触代码时 - 甚至每当你打开一个代码文件并且不确定是否修改了它时 - 你确实需要检查其中的所有内容,特别是你修改过的内容。
  • 测试。 任何事物都需要时时进行测试。 如果您做了任何更改,则需要重新测试所有内容,但这并不意味着您会发现所有错误。 实施良好的 DevOps 环境可能会使这种测试相对容易,但截至目前,我们中只有少数人生活在那片应许之地。

Engine Yard 上的这个博客对大部分这些问题都有很好的例子。

如果您决定继续升级到 PHP 7,请考虑对您的代码(或至少是其关键功能)进行全面的性能审查和修订,以利用 PHP 7 中的新功能。 对于您和您的团队来说,没有比这更好的方式来提升技能,并且您今天做出、审查和测试的改变可能会在未来许多年里为您服务。 您还将从本篇博文中的其他性能建议中获得最大收益,因为优化代码在优化环境中运行时将受益匪浅。

因此,尽管网站经常部署 NGINX 以在不触及应用代码的情况下获得更好的性能,但我们还是建议您咬紧牙关,勇往直前。 有很多人可以帮助你完成这一举动,或者你也可以自己撸起袖子,自己动手。 官方 PHP 网站上有PHP 7 迁移指南,O'Reilly 也有PHP 7 升级指南

提示 2——选择 NGINX 开源或 NGINX Plus

NGINX 是运行超过 1.4 亿个网站的软件,其中包括10,000 个最繁忙网站的一半。 (这些测量检测单服务器站点的 Web 服务器和多服务器站点的反向代理服务器。) 作为 Web 服务器,两者都能立即提升性能 — — 在某些情况下,运行其他软件的服务器超载和抖动的次数最多可达 10 倍。 作为反向代理服务器,两者都允许使用多个专用服务器来根据需要广泛扩展部署。

PHP 和 Apache 都会为每个打开的请求分配资源;如果其中一个或两个都必须加载多个库,则每个请求的启动时间和内存占用量可能会非常大。 将 NGINX 用作 Web 服务器软件可在服务器级别消除此问题。 使用 NGINX 的功能将工作卸载到 Web 服务器(例如提供静态文件)或反向代理服务器(各种缓存、协议终止、负载均衡等),可最大限度地减少 PHP 需要做的事情,简化和加快应用处理。

如果您的网站有自定义或专有的 Apache 模块,您可能无法用 NGINX 替换 Apache,除非您替换这些模块。 检查 NGINX 是否有简单的解决方法;如果没有,则估算进行更改所需的时间和精力。

一旦您决定使用 NGINX,您就可以在 NGINX Open Source 和 NGINX Plus 之间进行选择。 NGINX Plus 相对于 NGINX 开源的一些最突出的特点包括:

  • 预编译代码。 NGINX Plus 以编译形式分发,包括可动态添加和删除的流行库和动态模块。 (NGINX 开源有编译代码未编译代码两种形式。) 您无需重新启动服务器即可进行各种配置更改。
  • 支持。 NGINX Plus 包含一个支持包,让您直接联系 NGINX 工程师。
  • 监测和管理。 DevOps 友好型工具可帮助您保持服务器正常运行以满足服务水平协议 (SLA)。

作为反向代理服务器,NGINX Plus 还有以下优势:

  • 负载均衡。 NGINX 的两个版本都支持基本的 HTTP 负载均衡,但 NGINX Plus 增加了更复杂的算法TCP 负载均衡
  • 会话持久性。 除了负载均衡之外,NGINX Plus 还提供更复杂的会话持久性,通常与 PHP应用服务器高度相关。
  • 监测和管理NGINX Plus 监控和管理的全部功能在多服务器部署中发挥作用;预编译代码和支持的价值也在更复杂的实现中得到最大化。

NGINX Open Source 和 NGINX Plus 都支持内容缓存和微缓存(也称为应用缓存)。 缓存在 Web 服务器环境中很有用,因为它可以卸载应用服务器,但两个功能仍然共享单台机器或虚拟机实例。 在反向代理服务器上,缓存可以从应用服务器设备卸载大量工作,从而提供更大的性能优势。

您可以直接从nginx.org下载 NGINX开源软件,在那里您还可以找到社区支持。 要开始单个 NGINX Plus 订阅,请注册30 天免费试用版在线购买。 对于多实例包,请联系NGINX 销售

技巧 3——将 Apache 配置转换为 NGINX 语法

当你从 Apache 迁移到 NGINX 作为你的 Web 服务器软件时,你需要进行一些更改 - 详细信息请参阅sitepoint.com上的一篇优秀文章

  • 创建或转换配置文件。 更改配置代码以指定 NGINX(不再是 Apache)应使用哪些文件进行配置。
  • 更改读/写权限。 为您的帐户添加权限,以对网站根目录中的文件执行 CRUD 操作(创建、读取、更新、删除)。
  • 指定有效的搜索模式。 添加位置块来指定 NGINX 在处理请求时可以尝试和不能尝试哪些模式。
  • 替换.htaccess配置代码。 Apache 的配置详细信息通常位于 .htaccess 文件或静态配置文件(例如mod_rewrite指令)中。 用NGINX配置文件中的相关配置规范替换这些。 有关一些示例,请参阅我们的博客

进行这些更改可以让您熟悉 NGINX 并使您能够优化更复杂的网站,正如我们在本博文的第 2 部分中所述。 但是,如果进行这些配置更改会给您的网站运营带来不可接受的工作量或风险程度,请不要担心 - 您可以实现第 2 部分中描述的多服务器架构,而无需从 Apache 升级核心 Web 服务器软件,因此也无需更改您的 Web 服务器配置文件。

技巧 4——实现静态文件缓存

静态文件就是不经常改变的文件,至少从网络服务器的角度来看是这样。 静态文件通常包括图形文件(例如 JPEG 和 PNG)和代码文件(例如 CSS 和 JavaScript 文件)。 如果将这些文件放在应用服务器上或单独的数据库服务器上,则对它们的请求必须由应用程序代码处理,并且会产生发出和满足请求所需的所有开销。 这会“分散”应用服务器对更重要的工作的注意力,并使其更接近物理内存过载的程度,而新的请求会导致当前请求分页到磁盘。

静态文件缓存是 NGINX 的核心功能。您可以在 Web 服务器或反向代理服务器上实现它:

  • 在 NGINX Web 服务器上,静态文件缓存可减轻应用服务器的负担;文件检索速度更快,内存开销更少。 但是,文件检索仍然由相同的物理服务器或虚拟服务器实例进行,因此服务器的处理器仍然被迫处理除运行应用之外的任务。
  • NGINX 反向代理服务器在与 Web 服务器不同的机器或实例上运行,因此其静态文件缓存不会消耗应用服务器上的资源。 应用服务器可以专注于运行您的应用。

在 NGINX 上实现静态文件缓存总体分为三个步骤:

  • 指定搜索的根目录。
  • 处理请求。
  • 优化响应速度。

在没有反向代理服务器参与的 NGINX Web 服务器上,您不会进行通常意义上的缓存。 您只需使用X-Accel-Redirect标头将对静态文件的查询重定向到 Web 服务器。 应用服务器永远看不到该请求,并且可以将所有资源用于应用请求。 使用反向代理服务器,您确实使用静态文件缓存 - 并且运行应用的物理服务器或虚拟服务器实例不参与响应静态文件请求。

作为优化响应速度的示例,以下配置片段使 NGINX 能够使用操作系统的sendfile系统调用,通过不将文件复制到中间缓冲区,从而节省了文件传输中的一步:

位置 /mp3 { sendfile on;
sendfile_max_chunk 1m;
# ...
}

有关配置 NGINX 进行静态文件缓存的详细信息,请参阅NGINX Plus 管理指南

提示 5——实现微缓存

令人困惑的是,微缓存有许多名称,其中还包括应用缓存和普通缓存。 在 NGINX 中,我们使用术语“微缓存”来强调此类文件有效的短暂时间。

假设您有一个博客文章页面,提供用户评论机制。 您希望在新访问者访问页面时,或者现有用户刷新页面查看自己或其他人的新评论时,包含最新、最精彩的评论。 在这种情况下,每次有人访问时重新生成页面似乎是个好主意。

然而,“每次”都会成为负担。 如果某个页面每秒只获得一次访问,则每次访问都重新生成该页面是有意义的。 但是,如果该页面每秒的访问量达到十次、一百次或一千次,并且网站上的所有其他页面也都达到这一水平,则应用服务器可能会超载。 要实现向人们提供新鲜内容的目标,就意味着没有人能快速获得任何内容。

微缓存意味着一旦将缓存版本标记为在短时间内有效(比如一秒或几秒),就会生成一个页面。 当缓存版本过期时,下一个请求将提示生成一个新页面,并在获取其缓存版本后立即请求。 这与静态文件的行为相同,但时间范围要短得多。

此图像指示在您的网站上哪里可以查找可以进行微缓存的内容。 它来自我们自己的 Owen Garrett 的一篇微缓存博客文章

缓存能力范围静态动态个性化
许多动态内容适合微缓存

微缓存非常棒,因为它在最需要的时候从应用服务器中删除工作,并且对用户的损害很小甚至没有损害。 它非常棒,甚至被内置到某些系统中。 Drupal 认为其强大的内置微缓存功能非常重要,因此在 Drupal 世界中,微缓存被简称为“缓存”。

但是 Drupal 解决方案有点欠缺,任何类似的解决方案也是如此。 应用服务器的工作较少,但仍然是 Drupal(或者更一般地说是 PHP)需要管理配置、实施和文件服务。 通过使用 NGINX 进行微缓存,应用服务器可以完全卸载任何内容,只需按照微缓存指定的频率生成新页面即可。 它甚至看不到其他请求,更不用说存储或检索任何缓存命中的内容。

使用 NGINX Plus 或其他工具,您可以监控您的网站并查看哪些页面将从微缓存中受益。 以下配置片段实现了 1 秒的响应缓存期,200正常状态代码。

proxy_cache_path /tmp/cache keys_zone=cache:10m levels=1:2 inactive=600s max_size=100m;server {
proxy_cache 缓存;
proxy_cache_valid 200 1s;
# ...
}

第一部分结论

我们的 PHP 博客文章的第一部分重点介绍单服务器解决方案以及缓存,这在单服务器实现中非常有效 - 但在混合使用反向代理服务器时更为有效。 第 2 部分描述了反向代理服务器以及围绕 PHP应用的多服务器实现的好处。

要试用 NGINX Plus,请立即开始30 天免费试用联系我们讨论您的用例。


“这篇博文可能引用了不再可用和/或不再支持的产品。 有关 F5 NGINX 产品和解决方案的最新信息,请探索我们的NGINX 产品系列。 NGINX 现在是 F5 的一部分。 所有之前的 NGINX.com 链接都将重定向至 F5.com 上的类似 NGINX 内容。”