在现代网络应用中,使网站能够处理大量流量是关键之一。当一个网站无法处理流量时,这一点对每个人来说都是显而易见的(例如HealthCare.gov)。为了让网络应用能够处理高负载,需要大量的工作。特别使用PHP编写的代码来实现这一点。
当开始使用PHP开发时,LAMP(Linux + Apache + PHP + MySQL)非常流行。它非常适合快速原型制作和小型应用。当时,LAMP似乎是自切片面包以来最伟大的事物。但直到开始编写每天被数百人使用的代码时,流量高峰、高CPU和RAM使用率以及手动重启似乎都是PHP开发者的一部分。
PHP在压力下表现不佳的声誉不佳。经过无数次重构而没有成功,许多PHP开发者会感到想要放弃。如果LAMP模型限制只有几十个用户,为什么要使用PHP呢?
不久前,还在那条船上,直到遇到了Steve Carona的《扩展PHP到数百万用户》。找到了让代码运行速度提高500%以上的方法,并将正常运行时间提高到接近99%。
在这篇博客中,将分享扩展PHP应用程序的经验。将描述一些策略和陷阱,并希望为所有想要完全放弃PHP的迷失开发者提供指导。第一手经验可能有助于澄清Steve书中的领域。或者,可以激励某人控制他们的堆栈,将其从毁灭中拯救出来。
当谈论扩展时,指的是应用程序架构能够优雅地响应高负载的能力。这涉及到从DNS到Web服务器到PHP版本到数据库的所有内容。这篇博客中描述的一些策略是特定于PHP的,但其他策略(例如Nginx,Percona XtraDB Cluster)可以应用于其他Web应用程序。
任何扩展项目都应该有的目标是:
第一步 - 使用Nginx提供静态文件服务 通常,迈出第一步是最困难的。如果它失败了,其他计划就会慢慢崩溃。如果它成功了,那么至少在下一步的挣扎中有一些以前的成功可以推动它们前进。这就是为什么选择Nginx作为第一步。它简单、易于使用,并且在性能上比Apache有巨大的提升。它如此简单,以至于甚至不能搞砸。
在LAMP中,Apache有两个主要工作:提供静态文件和调用mod_php来评估PHP脚本。一个服务做两个工作可能是一个优点,但在扩展方面它是一个缺点。当用户向Apache请求静态文件时,检索文件的forked Apache进程中内置了mod_php。因此,用于该请求的所有RAM和CPU时间都浪费了。这是可以轻松削减的浪费。
这个领域是Nginx的亮点。它可以为提供静态文件,并且不在乎使用PHP作为服务器端语言。当它收到PHP请求时,它可以将该请求发送给Apache,而不会阻塞其他forks。它的fork中没有mod_php,所以那里也没有浪费。Nginx的fork在RAM和CPU使用量上比Apache的fork小得多。Nginx是事件驱动的,而Apache是进程驱动的,所以得到了异步和非阻塞的额外好处。
将Nginx放在前面,将PHP请求发送到后面的Apache,是这个过程中可以采取的非常简单的第一步。遇到的唯一问题是与gzip和PHP的flush()方法。Nginx需要一些特殊的配置,用于长时间运行的进程,其输出是gzip的。将把那个和阅读Nginx陷阱/最佳实践作为家庭作业。
第二步 - 使用PHP-FPM进行PHP处理 一旦迈出了第一步,并且致力于让架构变得更好,就迫不及待地想看看其他步骤会让堆栈变得多好。记得第一次运行Nginx与Apache的基准测试时,惊呆了。计算出正在扩展的堆栈可以在使用较少资源的情况下处理200%到300%的流量。
现在,让最喜欢的部分:摆脱Apache。记得以前Apache是最棒的。当然,由于解决了许多依赖关系,它花了几个小时来安装,但它工作得很好。哦,是多么的傻瓜。
当涉及到大规模评估PHP时,PHP-FPM是黄金标准。它和Nginx是高负载PHP处理的事实上的赢家。与Apache不同,Apache在数百件事情上都做得相当不错,PHP-FPM只关心一件事:尽可能快地评估PHP。
它非常擅长这一点。它如此擅长,以至于从一个用户维护的补丁变成了被PHP团队纳入PHP本身。PHP-FPM是一个FastCGI服务器,它将PHP与每个fork捆绑在一起。这允许PHP请求尽可能快地被评估,并且尽可能少地进行繁琐的程序。
PHP-FPM自5.3以来就得到了PHP团队的支持。如果还没有使用5.3或更高版本,请加入潮流。它更快、更可靠、更一致,并且允许一些非常酷的语法糖。升级过程可能很困难,特别是对于大型代码库。然而,优势使所有花费的时间都值得。