加入收藏 | 设为首页 | 会员中心 | 我要投稿 济南站长网 (https://www.0531zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

Badoo 告诉你切换到 PHP7 节省了 100 万美元

发布时间:2016-10-01 09:17:52 所属栏目:PHP教程 来源:oschina
导读:副标题#e# 介绍 我们成功的把我们的应用迁移到了php7上面(数百台机器的集群),而且运行的很好,据说我们是第二个把如此规模的应用切换到php7的企业,在切 换的过程我们发现了一些php7字节码缓存的bug,庆幸的是这些bug现在已经被修复了,现在我们把这个激

鉴于我们不得不重写大量的代码,而且还要依赖于runkit和uopz这种不知道有没有问题的项目。很明显,我们有了结论:我们应该重写我们的代 码,而且要尽可能独立。我们也承诺将尽一切可能来避免今后发生类似的问题,即使我们最终切换到HHVM或任何类似的产品。最终我们做出来了自己的框架。
我们的系统名为“SoftMocks”,“soft”意思是纯php实现,未使用扩展。该项目目前是一个开源的php库。 SoftMocks不跟PHP引擎绑定,它是在运行中动态重写代码,功能类似于Go语言的AOP!框架。
以下功能在我们的代码里已经测试过:

  1. override类方法

  2. 覆盖函数执行结果

  3. 更改全局常量或类常量的值

  4. 类新增方法

所有这些东西都是用runkit实现的。动态修改代码使项目临时变更有了可能性。

我们没有更多篇幅来讨论关于SoftMocks的细节,但我们计划写一篇关于这个主题的文章。 这里我们给出一些关键点:

  • 通过重写中间函数来适配原有的用户代码。因此所有的包含操作将自动被中间函数重写。

  • 在每一个用户定义的方法内都增加了是否有重写的检查。如果存在重写,相应的重写代码就会被执行。 原来直接函数调用的方式将被通过中间函数调用的方式所替换;这样内嵌函数和用户自定义函数都能被执行到。

  • 对中间函数的动态调用将覆盖代码中变量的访问权限

SoftMocks 可以和 Nikita Popov’s 的 PHP-Parser 配合: 这个库不是很快(解析速度大概比token_get_all 慢15倍),但他的接口让你绕过语法解析树,并且包含了一个方便的API 用来处理不确定的语法结构。

现在让我们回到本文主题:切换到PHP 7.0版本。  当我们通过SoftMocks把整个项切换过来后,我们依然有1000多个测试需要手动处理。你可以说这还不算太差的结果,和我们在开始时提到的 60000个测试相比的话。 和runkit相比,测试速度没有下降,所以SoftMocks并没有性能问题。 为了公平起见,我们认为uopz 明显的快很多。

尽管PHP7包含了许多新功能,但是仍然存在一些与老版本兼容的问题。首要的解决办法是阅读官方的移植文档,之后我们会马上明白如果不去修改现有代 码,我们将会面对的不仅仅是在生产环境中遇到致命的未知错误并且由于升级后代码的改变,我们无法在日志中查找到任何信息。这将会导致程序无法正常运行。

Badoo中有许多PHP代码仓库,其中最大的有超过2百万行代码。此外,我们还使用PHP实现了很多功能,从网站业务逻辑到手机应用后段再到集成 测试和代码部署。就目前来说,我们的情况很复杂,毕竟Badoo有很长的历史,我们使用它已经快十年了,最不幸的是仍然有采用PHP4的环境在运行。在 Badoo中,我们不推荐用‘just stare at it long enough’的方式来发现问题。一套所谓的’Brazilian’系统将代码部署在生产环境,你需要等待直到它发生错误,这很容易引发大面积用户在使用 中遇到业务上的错误,使其不明原因。综上所诉,我们开始寻找一种方法能自动发现不兼容的地方。

最初,我们试图用IDE的,这是开发者中很受欢迎,但不幸的是,他们要么不支持PHP7的语法和特征,要么没有函数可以在代码中找到所有的明显的危险的地方,发现所有明显危险的地方。进行了一些研究(如谷歌搜索)后,我们决定尝试php7mar工具,它是用PHP实现一个静态代码分析仪。这PHP7工具使用起来非常简单,很快工程,并为您提供了一个文本文件。当然,它不是万能的; 找特别是精心隐藏的问题点。尽管如此,该实用程序帮助我们铲除约 90%的问题,大大加快和简化了准备 PHP7 的代码的过程。

对我们来说,最常遇到的和潜在危险的问题是以下内容:

  • 在func_get_arg()以及func_get_args的行为变化()。在PHP的第5版本中,这些功能中的传输的时刻返回参数值,但在 七个版本发生这种情况的时刻时func_get_args()被调用。换句话说,如果函数内func_get_args前参数变量的变化()被调用,则该 代码的行为可以由五个版本不同。同样的事情发生时,应用程序的业务逻辑坏了,但并没有什么在日志中。

  • 间接访问对象变量,属性和方法。并再次,危险在于,该行为可以更改“静默”。对于那些寻找更多的信息,版本间的差异进行了详细的描述在这里。

  • 使用保留类名。在PHP7,可以不再使用布尔,整型,浮点,字符串,空,真假类名称。,是的,我们有一个空的类。它的缺席实际上使事情变得更容易,但因为它常常导致错误。

  • 使用引用许多潜在的问题的foreach结构被发现了。由于我们试图早不改变迭代数组中的foreach或虽在其内部指针数,几乎所有的人都表现在版本5和7相同。

剩余的不兼容性的情况下也很少遇到了 (像 ‘e’ 修饰符在正则表达式),或他们固定的一个简单的替换 (例如,现在所有构造函数应该被命名为 __construct()。类名称不允许使用)。
但是,我们即使在开始修复代码之前,我们很担心,一些开发商做一些必要的兼容性变化,其他人会继续写不符合 PHP7 的代码。为了解决这一问题,我们把 pre-receive 钩在已更改的文件 (换句话说,确保语法匹配 PHP7) 上执行 php7-l 在每一个 git 存储库中。这并不能保证不会有任何兼容性问题,但它不会清除主机问题。在其他情况下,开发人员只是不得不变得更加专注。除此之外,我们开始在 PHP7 上运行的测试整个集并与 PHP5 的结果进行了比较。

此外,开发者不允许使用任何PHP7的新功能,例如,我们没有禁止老版本的预接收钩子 php5 -l。这允许我们让代码兼容PHP5和PHP7。为什么这个很重要?因为除了php代码的问题之外,还有PHP7极其自身扩展的一些潜在的问题(这些都可 以证实)。并且不幸的是,不是所有的问题都可以在测试环境中重现出来;有一些我们只在产品的大负载时才见过。

实践出真知

(编辑:济南站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读