惠新宸,百度PHP高级顾问,年二十有八,好追根究底,有不良嗜好, 幸性本善。乙酉年识互联网,丁亥年入雅虎,翌年入百度。虽性好安稳,然经变无数,唯常叹"人生,菠菜汤尔"。
大家好,今天我主要介绍是PHP在百度一个发展历程,最早的时候百度成立于2000年,2000年的时候,百度刚刚成立,刚刚在北大资源宾馆建立百度,直到2001年的竞价排名,我不评价这个产品怎么样,竞价排名当时是第一个采用PHP,在百度的PHP系统。从2001年到今年已经10年时间了,这10年时间百度PHP经历一些什么变化呢?
我们现在看到是百度,那天我自己脑子里想了一遍,当然不是全部,大家能够知道的一些用户产品,无线产品,商业产品。包括贴吧这个比较大了,还有最新的旅游。对于贴吧来说,前端可能是CUI,或者业务逻辑,一直到后来已经迁到PHP。我列出来这些产品,都是使用了PHP,还有没列出来也是使用了PHP的,很多。所以,如果说让我去介绍每个产品是怎么用PHP的,我觉得这个不太现实,我一共只有30分钟。
这30分钟我主要想跟大家分享的我们发现一些问题和怎么去解决,这些问题是大家都会遇到的。我们最早的时候,就像我刚才提到的我们一些,因为处于最高性能要求,以及对于PHP的不了解,以及对于外部我们可能觉得PHP很慢,所以我们以前的时候,这些大的访问量产品都是用C来做的。他可能在模板上用Cu-i来做展现,这样的方式大家都知道开发,调试,部署都很复杂,成本也比较高,门槛也比较高,招人也比较难招。
后来的时候我们就考虑是不是应该去换一个,当时应该考虑要是JAVA,或者是PHP。我们在C的时候,C-ui和后面进程去通讯主要是Nsheader和mcpack,类似于上面一些打包传输的方式。我们为什么选了PHP?第一高性能,快速开发要求。我这说高性能,可能下面有一些工程师就笑了,你PHP讲什么高性能。我说的这些高性能是在相对情况下高性能,当我们WAP应用程序不仅仅局限PHP,瓶颈更大在于数据和文件,以及这些IO方面,在这些方面来说,PHP性能已经足够了。
那么开放开发就不用说了,PHP不需要编译,不依赖于环境,我所改即所建,改了就能看到,这个调试开发过程非常快,这是一个优点。稳定性,路棒性,安全性,怎么讲呢?有一个玩笑,我跟我们百度几个同学去聊天,他们就抱怨,PHP工程师真的是这个质量层次不齐,再烂的PHP工程师写出的代也能跑,跑完了也正常。这是从一个方面,可能他的本意是说我们招聘有一部分人水平本来不一样。但是从另外一个方面,也体现出来PHP一个特点是什么呢?稳定,鲁棒性很强。再烂,再不懂PHP的新手去写,你也不会把它写垮掉。
说到这里我有一个小问题,大家知道怎么PK掉一个PHP进程吗,最简单的方式。其实这个问题还挺难的,我跟我的朋友讲,你们说怎么PK掉一个PHP进程,我需要调试,其实很简单你写一个无线递归下去就会打掉。PHP有很多安全措施,比如我们颇为被人争议GPH选项,打开之后会对客户进行过滤。还有PHP对输入做各种各样的转换验证,这方面PHP对安全性考虑也是多的,当然还有是不建议打开的,那样的话更安全。
灵活和丰富的语法就不用多说了,一个PHP怎么写,不需要特定格式,随意性也非常强,功能当然也很多了。他应用面这么广,自然是一个例证。良好的运行在Linux,可扩展C/C++。PHP经典搭配是没有问题的,我们都知道,我们当时不选择JAVA一个原因,还有一方面考虑,JAVA那套开发环境比较复杂,重启一下需要30-40秒。更重要一点可扩展,因为我接下来讲的问题就是从可扩展来的,我们的优化方案。
当时我们就想因为PHP应用很多,一个开源东西,有很多方便第三方房展,我们经常用的PDO,都是扩展的方式,并且他的扩展也非常容易开发,网上有一堆教程,只要你照着教程做一遍。因为PHP对扩展做的很好,一行命令把自己代码写进去,就是一个很完整的扩家,一个扩展就能用。易部署,易调试,更不用说了PHP直接拷贝,拷贝到哪都能够运行,不需要依赖系统的共享库,不会因为库的挂接处而出现问题,调试也很容易调试,最经典的方式不停调试,我们还有一个PHP调试技术手册,我相信在座很多人都看过,那里面介绍一段做单布跟踪调试,这样的调试今天在这里讲,效率往往还不如直接调试快,当时只是一种尝试,或者说一种探索去跟大家分享调试的技术。
展现逻辑分离这个也很重要,对于PHP来说,本身生来就是做WAP开发的,可以把PHP代码嵌入到WAP里面去,这个非常适合于做外部开发的。入门快,刚才也提到了,我们现在招聘新来这些大学生其实他以前可能是做JAVA,是做C,一周时间就可以开始写。所以,入门非常快,社区活跃,这里我要提一下,在我们百度就我所知有400多名做PHP开发,我们这400多名工程师都在一个群里,大家聊天,问一个问题立马就有人来回答你,这只是在百度社区,更不用说开源社区活跃程度了。
从这些方面我们就觉得PHP替换现在C的方式是可行的,于是我们就有了经典的方案,就像我这大家看到的,用户浏览器经过的分发,分发以后后台就是这样一个用PHP脚本,下面可能有一些扩展,再下面就是PIP,后面数据,因为这块对于开发来讲,我这块主要从贴吧角度来讲,它是服务其逻辑数据还是用一些比较快的,还是以前那套老东西,只不过把UI这一块做到PHP,当然其他系统不是这样。
这个时候后台像Web Services等等提供这种数据,给PHP脚本,这是一个现在这样一个,应该说比较经典PHP开发模式,或者在我们百度来说,主要还是以这种方式,PHP只是做展现。这样的情况下有一个问题,什么问题?比方说你是一个PHP工程师,你的上级交给你一个任务,你去写一个什么样的系统,你把它部署下去。你刚来很有信心,没问题我去做,你用了一周时间写出来,写完之后你用一天时间把环境搭起来,把代码放上去,四台服务器需要共享,把这些东西都用完你可能用一周半时间,没有问题你这个做的很好,你这个东西也很正常,架构也设计很好。
现在这样的问题还有100个你怎么办?难道你再去部署100次,这不行吧。另外你做的东西放上去之后,你可能出去玩了,下班回家了,那怎么监控呢?谁去监控呢?这也是现在单个产品线都要遇到的问题。还有一个问题资源流量陡增,比方说你这个产品挺好的,日均PV10万,突然一天涨到100万,大家都知道去年的时候69圣战,贴吧经过一次所谓69圣战,流量爆增了多少不知道,但把服务器给压死了。
那么遇到流量陡增怎么办,不能说现在这个产品10万,前台上了100台前台机,我告诉老大,我这个流量某一天陡增10谁信啊,成本也受不了这也是一个问题。规范和标准,这是最头疼的,我到百度以后参与了很多规范制定,也会提很多意见,我每次做这些事情的时候我都是信心慢慢的,我觉得做完之后大家看了之后会去用,会去学,可能咱们普遍共同语言就会多一点。但是发现你标准规范制定出来没人理,这就是规范一个怎么去执行,当然这个问题很难了,另外一个问题,这也是我们现在遇到的问题,我们有编码规范,有部署规范,有目录规范,但是没有办法推卸,没有一个东西去强制让他们这么去做。
还有防攻击容灾,你有4台前端机,仅仅4台,某个不知名相关组织弄了100多台僵尸肉鸡去压你,你有什么办法,没有办法,你只能被攻击。还有一个问题,我们现在产品线这么多,每个产品线使用的框架各不相同,开发模式各不相同,这就造成他们都是异构的,异构会有什么问题,OP会很郁闷。OP遇到每个产品线,有的配置文件在这放,有的配置文件在那放,就像我们UC就得为各种各样框架命名规则开发一个不同类库。快速开发我就要求我的基础设施足够丰富,我基础设施足够丰富的情况下才能做到快速开发,我框架功能要很强,这样开发才会快。
但是你框架功能很强就带来一个问题,你代码多,就慢,PHP就这样,怎么办,这也是一个根本矛盾。这些问题有没有解决方案呢?当然是有的,要不然我也不会拿出来讲了。在百度现在对于前面的问题,比方说运维,部署和容灾,一些流量陡增这些问题怎么办呢?看最右边一个Bae,就是百度应用开发平台,在这个上面会做一些类似于Gae,Sae这样的东西,目前来说只是百度内部用。这样的话当我用了这个东西之后,我们开发者不再要求需要关心资源,也不需要关心被攻击,或者流量陡增,这个我待会还会讲。
我们在PHP这层加了一个小螃蟹,它的名字叫做AP,我待会会介绍AP是什么样东西。然后在脚本和PHP之间又加了一层Odp,又是什么东西?这三个就是解决我刚才提到哪些问题。Bae,我刚才提到是来解决我们刚才说的那些问题,比方说我资源怎么管理,流量陡增没法应付了怎么办。Bae把所有资源统一调度起来,提供一个很大平台给你,你其中只用一部分,他会把冗余资源调配节给你,满足你陡增的资源需求。
集群化还有一个问题是防攻击,我现在是三大服务器有人来压我了,他拿100台肉鸡来压我,没有关系,我们百度后面还有1千台服务器呢,上,你再来压。如果他真的强大到拿1万台,1千万台来压你,这样成本在国内很难做到。所以,这样情况下能解决我们刚才所说小规模攻击,因为你攻击我就可以迁移,我可以自动迁移。
流量陡增也是一样道理,太多。接下来就是今天我要介绍的重点,就是怎么解决沉重的框架问题。我们现在用的很多框架,各个公司开发都会有用框架,也有自己开发框架。在做开发框架的时候大家都会遇到一个问题,这个框架要不要做的这么重,为什么要做的重呢?因为你工作要提供的多,要提供路由,提供搜索引擎,还有ORM等等这样东西。我提供这么多东西,必须有这么多的代码,我有那么多代码,就那么多逻辑,就有一个结果慢了下来,怎么取舍呢?
对于百度来说,我们现在解决方案出来之前流行两种开发模式,一种比较成熟E框架,或者ZF框架,还有性能要求比较高的,会使用我们百度自己开发的B-Gou框架,只做路由,是一个轻量级框架,是一个非常非常轻量框架,来满足性能问题。有没有一个解决方案做他们俩的取舍呢,下面有一个扩展化。
什么是扩展化?在座都知道PHP扩展,如果关心这个肯定会知道,可能也有不知道同学,我就提一下什么是PHP的扩展。PHP本身是用C语言写的,你所编写的PHP脚本到最后都是通过C代码执行的,这时候PHP还提供一种方式可以直接写用C来写一个共享库,动态的共享库,把它加载到PHP中,通过这种方式让你业务模式以C模式存在在PHP当中,这个模式就叫扩展,PHP提供一个很强大模块来支持你自己PHP扩展。
我刚才提到了其实问题也就很明显了,我们需要用一个PHP扩展去做一个很重的PHP框架。还有一个要提的,什么样的情况下我们应该使用扩展,还有一个问题扩展为什么会快,这两个问题,有些看似很简单问题,其实要想起来还是挺难的。第一什么样的情况下我们可以使用扩展,我们有两种方式是需要扩展,第一种方式我们有一些,比方说已经成熟的C库,我们PHP许多办法直接用,我必须用一个扩展把它桥接过来,这种情况下需要使用PHP扩展。
还有一种情况我对CPU密集型的东西,比方说我有一个算法,或者我有一个很复杂,很复杂的加密算法。这个算法如果我用PHP写的话非常慢,对于这种CPU密集型的东西,我是可以把它扩展化用C来实现,这样的话能提高性能,就这两种方式要去使用PHP扩展。PHP扩展为什么会快呢?这里我要提一下FaceBook极致,去年11月份极致把一个应用性能提高到4倍,他是怎么做到的呢?我们大家听各种各样报告,是把PHP编译成C++,他这个编译其实不是说我根据你的逻辑找到对应的C代码进行编辑,他做的更多是把这个符号解析给拿掉了。我们在PHP里面,我们的变量,我们的函数都是存储在一个一个关联数字结构里面,他这个结构设计足够精妙,确实也花很大心思去设计,但是当我们使用一个变量,或者一个方式的时候,都需要从这个表里面去查的,这个过程是非常耗时的。
所以,PHP性能绝大部分低也是这个关键。PHP就把能在编译期间确定的符号就把它直接替换掉,相当于我们C程序编译的时候把符号直接换成二进制地址的一样,就是一个符号回天。这只是一方面,还有一方面为什么扩展会比PHP快?这个我们抛开一切问题,一切IO,抛开一切内存存储我们来算一个简单算术题,一个1G赫兹CPU能编织多少,这也是PHP比较慢一个原因。
比方说一个简单ICOU(音译),如果你用C代码来写,直接写ICOU2也可以,如果PHPICOU2先编译,第二部分先分析这个PHP,找到对应PHP调用,这个时候有三种情况,这时候拿到一个指令进行执行,当执行这次指令的时候可能会发生多次调用。我一个简单的ICOU可能在PHP最后执行的时候,可能有5次以上函数调用,这个就慢了,扩展化就可以避免这些问题。
我们Ap就是一个全功能MVC框架,是用扩展来实现,也就是利用C语言去写的一个PHP扩展。这个地方又有一个问题,我们扩展一般也两种理由去写扩展,扩展还分两类,第一类就是说一个简单我的业务逻辑都是用C代码去做的,我只是简单从PHP脚本拿到数据,把处理结果反给PHP,我基本上不怎么使用Ap。第二个扩展就是负载PHP扩展,就是Ap,用了大量API,提供相应存量,或者是一些资源给PHP脚本让用户去进行使用。对于用户来看,他可能觉得这跟PHP脚本使用起来一样,他用Ap框架,如果我用PHP脚本使用一个类似框架,把这个替代掉,PHP写的这个框架换上去对他是透明的。第二类框架复杂性要远远高于第一类型,他要遵循PHP引用技术,要遵循PHP一些比较特殊约定。
当然,这些不是说PHP的问题,可能有一些历史原因。种种这些你都是要去遵循的,这个复杂度确实比第一种高一些。
联系客服