在过去的十年中,无论是天下 500 强企业或是仅拥有 500 名用户的企业,我的团队都曾为他们开拓过软件。
在此期间,我的工程团队紧张利用 PHP 进行后端开拓。
2 年前,我们在开拓项目中引入了一些东西,这不仅彻底改变了我们产品的性能,也改变了它们的可扩展性————我们将 Golang 引入到我们的开拓框架中。

很快,我们创造 Golang 的引用使得我们能够为客户设计更大型,速率提高 40 倍的运用程序。
我们可以利用 Go 的强大功能来增强我们用 PHP 编写的产品,并充分利用这两种措辞的利害进行取长补短。

我将阐明如何结合 Golang 和 PHP 这两种措辞办理实际开拓中的问题,这将为你的 PHP 开拓带来全新的道路,以此办理垂死的 PHP 模型 干系的一些问题。

golangphpGCTT 出品PHP 不会逝世若何应用 Golang 来阻拦 PHP 走向衰亡 Docker

首先先容常用的 PHP 设置

在回答我们如何利用 Golang 来将 PHP 起去世复生之前,我们先先容一下标准的 PHP 设置。

在大多数情形下,PHP 开拓者会利用 nginx Web-serverphp-fpm 做事器组合运行运用程序。
php-fpm 实行 PHP 代码时,Nginx 供应静态文件并将特定要求转发到 php-fpm
也可以将 Apachemod_php 一起利用
纵然这种事情办法和上面那种略有不同,但它们的事理还是类似的。

对付开拓者来说,理解 php-fpm 如何实行运用程序的代码是最有趣的。
当一个要求发送时,php-fpm 启动一个 PHP 子进程,并且将要求内容作为进程状态的一部分(_GET,_POST 和 _SERVER 等)。
在实行 PHP 脚本期间,状态无法变动,因此获取一组新输入数据的唯一方法是销毁该进程并重新开始。

像这样的实行模型有很多好处。
你不必担心内存利用情形,所有进程都完备隔离,如果个中任何进程去世亡,那么它们将自动创建而不会影响其他进程。
但与此同时,当你考试测验扩展运用程序时,这一特性会成为程序开拓的绊脚石。

一样平常的 PHP 设置利用起来很麻烦并且非常低效

如果你本日正在进行专业的 PHP 开拓,那么你该当已经知道开始一个新项目的第一步 - 选择框架。
框架供应了依赖注入,ORM,翻译和大量丰富的库。
当然,所有用户输入数据都可以方便地放在一个工具(Symfony/HttpFoundationPSR-7)。
框架用起来是那么得心应手!

但任何事都有两面性。
所有的企业级框架都哀求你加载至少十二个文件,布局多个类并解析一些配置,以便处理大略的用户要求或查询数据库。
最糟糕的部分是每个任务完成后,你不得不抛弃这些代码。
你刚刚启动的所有代码现在都变得无用,并且永久不能拿来处理另一个要求。
若是说给任何利用 PHP 之外的开拓职员听,他们一定会对此满脸困惑,不能理解。

多年来,聪明的 PHP 工程师一贯试图通过利用延迟加载技能,微框架,优化良好的库,二级缓存等技能来缓解这些问题。
但是在你项目结束时,你仍旧不得不扔掉你的全体流程并一遍又一各处重新开始重复的事情。

在 Golang 的帮助下,PHP 能否支持多要求?

只要不是几小时或几天的生命周期,编写生命周期超过几分钟的 PHP 脚本还是可以的:比如 cron 作业,CSV 解析器和行列步队利用者。
所有这些脚本都遵照相同的过程:检索值,实行作业,等待下一个值到来。
代码在全体过程中都保留在内存中,终极只能节省几毫秒,由于加载框架和勾引程序须要进行大量的交互。

开拓能够永劫运行的脚本并不随意马虎。
任何缺点都会彻底杀去世进程,诊断内存泄露非常麻烦,我们无法再利用 f5-debug。

