再谈 PHP 未来之路
前段时间我写过一篇博文《phper:敢问路在何方》,分析了 PHPer 的困境以及 PHP 程序员的学习、进阶突破之路。同时我在知乎上也发过类似的提问。从大家的评论和回答看,大体分为以下几种情况:
认为 PHPer 的困境跟 PHP 语言无关,而取决于程序员自身的水平、能力;
认为 PHP 语言本身就不行,只适合初创企业、外包公司使用,程序员不应该从事 PHP 开发,应当选择更有前途的如 java、go 等语言;
认为 PHP 生态不行;
我在前面那篇文章中重点讨论了程序员(PHPer)面临的困境以及进阶之路,就 PHP 这门语言本身并没有做过多分析。文末,我得出的结论是“PHPer 的唯一出路是不要把自己定位成 PHPer”,这句话从狭义来理解,确实对 PHP 本身抱有悲观态度,但从广义理解,任何一个程序员,无论他使用的主编程语言是什么(哪怕是 java、c++),要达到一定的高度,就不能把自己定位成那门语言的专职猎手。
写完那篇文章后,看到一些留言,以及知乎的一些回答,我便陷入了对 PHP 语言本身的思索:这门语言现在到底处于生命周期的哪个阶段?其定位到底是怎样的?诸如 PHP7、Swoole 的出现到底能给 PHP 带来怎样的变化?
这些问题又让我失眠了一整夜,现在,我就自己的思考写下此文。
当我们谈论语言的时候,我们到底是在谈论什么?
当我们拿 PHP 和 java 进行比较的时候,我们往往就两门语言本身进行比较,如一个是弱类型一个是强类型,一个是数组打天下一个是各种数据结构,甚至连花括号是不是换行写都会被讨论一番。但它们真正的区别并非这些。
当我们谈论一门语言的时候,我们是在谈它的生态。
“生态”一词在百度百科上的解释是:“生态一词,现在通常是指生物的生活状态。指生物在一定的自然环境下生存和发展的状态,也指生物的生理特性和生活习性。生态(Eco-)一词源于古希腊字,意思是指家(house)或者我们的环境”。
生态具有如下特点:
生态是系统,由多个部分组成的完整体;
生态是开放系统;
生态具有动态平衡性;
维持其动态平衡的是源动力,源动力一旦消失,生态即消亡。例如地球生态系统的源动力是太阳能;一旦太阳消失,地球生态则不复存在(想想《流浪地球》);
一种生物的生存状态不取决于生物自身,而取决于环境,就如恐龙的灭绝并非恐龙自身退化了,而是环境改变了(或者说恐龙的进化赶不上环境的变化)。
一门语言的兴衰不取决于它自身,而取决于环境,具体来说是环境中源动力的强弱。
PHP 应 Web 而生,考查其兴衰得考查互联网的发展。
一般认为互联网大致经历了三个阶段:
阶段一:Web1.0 时代,传统的内容网站,如企业官网、行业门户网站等,网站自身产生内容,用户仅查看内容;
阶段二:Web2.0 时代,用户参与内容的创建,如论坛、博客。阶段一和阶段二都是内容为主,服务为辅(虽然内容的产生方式有所不同);
阶段三:移动互联网时代,信息流、内容与服务并存;
以上三个阶段的演化中,用户参与度越来越高,交互方式越来越丰富,网站流量越来越大。
阶段一和阶段二是 PHP 的黄金时代,从阶段二开始悄悄发生变化,而到了阶段三,PHP 的黄金时代基本结束。
PHP 这门语言的特点是“简单、实用”,入行门槛极低,一个编程小白,一周入门,两天出个网站。一个典型的例子,在数据结构上,不像其他语言有 Array、List、Map、Set,PHP 一个 Array 搞定所有的情况。
PHP 的这种“简单”是通过牺牲性能为代价的。由于需要简单,不能有各种类型限制,PHP 必须是动态语言;由于需要简单,能封装则封装,一个 file_x_contents 搞定文件(甚至是网络)读写(该函数是一次性将文件全部加载到内存中,很多人开发不考虑其局限性而用在所有场景,导致内存溢出);由于 Array 承包了所有集合型数据结构,其底层需要做各种处理不说,业务层也无法自主选择更合适的数据结构做针对性的优化(虽然后来 SPL 提供了一些基本数据结构)。
PHP 的这种“简单”还牺牲了另一样东西:程序员的专业素质。PHP 程序员根本不需要去了解真正的 Array 和 List 有什么区别,也不需要去管数据流、缓冲区。从长期来看,这一点是致命的,它使得 PHP 生态中的重要一环很脆弱,很可能是导致 PHP 最终衰落的真正因素。
在 Web1.0 时代,一方面内容产生者是网站自身,另一方面人们只能通过桌面浏览器上网,这些因素使得这个阶段绝大部分公司根本不会遇到高并发等性能问题,而且业务的简单性使得单体应用足以应付一切,因而这个阶段 PHP 的缺陷根本不足为患。于是,PHP 的优势(简单上手、快速开发)让这门语言大行其道,什么 JSP、ASP,根本不是对手。那个时期,人们谈论 java、C# 时,基本是在谈 ERP,只有 PHP 才是 Web。
到了 2.0 时代,论坛、博客、SNS 的出现,使得用户创建内容成为可能。由于用户的积极参与,网站服务器流量相对于 1.0 时代有了突增,特别是 SNS 的信息流特性,使得服务器面临相当的挑战。不过由于人们仍然是通过 PC 浏览器上网,在一定程度上限制了使用频率。这个时期,一些大公司针对 PHP 的性能缺陷做了自己的改造,如新浪的各种 c 扩展(yaf、yar 等),facebook 的 HVVM。
在这两个黄金时代,PHP 世界涌现了大量的经典开源项目:WordPress、ecshop、Magento、Discuz、Thinkphp、Yii 等。
彻底结束掉 PHP 黄金时代的是移动互联网的到来。iphone 改变了世界,也改变了 PHP 的命运。
移动互联网时代,人们随时随地都能上网,而且几乎每人一部手机,这带来的直接效果就是 Web 使用需求出现了数量级的增长。另外,移动互联网时代的另一个特点是内容+服务的一体化,网站不再只是提供内容,还提供服务(如各种 O2O),因而在使用频率、交互体验上的需求都大大增强。
举个例子,在 1.0 时代,浏览器和服务器根本不需要建立长连接,2.0 时代,由于信息流的出现,要求有轮询机制,但由于当时无论是浏览器还是 PHP 都不支持长连接,人们想了各种奇淫技巧来实现轮询。移动互联网时代,浏览器端有了 WebSocket,悲剧的是 PHP 本身却不支持 WebSocket(由于 PHP 的运行机制是一次请求后进程就结束了,在语言核心层面无法提供 WebSocket 机制。要想在核心层面支持 WebSocket,必须改造 PHP 的整个运行机制,这几乎是不可能的)。
至此,一方面 PHP 的性能问题成了致命问题,另一方面 PHP 各种“方便”的机制(如由 php-fpm 代替 PHP 脚本自身的常驻进程)满足不了新的场景需求,反倒成了桎梏。
在移动互联、万物成网的大背景下,微服务应运而生。一般认为微服务本身并非新的概念,早期的 SOA 就有其身影。不过我们谈论一个概念本身到底新不新没有意义(就好比有人认为中国的勾三股四弦五的发现比希腊的毕达哥拉斯定理要早,于是认为该定理是中国人发现的;有人认为中国的阴阳学说含有二进制思想,便认为二进制是中国人发明的),重要的是一个概念何时形成了一套完整的体系,以及是如何来解决实际问题的。
微服务架构是相对单体架构来说的。我们先说说微服务的缺点:服务间调用关系复杂、难治理、问题排查复杂、分布式事务问题等。既然有这么多缺点,为啥微服务架构当今能大行其道?原因在于单体架构解决不了当今面临的问题:巨大而复杂的业务群、高并发、高可用的系统需求。
微服务给 PHP 带来什么呢?
当我们将单体架构拆解成一个个小的服务的时候,我们来考查一下编程语言的选择,看看 PHP 还是不是最佳选择:
首先微服务要轻量化。
其次服务要被多个业务端调用,其运行要足够快。
另外当服务间通信非常频繁时,通信协议要保持高效,此时 HTTP 协议并非最佳,很多公司倾向于 RPC 协议。
后端服务相对于前面的业务层来说,变动频率相对要低一些,因而可以适当地牺牲一些开发效率。
要有较成熟的生态和框架支持(成熟的服务治理生态)。
从上面几点来看,PHP 并非最佳选择:
传统的 PHP 架构是 nginx + php-fpm + PHP script,显然不够轻量,成百上千个服务都驮着这么厚厚的一层壳,显然存在资源浪费问题。
PHP 作为脚本语言,由于存在脚本解析消耗,运行速度上赶不上 java、C++ 等静态语言(不过在 PHP 引入 opcode cache 后情况得到了很大改善,而且对于 Web 来说大部分时候都是 I/O 密集型操作,语言本身的性能影响对于绝大部分的公司来说并非主要问题————不过一方面心理学研究表明人类的认知并非完全理性的,人们认为 PHP 比 java 性能差那就是差,不管实际差多少(这就好比我们认为大品牌的东西一定比小品牌的好一样,编程语言的世界也有品牌效应))。
PHP 核心没有提供现成的 RPC 方案,但可以通过扩展解决,这不是问题。问题是传统的 PHP 架构(nginx + fpm + script,一次请求完成后工作进程即结束)并不能很好地应用 RPC 通信的优势。
在生态和框架上,Swoole 貌似是个不错的选择,不过 Swoole 的微服务生态目前尚不成熟。
大部分的 PHP 程序员对服务化比较陌生(以及对性能、可靠性等非功能性需求的普遍漠视),上手较慢。
综合考虑,大部分公司进行服务化的时候,会选用主流静态语言(java、C++ 以及后起之秀 golang 等)做服务,PHP 更多是来开发中间的业务聚合系统来调用这些服务。
至此,PHP 走下“神坛”,官方那句“PHP 是有史以来最好的语言”永成过去式。
不少人认为,PHP7 和 Swoole 给 PHP 在服务化时代带来新希望,因为理论上,上面提到的问题 PHP7 和 Swoole 都能较好的解决。
首先 PHP7 带来了极大的性能提升,而且引入强类型、严格模式等新特性,使得 PHP 越来越像强类型语言。其次 Swoole 的出现使得 PHP 很容易像 java、go 那样实现常驻进程服务而不需要依赖 nginx + php-fpm,那么 由“nginx + php-fpm + script” 的 CGI 模式在服务化时遇到的问题也都得到了很好的解决。
那么,PHP7(以及即将到来的 PHP8 的 JIT 特性)和 Swoole 能给 PHP 带来第二个黄金时代吗?
个人认为不能。还是那句话,当我们谈论语言时,实际上是在谈论生态。
编程语言的生态系统中有个很重要的角色:开发者群体。PHP 自出生时的目标就是“简单、强大、实用”,实现了高度的封装,让开发人员专心面对业务。这对工程是好事,对开发人员的成长(以及开发人员生态)来说却不是。绝大部分的 PHPer 都是业务工程师,几乎所有工作都是各种业务的 CRUD,很少涉及稍底层的东西,也鲜有关乎设计、架构的。在我周围的,以及面试遇到的,大部分人根本不了解设计模式、数据结构、算法、计算机原理,写出来的代码也仅仅是实现了业务的功能性需求,很少考虑非功能性需求。另外,在传统 PHP 的 CGI 模式下,PHP 脚本并不需要考虑自我恢复、自我保护能力如限流、重试、异步等这些在微服务架构下必须考虑的东西。
另外,由于大部分 PHP 程序员平时都是使用 MVC 框架提供的功能实现 CRUD,较少进行对象建模(PHP 并非生来就是面向对象语言,OO 特性是后面加进去的),导致大部分有相当工作经验的 PHPer 的建模能力都很弱,而微服务的一个重要工作就是对单体项目按业务领域进行拆分、建模,这对 PHPer 来说是个相当大的挑战。
一个结果是,PHP 程序员普遍专业素质都很弱,根本胜任不了复杂的系统架构————这里的复杂性有两个层面:技术层面和业务层面。
PHP7 和 Swoole 虽然弥补了语言自身的短板,却弥补不了生态中非语言部分的缺陷。有人认为这些缺陷是历史造成的,不能代表未来。万物的生命都是连续的、演化的,历史往往决定了未来,虽然身处现在的我们察觉不出。既然 PHP 生态在解决复杂系统问题时不具备优势,那么公司就会自然而然地选择其它更具优势的生态系统,自此便形成恶心循环(现实中我们遇到的情况是,很多使用 PHP 作为主要语言的中小公司业务规模上来后,不得不从外面聘请架构师,这些架构师大部分都是 java 出身,到公司第一件事就是强行 PHP 转 java)。
有人可能觉得我是 PHP 黑,毕竟我也没有做过严格的调查来得出上面的结论。但我们可以通过一些现象管中窥豹:
我们可以很容易找到用 java、C++ 写的设计模式、数据结构与算法方面的畅销书,却几乎找不到 PHP 的。
我们在博客园、CSDN 等技术博客上能看到大量 java、C++、C# 程序员的博客,却很少看到 PHP 的。
我们看到技术博客上大量 java 程序员在谈论各种设计、服务、“三高”架构,却很少见到 PHP 的。
我们能看到 java、C++ 程序员到处参加各种技术峰会,却很少见到 PHPer(除了 PHP 自己的专项会议)。
你会觉得仅凭 PHP7 与 Swoole 能让几乎不谈设计模式、不研究数据结构与算法、很少写博客、很少参加峰会的 PHPer 们开拓出一片服务化的新天地吗?
PHP 曾经辉煌过,在移动互联网之前,在单体为王的时代,就像 Delphi 在 Windows 桌面应用为王的时代取得的辉煌一样。现实的需求是语言生态系统的源动力,当需求发生不可逆转的改变时,午日终将西傍。
那么,接下来的问题是:PHP 会很快没落吗?
这个问题实际是在问:如今 PHP 是否还在某些场景下具有优势(即是否还存在现实需求这一源动力)?
PHP 的优势是简单、门槛低、实现功能快捷,很适合如下场景:
- 业务、系统相对简单,无需服务化;
- 对性能不是很敏感;
- 需要快速实现、快速迭代;
在上面这些场景下,微服务(以及 java、C++ 等静态语言)的优点并不能弥补其缺点,因而推荐使用单体架构或者简单的服务化(仅仅进行主要服务拆分,并不引入复杂的服务治理体系),这种情形下 PHP 的优势就显现出来了。一般中小公司正是满足上面的场景,因而我们发现即使是在移动互联网时代 PHP 辉煌不再,但仍有大量中小公司采用 PHP 作为核心开发语言。
另外一个事实是,由于所有的大公司都是由小公司成长来的,在公司规模尚小的时候,他们大多也是采用 PHP 作为核心语言的,规模成长后,虽然 PHP 的各种短板阻碍了系统的发展,但由于已经有大量的 PHP 项目,完全重新用其他语言开发一遍不太现实,因而他们会采用各种优化手段,比如编写 PHP 扩展或者将 PHP 编译成某种静态语言(如 C++),或者将单体项目中的某些核心功能拆解成服务,单体项目调用后端服务接口————这种情况下,PHP 项目成了粘合层。
将 PHP 作为粘合语言的不光是因为历史遗留问题,还有不少公司新项目也会采用这种架构,这样既充分利用了 PHP 的开发效率(因为粘合层往往比较靠前端,需求变动较频繁,开发效率是必须要考虑的重要因素),也保证了核心服务的性能。
那么,接下来的问题是,作为快速原型语言和粘合层语言,有没有其他语言比 PHP 更具优势?
至少国内不用谈 Python 和 RoR(在国外这两者在 Web 开发上的占有率也不及 PHP),Python 程序员的重心已转大数据、人工智能了, RoR 至少在国内一直不温不火,在程序员的招聘上比 PHP 要难很多。
nodejs 曾经被认为是 PHP 的最大对手,一个很大的原因是人们认为如果一个公司使用 nodejs 作为后端语言,那么他只需要一样技术栈(前后端都是 js 程序员,而 js 程序员和 PHP 一样一抓一大把),体现了莫大的成本优势。但事实是 nodejs 并没有对 PHP 造成根本威胁,未来也不太可能会,原因是持上面观点的人认为统一技术栈就一定能节约成本,但这是个伪命题。一门语言具有解决某个问题的能力不代表人们就一定会拿它去解决问题,就好比 PHP 也能进行 socket 编程,但很少公司在生产环境大规模使用 PHP 编写服务器。js 天生就是 Web 前端语言,因而绝大部分 js 程序员都是一直做前端开发的,而前端开发和后端开发模式上有很大不同。前端在很长一段时间都是面向 DOM 编程,即使是有了模块化、React 这些新玩法后,前端开发的重心仍然是事件驱动的交互式编程。后端开发的重心在于建模(即使不对业务进行对象建模,也至少需要面向数据库进行数据建模)以及业务逻辑的实现,做后端开发,数据库、Linux 服务器是绕不开的,而这两者恰恰是大部分前端程序员所缺乏的(换句话说,要招一个既很熟悉前端开发又很熟悉后端开发的 js 程序员是非常难的)。结果就是,招一个 js 程序员用 nodejs 开发后端系统,其成本远大于招一个 PHPer。
因而,PHP 在未来可预见的很长时期内不会没落,它会作为中小公司的快速原型语言和大公司的粘合层语言长期存在。
我的另一个有趣的结论是:Python、Ruby On Rails、nodejs 这些语言虽然不会对 PHP 造成根本威胁,但会跟 PHP 一同在 Web 开发领域长期存在————因为它们的源动力是相同的,而 PHP 相对于它们的优势又不足以完全抹杀掉它们的存在。
总结:
最后,我将上面的分析总结成四个论断:
- 论断一:PHP 在移动互联网到来之前出现过黄金时期,如今辉煌不再;
- 论断二:PHP 在未来可预见的很长时期内不会没落;
- 论断三:后黄金时代 PHP 的定位:中小公司的快速原型语言以及大公司的中间粘合层语言;
- 论断四:PHP7 和 Swoole 让 PHP 在和其他同层级语言(如 Python、RoR、nodejs)的竞争中保持优势,但无法给 PHP 带来根本的变化(无法改变 PHP 的定位);
相关文章:《phper:敢问路在何方》
再谈 PHP 未来之路的更多相关文章
- python之路--小数据池,再谈编码,is和 == 的区别
一 . 小数据池 # 小数据池针对的是: int, str, bool 在py文件中几乎所有的字符串都会缓存. # id() 查看变量的内存地址 s = 'attila' print(id(s)) 二 ...
- Unity教程之再谈Unity中的优化技术
这是从 Unity教程之再谈Unity中的优化技术 这篇文章里提取出来的一部分,这篇文章让我学到了挺多可能我应该知道却还没知道的知识,写的挺好的 优化几何体 这一步主要是为了针对性能瓶颈中的”顶点 ...
- 阿里封神谈hadoop学习之路
阿里封神谈hadoop学习之路 封神 2016-04-14 16:03:51 浏览3283 评论3 发表于: 阿里云E-MapReduce >> 开源大数据周刊 hadoop 学生 s ...
- Asterisk 未来之路3.0_0002
原文:Asterisk 未来之路3.0_0002 伟大的变化需要可扩展性技术 每一个现有的PBX都因为其自身的缺点变的糟糕,不管其功能如何丰富,总有一些东西会漏掉.具备非常完全功能的PBX 也不能预见 ...
- Asterisk 未来之路3.0_0003
原文:Asterisk 未来之路3.0_0003 Asterisk: The Hacker's PBX 如果电信公司忽视了asterisk,那么正在处于危险中.asterisk 良好的扩展性,能够创建 ...
- 再谈 Go 语言在前端的应用前景
12 月 23 日,七牛云 CEO & ECUG 社区发起人许式伟先生在 ECUG Con 2018 现场为大家带来了主题为<再谈 Go 语言在前端的应用前景>的内容分享. 本文是 ...
- Python基础篇 -- 小数据池和再谈编码
小数据池 1. id() 通过id()可以查看到一个变量表示的值在内存中的地址 s = "Agoni" print(id(s)) # 2410961093272 2. is 和 = ...
- mui初级入门教程(四)— 再谈webview,从小白变“大神”!
文章来源:小青年原创发布时间:2016-06-05关键词:mui,html5+,webview转载需标注本文原始地址: http://zhaomenghuan.github.io/#!/blog/20 ...
- 程序员肺被切掉一块还得去加班... 再谈“工作996,生病ICU”
如题,为什么要说再谈“工作996,生病ICU”,因为996问题早已不是一个新问题,在我最近刚出版的新书<SOD框架“企业级”应用数据架构实战>写作期间,爆发了一次程序员“起义”,出现了一个 ...
随机推荐
- C++线性表的链式存储结构
C++实现线性表的链式存储结构: 为了解决顺序存储不足:用线性表另外一种结构-链式存储.在顺序存储结构(数组描述)中,元素的地址是由数学公式决定的,而在链式储存结构中,元素的地址是随机分布的,每个元素 ...
- python3(二十九) orderClass
""" """ __author__ = 'shaozhiqi' # Python的class中还有许多有特殊用途的函数,可以帮助我们定制类 ...
- golang 在 Mac , Linux , Windows 下交叉编译详解
一. 前言 Golang 支持交叉编译, 在一个平台上生成然后再另外一个平台去执行. 而且编译的工具[build]这个工具是Golang 内置的,不需要你去下载第三方的包啥的,贼方便. 二. 交叉编译 ...
- MAC 上brew 更新 出错
在MAC上brew update的时候出现报错:Error: /usr/local must be writable! 错误,在该文章中也给出解决办法(sudo chown -R $(whoami) ...
- C语言折半查找法练习题冒泡排序
C语言折半查找法练习题 折半查找法: 折半查找法是效率较高的一种查找方法.假设有已经按照从小到大的顺序排列好的五个整数num[0]~num[4],要查找的数是key,其基本思想是: 设查找数据的范围下 ...
- Python队列的三种队列方法
今天讲一下队列,用到一个python自带的库,queue 队列的三种方法有: 1.FIFO先入先出队列(Queue) 2.LIFO后入先出队列(LifoQueue) 3.优先级队列(PriorityQ ...
- (转) 关于Windows CE和Windows Mobile
转发自http://www.cnblogs.com/chump/articles/1281955.aspx 一.Windows CE Windows CE是微软的嵌入式操作系统主要的一种,面世于199 ...
- Vm安装虚拟机并使用net模式连接外网
Vm安装虚拟机并使用net模式连接外网 最近想搭建一个maven私服和阿波罗配置中心一切准备就绪时 发现本地vm虚拟机无法连接外网,嗯 ~ ~ ,一句cnm不由从嘴里崩了出来.没办法,只能配置一下了接 ...
- jQuer实时监控input对table进行筛选
记得以前写过一个预定表格~~~~~比这个更难,一大串前端js~~~忘了~~~好记性不如烂笔头~~记录下,既帮助别人,也帮助自己~~~ 实现思路~通过.on监听input标签的内容变化,通过this获取 ...
- 浅析CAS与AtomicInteger原子类
一:CAS简介 CAS:Compare And Swap(字面意思是比较与交换),JUC包中大量使用到了CAS,比如我们的atomic包下的原子类就是基于CAS来实现.区别于悲观锁synchroniz ...