ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

【思考】PHP——成也Web,败也Web

2021-05-11 19:55:01  阅读:256  来源: 互联网

标签:Web HTTP SAPI Python 思考 服务器 PHP


早年我并不知道Python写的Web应用是怎么部署的,总觉得像PHP、ASP一样,仅仅提供一个语言级别的执行模块,直接嵌入Web服务器运行,甚至于直接对外提供带扩展名的URL都是自然而然的事情。

前一阵学习了Python,总是如别人一样,不自觉的和PHP进行对比。随着学习的逐步深入,更发现PHP的发展受限于其Web出身,恐将来难成正经的通用开发语言。

先说说PHP从历史到今天分别是怎么运行的:

  • CGI SAPI:由Web服务器的请求处理进程fork+exec这个CGI,用环境变量单向传递Headers给应用程序,应用程序从stdin读request body,其stdout会被Web服务器作为response headers和body输出给客户端。Web服务器和PHP CGI的关系是父子进程间通信,当应用程序的响应速度较慢时(忙于计算、外部I/O等),会阻塞对应的Web服务器进程/线程
  • Apache2Handler等Web服务器模块类SAPI:Apache2调用Handler,并向其传递server_context;Handler利用server_context读到Header、body等内容之后构造起PHP脚本的context,也就是$_SERVER之类,然后开始执行PHP脚本。而脚本执行的输出也直接被Web服务器收集。PHP和Web服务器在同一个进程内执行,处于完全从属的地位。Apache2Handler方式本来可以通过多线程等方式让Apache不受PHP阻塞,但由于PHP社区的坚持,目前常见的Apache2+PHP配置都是prefork MPM的,以至于性能相当一般
  • FastCGI SAPI:原理是把每次fork处理一个请求,变成一个不退出的循环,每循环一轮就处理一个请求;多进程listen在同一个socket上,实现并发。PHP-FPM是后来的一个民间补丁项目,提供了更好的进程管理和附加功能,处理完License问题之后,FPM合并入PHP主线。Web服务器和PHP的关系是网络通信的关系,可以分离到不同服务器上部署。Web服务器可以使用多线程或者I/O复用技术来处理别的请求,性能会>比前二者好很多。但FPM的实现仍然不够好。

PHP的各种扩展模块,大都是偏重于数据库、字符串处理等应用层面的功能,充分体现了其作为Web开发利器的特点;而对于I/O、POSIX基础功能,则关注较少。
Web开发之外的领域,用PHP写独立运行的服务器,并不是主流的用法。其依赖的pcntl、pthread等模块也是较晚加进来的,而且也没啥人用。用以下几个模块可以很容易的创作一个独立的HTTP静态文件或SOA服务:

  1. PEAR Net_Server(无人维护) 通用服务器框架
  2. PEAR HTTP2 协议解析库
  3. PEAR HTTP_Server(无人维护) HTTP服务器框架
  4. PECL pecl_HTTP(需要编译) HTTP服务器框架,我没编译出来……
    但如果想在其中运行一般的Web PHP脚本,就需要用PHP本身实现一个SAPI:
  • 输入方面是很容易仿制的,除了需要构造Predefined/Reserved Variables(感谢作者,$_SERVER等只是普通数组,只须填充内容就差不多了,而不像ASP那样是复杂的Request对象)再写一下上传文件自动存盘的处理就差不多了
  • 输出方面就比较麻烦,因为“写”是动作。考虑到PHP深深的“假设stdout”情结,须使用output buffer机制收集输出内容。另外,header()函数等的实现可能会比较复杂

传统上,协议解析是SAPI的工作,PHP从属于Web服务器,以至于没积累出什么好用的协议解析库;而PHP书写的Web应用向来都是直接调用SAPI提供的函数,积习难改,以至于想用PHP本身来写Web服务器就须要去实现一个SAPI,但又会遭遇到这个语言本身的Web烙印太深、假设太多,以及不够“动态”的问题。
传统上,网络通信向来也不须由PHP来处理,以至于也没积累出什么好用的通信框架库。

最终,PHP成了一个Web only的开发语言。真可谓成也Web、败也Web。

一些新兴的PECL扩展提供了高性能I/O框架,比如swoole,但因为上述SAPI的问题,目前尚未出现像Python那样用PHP本身写的PHP Web服务器。

相比之下,不用写<%的Python语言,其发展道路就更加general purpose一些:

  1. 标准库中有os、multiprocess、threading、select等模块,一看就是面向系统编程而非仅仅针对Web开发
  2. 标准库中的SocketServer及其MixIn classes、HTTPServer等可用于写服务器;CGI模块可用于解析HTTP协议请求
  3. 标准库中的wsgiref是纯Python的。也就是说,用Python语言写一个WSGI Server很容易且是提倡的做法
  4. yield语法加入语言比较早,可以实现协程
    在Web应用方面,Python的WSGI接口已经基本统一江湖。WSGI不是通信协议,而是语言级别的调用约定(关于这个函数后面带几个什么样的参数的约定),而WSGI可以用纯Python实现,因此不会遇见用PHP实现SAPI的尴尬。由于Python没有像PHP那样深深的Web烙印(甚至早年在Web上的部署并不太方便)加上标准库中很早就带有各种基础模块,导向结果就是出现了很多优秀的高性能框架和服务器软件。现在流行的组合是用 gunicorn WSGI Server运行WSGI应用程序,管理多个worker充分利用多处理器,用gevent消除I/O等待时的浪费;对外提供HTTP服务,前面套一个nginx提供静态文件和访问控制、rewrite等功能。



发现文章有错误、对内容有疑问,都可以关注美团点评技术团队微信公众号(meituantech),在后台给我们留言。我们每周会挑选出一位热心小伙伴,送上一份精美的小礼品。快来扫码关注我们吧!

公众号二维码

标签:Web,HTTP,SAPI,Python,思考,服务器,PHP
来源: https://blog.51cto.com/u_15197658/2768717

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有