然而,随着 PHP7 的推出,情形有所改进,这个版本供应了一个可靠的垃圾网络器,使得缺点更随意马虎得到处理并防止核心内存泄露。
虽然工程师们仍旧适合心他们的代码中的内存和状态问题,但是,你不必担心找不出问题所在并有效办理这些问题。

是否有可能采取模型来处理那些,须要长期运行的 PHP 脚本并使其适应更繁芜的任务需求,如处理 HTTP 要乞降肃清每个要求的勾引加载?

首先,我们须要实现一个做事器程序,该程序可以接管 HTTP 要求,然后逐个将它们转发给 PHP 事情者,而不是每次都杀去世事情者。

我们知道我们可以利用纯 PHP(PHP-PM)实现 Web 做事器,或者利用 C-extension(Swoole)编写。
虽然这两种方法都有各自上风,但两者都不能让我们满意,我们须要更好的方法。

我们须要的不仅仅是一个 Web 做事器,而是希望能够去掉 PHP 开拓中的繁重操作和其他负面成分同时,仍旧保障每个运用程序的可扩展性和多样性。
我们须要一个能够多元化的运用做事器。

Golang 可以帮助我们创建这样的运用做事器吗?我的答案是,它可以。
由于这种措辞是跨平台的,它可以将运用程序编译成单个二进制文件,我们还可以利用其非常优雅的并发模型和 HTTP 标准库,最主要的是,我们可以利用 Golang 所拥有的数千个开源库和集成环境。

如何使两种编程措辞进行一体化开拓

首先,我们须要理解两个或多个运用程序如何相互通信(进程间通信)。

一种方法是利用 Alex Palaistras 在英国发布的令人生畏的库,可以在 PHP 和 Golang 进程(类似于 Apache mod_php)之间共享内存。
但是,这种库在我们实际开拓中对我们造成了很大的限定。

我们决定利用另一种更经典的方法,即利用 Socket/Channel 上的二进制流完成进程之间的通信。
我们选择这种方法是由于这种通信方法被利用了数十年,是一种可靠的通信方法,并且在操作系统级别上得到了很好的优化。

首先,我们创建了一个轻量级二进制协议,用于在进程之间交流数据并处理缺点。
在最大略的实现方法中,这种类型的协议是类似于 netstring 的实现,拥具有固定大小的包头(点击这里查看我们给出的例子),其包含每个包类型,大小和二进制掩码等信息,以便验证数据完全性。

在 PHP 方面,我们利用了 PHP 函数。
对付 Golang,我们利用了编码 / 二进制库。

我们乃至在创建协议上更进一步。
添加了直接从 PHP 调用Golang net / rpc做事的功能。
这个功能在开拓中非常实用,由于我们可以轻松地将 Golang 库集成到我们的 PHP 运用程序中。
你可以在我们发布的另一个名为Goridge 的 开源产品中看到这项事情的结果。

实现 PHP 高并发处理任务

一旦建立了通信,下一个目标便是最有效地将作业通报给 PHP 进程。
对付任何传入作业,运用程序做事器必须选择一个空闲事情程序来实行所需任务。
如果 worker / process 失落败或去世亡,我们会舍弃它并为他创建一个替代的进程。
另一方面,如果 worker / process 成功,我们会将其返回池中并使其可用于下一个作业。

在此需求的实现中,我们利用有缓冲的通道 来存储活动事情池。

终极结果是一个能够处理任意二进制作业的有效 PHP 做事器。

