站长资讯网
最全最丰富的资讯网站

为速度而生:PHP 与Golang 的合体 —— RoadRunner

为速度而生:PHP 与Golang 的合体 —— RoadRunner

php入门到就业线上直播课:进入学习
API 文档、设计、调试、自动化测试一体化协作工具:点击使用

在过去的十年中,我们一直在为 财富 500 强公司 以及用户人数不超过 500 人的企业开发应用程序。 一直以来,我们的工程师主要使用 PHP 来开发后端。 但是两年前,出现了一些问题不仅严重影响了我们的产品性能,还影响了它们的可扩展性 —— 因此我们将 Golang (Go) 引入了我们的技术栈。

几乎同时,我们发现 Go 不仅允许我们创建更大的应用程序,并且能够将性能提高多达 40 倍。 有了它,我们能够扩展使用 PHP 编写的现有产品,并通过结合两种语言的优势来改进它们。

我们将通过大量的 Go 和 PHP 经验告诉你,如何用它解决实际的开发问题,以及我们如何把它变成一个工具,来消除与 PHP 死亡模型 相关的一些问题。

常规 PHP 开发环境#

在讲述 Go 如何改善 PHP 死亡模型前,先了解一下常规 PHP 开发环境。

通常,应用运行于 nginx 和 PHP-FPM 上。nginx 处理静态请求,而动态请求则被重定向给 PHP-FPM,并由其执行 PHP 代码。也许你用的是 Apache 和 mod_php,但是他们原理相同,运行起来只有细微的差别。

看看 PHP-FPM 是如何执行代码的。当收到请求,PHP-FPM 初始化 PHP 子进程,并将请求的详细信息转发给它,作为其状态的一部分(_GET, _POST, _SERVER 等)。

在 PHP 脚本执行期间,状态将无法更改,因此只能通过一种方式获取一组新的输入数据:清除进程内存并再次初始化它。

这种性能模型有许多优点。你不需要太担心内存消耗,所有进程都是完全隔离的,如果其中一个进程「死亡」,它将自动重新创建,并且不会影响其他进程。但是,当你尝试扩展应用程序时,这种方式会有缺点产生。

典型 PHP 环境的缺点和低效性

如果你从事 PHP 的专业开发,那么你就知道从哪儿开始创建一个新项目 —— 选择框架。它是一个用于依赖注入、ORM、转化和模板方法的库。当然,所有用户输入的数据都可以方便地放在一个对象中(Symfony / HttpFoundation 或者 PSR-7)。这些框架很棒!

但一切都有它的代价。在任何企业框架中,为了处理一个简单的用户请求或访问数据库,您必须加载至少几十个文件,创建许多类,并解析多个配置。但最糟糕的是,在每个任务完成后,您需要重置所有内容并重新启动:您刚刚启动的所有代码都将变得无用,在它的帮助下,您将无法处理另一个请求。把这件事告诉任何用其他语言编写的程序员 —— 你会看到他脸上的困惑。

多年来,PHP 工程师一直在寻找解决此问题的方法,他们使用了延迟加载技术、微帧、优化库、缓存等。但最终,您仍然必须放弃整个应用程序,重新开始 *(译者注:随着 PHP7.4 中预加载的出现,这个问题将得到部分解决)

一个 PHP 进程能处理多个请求吗?

您可以编写持续时间超过几分钟的 PHP 脚本(最多几小时或几天):例如 Cron 任务、CSV 解析器、队列处理程序。所有这些工作遵循一个模式:他们获取一条任务,处理完它,然后获取下一个任务。代码常驻在内存中,因此避免了额外的操作来加载框架和应用程序,节约了宝贵时间。

但是开发长时间运行的脚本并不是那么容易。任何错误都会杀死进程,内存溢出会导致崩溃,而且不能用 F5 来调试程序了。

自 PHP 7 后情况有所改善:可靠的垃圾收集器出现了,它变得更容易处理错误,内核的扩展可以避免内存泄漏。是的,工程师仍然需要仔细处理内存并记住代码中的状态的问题(有哪一种语言能让你可以不关注这些事情呢?)当然,在 PHP 7 中,惊喜并不多。

是否可以采用一种 常驻 PHP 脚本的模型,将其用于处理 HTTP 请求等更琐碎的任务,从而消除对每个请求都从头开始下载所有内容的需要?

要解决这个问题,首先需要实现一个服务器应用程序,该应用程序可以接收 HTTP 请求并将它们逐个重定向到 PHP worker,而不是每次都杀死它。

我们知道我们可以用纯 PHP(PHP-PM)或 C 扩展(Swoole)编写 web 服务器。尽管每种方法都有其优点,但这两种选择都不适合我们 —— 我想要

赞(0)
分享到: 更多 (0)
网站地图   沪ICP备18035694号-2    沪公网安备31011702889846号