在许多语言中,您从头开始构建 Web 框架(即从 unix 套接字)并在抽象层上构建。如果我想用 OCaml 或 C 从头开始构建一个 web 框架,我首先构建一个侦听端口 80 的套接字服务器。
我突然想到 PHP - 就像任何其他高级语言一样 - 可能会以某种方式包装 unix 套接字。现在我知道情况是这样的,PHP 从来就不是这样设计的。但是,我不明白为什么它从未以这种方式使用过。按照同样的思路,PHP 解释器从未像 Python 解释器那样以这种方式使用。
例如,当我从头开始构建 Python Web 服务器并部署它时,我执行以下操作:在某个端口(比如 8000)上添加一个 unix 套接字,像 一样守护我的脚本python server.py 8000
,并在端口 80 上设置 nginx 反向代理并转发到我的端口 8000 上的内部本地服务器。我从未见过用 PHP 完成的,即使它是可能的。
我承认,除了使用独立的解释器(即 Tornado、uwsgi 等)之外,您在 Python 中还有其他选择。然而,它是双向的。
我的问题是,PHP 语言、解释器或社区的哪些方面阻止了 PHP Web 框架从 unix 套接字调用从头开始构建、在本地端口上进行守护进程以及被反向代理而不是使用 cgi/ fastcgi 包装器?
一句话,历史。这是对 15+ 年历史的一个非常简略的总结(如果你真的有兴趣,你可以在网上找到更多):
首先,虽然 PHP 具有编程语言的所有功能,但并非总是如此。它最初是一个“超文本预处理器”,其目的是嵌入 HTML 页面并由 CGI 程序或 Web 服务器本身解析。它本来是要运行由现有的web服务器,而不是成为一个网络服务器。在它的早期迭代中,它是一种非常简单的语言(有些人会说它仍然是)。
PHP 可以追溯到 1990 年代后期,当时 Web 服务器运行动态内容的唯一方法是通过CGI。然而,CGI 的一个大问题是它相当慢,因为它为每个请求分叉了一个新进程。早期没什么大不了的,但是当互联网热潮袭来时,它就成了一个问题。PHP 变得足够流行,以至于它作为可加载模块嵌入到 Apache 中,这提供了比 CGI 更好的性能并提供了一些其他好处。
在很长一段时间里,PHP 只能以这两种方式中的一种方式运行,但由于它已成为拥有绝大多数市场份额的语言,因此没有人真正关心。尽管最终有些人想要使用 Apache 以外的服务器,并且有一段时间 CGI 是唯一的方法,直到一个称为php-fpm(FastCGI 进程管理器)的FastCGI服务器 API最终被贡献到 PHP 中。与 CGI 不同,FastCGI 保持一个进程池始终运行并准备好为传入的请求提供服务。
在 2000 年代出现了其他语言,它们以不同的方式做事。例如,在 Ruby 中,应用程序库是在所谓的 gem 中提供的,只需将一些现有的 gem 与业务逻辑粘合在一起,就可以轻松创建程序。Rack 是一个 Ruby gem,它提供了一个 Ruby API 来构建 Web 服务器,mongrel、unicorn、thin 等服务器以及 Rails 和 Sinatra 等框架都建立在它之上。
其他语言(例如 Python 和 Java)具有类似的 Web 服务器和 Web 服务器框架。正如您所看到的,这与 PHP 所采用的方法完全不同,后者通常根本不使用 HTTP 来处理请求。
但是,最近的 PHP 版本现在有一个“内置 Web 服务器”,但它相对较新,一次只能处理一个连接,因此不适合生产使用。它是专为开发人员使用而明确设计的。
最终归结为:PHP 旨在在现有 HTML 文档的上下文中工作,而其他语言(如 Python、Ruby、Java 等)则是通用的。我所知道的在这方面与 PHP 类似的唯一其他网络语言是微软的“经典” ASP,它具有类似的设计。