为了使我们的运用程序能作为 Web 做事器事情,我们必须选择一个可靠的 PHP 标准来表示任何 HTTP 传入要求。
想要知足此需求,我们只需将 Golang net / HTTP 要求转换为 PSR-7 (https://www.php-fig.org/psr/psr-7/meta/)格式,使其与大多数市场上的 PHP 框架兼容。

由于 PSR-7 格式是不可变的(一些工程师可能会指出它在技能上不可变),它迫使开拓职员编写不再将要求视为全局实体的运用程序。
这完备符合长期运行 PHP 进程的想法。
终极实现看起来流程如下:

先容 RoadRunner- 一个高性能的 PHP 运用做事器

我们最初的测试用例是一个用于后真个 API,它常常难以预测的涌现突发要求的次数比平时赶过许多倍的情形。
虽然在大多数情形下 nginx 可以帮忙处理,但是涌现 502 缺点的情形会频繁发生,由于我们无法预见到什么时候负载增加,做不到在负载增加之前快速地平衡系统。

在 2018 年初,我们将第一个 PHP / Golang 运用做事器支配到市场中以取代此设置。
效果吹糠见米,令人难以置信。
我们不仅完备肃清了 502 缺点的发生,而且我们终极将做事器总数减少了近三分之二,这为工程师们和产品所有者节省了大量事情本钱和做事器本钱。

到 2018 年中期,我们对该方法进行了优化,并在 MIT 容许下将其发布到 GitHub,并称之为 RoadRunner,它实现了其令人难以置信的速率和效率。

RoadRunner 如何帮助开拓

将 RoadRunner 引入我们的技能栈使我们能够利用中间件进行 HTTP 通信,在要求进入 PHP 之前启用 JWT 验证,处理 WebSockets 并将统计数据汇总到 Prometheus 中。
通过利用嵌入式 RPC,我们可以将任何 Golang 库中的 API 通报给 PHP 利用,而无需自定义驱动程序。
最主要的是,我们可以利用 RoadRunner 库来设置与 HTTP 不同的新做事器。
示例包括在 PHP 中运行 AWS Lambda 处理程序,创建可靠的行列步队利用,乃至将 GRPC 添加到我们的运用程序中。

到目前为止,在 PHP 和 Golang 开拓社区的共同帮助下,我们改进了调试工具,将其与 Symfony 框架集成,并增加了对 HTTPS,HTTP / 2,和 PSR-17 的处理。
我们提高了程序的稳定性,并且在一些测试中,程序的性能提高了 40 倍之多。

结论

有些人仍旧坚持认为 PHP 是一种缓慢,笨重的措辞,只能用来编写 WordPress 插件。
他们乃至可能会说 PHP 有一个限定:一旦你的运用程序变得比较大,你就必须切换到更“成熟”的措辞并取代之前的 PHP 代码。

对他们来说,我们想说“请三思”。
我们认为 PHP 的唯一限定是你自己给自己的限定。
你可以花生平的韶光从一种措辞跳到另一种措辞,试图找到知足你编程需求的“完美匹配”,或者你可以开始将措辞本身重新设想为工具。
像 PHP 这样的编程措辞的表面缺陷实际上可能是其成功的关键。
通过将其与 Go 等其他措辞配对,你终极可以创建比你自己利用任何一种措辞更强大的产品。

在利用 Go 和 PHP 进行稠浊编程一段韶光之后,我们可以自傲地说我们都很喜好这种开拓办法。
我们不打算放弃,而且我们将连续探求从这种双栈编程中得到最高效率的方法。

Spiral Scout 是一家领先的软件开拓公司,为旧金山和美国各地的客户供应从小型网站到大型分布式系统的定制产品的全栈开拓。
如果你有 PHP 或 Golang 干系项目,或者你碰着了运用程序在 PHP 中无法扩展或被过期的代码压缩限定,请通过spiralscout.com 与我们的团队联系。

RoadRunner Creator: Anton Titov, CTO, Spiral Scout

via: https://blog.spiralscout.com/php-was-never-meant-to-die-830de87915ee

作者:John W. Griffin 译者:CNbluer 校正:polaris1119

本文由 GCTT 原创编译,Go措辞中文网 名誉推出

本文由 GCTT 原创翻译,Go措辞中文网 首发。
也想加入译者行列,为开源做一些自己的贡献么?欢迎加入 GCTT!
翻译事情和译文揭橥仅用于学习和互换目的,翻译事情遵照 CC-BY-NC-SA 协议规定,如果我们的事情有陵犯到您的权柄,请及时联系我们。
欢迎遵照 CC-BY-NC-SA 协议规定 转载,敬请在正文中标注并保留原文/译文链接和作者/译者等信息。
文章仅代表作者的知识和意见,如有不同不雅观点,请评论排队吐槽