一直对php的运行原理一知半解,某个周末查询了网上的资料,不才有了一些浅显的理解。特此记录下来。文章主要分为两个模块进行介绍:php代码内部运行原理和php运行模式。本文原理介绍的大部分文字是直接引用他人文章,本文是按照个人理解的逻辑将收集的资料重新组织了起来,并添加了个人的一些理解。
这一块的内容暂时理解的不是很深入,直接引用他人的解释。
什么是 Zend ? 什么是 PHP ?
Zend是语言引擎,PHP内核。PHP是从外层展现的完整系统。咋一听似乎有点模糊不清,但是其实并不复杂( 看下面).为了实现一个 web 脚本解释器,你需要三个部分:
Zend完全参与第一部分,部分参与第二部分;PHP参与第二部分和三部分.他们一起构成完整的PHP包。实际上Zend自己仅仅构成语言核心,用预定义函数实现 PHP 非常基础部分。而 PHP 包含所有的实际形成语言突出能力的所有模块。
关于php的扩展等知识以后了解后再补充,这里理解到这个程度就足够了。
本文所讲的运行模式特指使用Apache和nginx等服务器协作的php项目。这里讨论的简单来说是nginx,Apache是怎么和php通信的这个问题。
这里我将收集到的逻辑画成了一张图:
对上图的解释如下:
SAPI(Server Application Programming Interface)指的是PHP具体应用的编程接口, 就像PC一样,无论安装哪些操作系统,只要满足了PC的接口规范都可以在PC上正常运行, PHP脚本要执行有很多种方式,通过Web服务器,或者直接在命令行下,也可以嵌入在其他程序中。
通常,我们使用Apache或者Nginx这类Web服务器来测试PHP脚本,或者在命令行下通过PHP解释器程序来执行。 脚本执行完后,Web服务器应答,浏览器显示应答信息,或者在命令行标准输出上显示内容。
我们很少关心PHP解释器在哪里。虽然通过Web服务器和命令行程序执行脚本看起来很不一样, 实际上它们的工作流程是一样的。命令行参数传递给PHP解释器要执行的脚本, 相当于通过url请求一个PHP页面。脚本执行完成后返回响应结果,只不过命令行的响应结果是显示在终端上。
脚本执行的开始都是以SAPI接口实现开始的。只是不同的SAPI接口实现会完成他们特定的工作, 例如Apache的mod_php SAPI实现需要初始化从Apache获取的一些信息,在输出内容是将内容返回给Apache, 其他的SAPI实现也类似。
而PHP最常用的SAPI提供的2种连接方法:mod_php和mod_fastcgi。
当Apache采用mod_php模式工作时,需要有如下的配置:
也即php作为Apache的一个子模块来运行,当通过web访问php文件时,Apache就会调用php5_module来解析php代码。
配置加载mod_php模块后,php便是Apahce进程本身一部分,每个新的Apache子进程都会加载此模块。这种模式相当于Apache自己就能运行php程序,这样会有一些弊端:
mod_php 通过嵌入 PHP 解释器到 Apache 进程中,mod_php 这种嵌入的方式最大的弊端就是内存占用大,不论是否用到 PHP 解释器都会将其加载到内存中,典型的就是处理CSS、JS之类的静态文件是完全没有必要加载解释器。参考此篇文章。
CGI全称是“通用网关接口”(Common Gateway Interface),它可以让一个客户端,从网页浏览器向执行在Web服务器上的程序请求数据。 CGI描述了客户端和这个程序之间传输数据的一种标准。 CGI的一个目的是要独立于任何语言的,所以CGI可以用任何一种语言编写,只要这种语言具有标准输入、输出和环境变量。 如php,perl,tcl等。
CGI运行原理表述如下:
上面的这段话理解可能还是比较抽象,下面我们就通过一次 GET 请求为例进行详细说明。
如图所示,本次请求的流程如下:
FastCGI是Web服务器和处理程序之间通信的一种协议, 是CGI的一种改进方案,FastCGI像是一个常驻(long-lived)型的CGI, 它可以一直执行,在请求到达时不会花费时间去fork一个进程来处理(这是CGI最为人诟病的fork-and-execute模式)。 正是因为他只是一个通信协议,它还支持分布式的运算,所以 FastCGI 程序可以在网站服务器以外的主机上执行,并且可以接受来自其它网站服务器的请求。
FastCGI 是与语言无关的、可伸缩架构的 CGI 开放扩展,将 CGI 解释器进程保持在内存中,以此获得较高的性能。 CGI 程序反复加载是 CGI 性能低下的主要原因,如果 CGI 程序保持在内存中并接受 FastCGI 进程管理器调度, 则可以提供良好的性能、伸缩性、Fail-Over 特性等。原理表述如下:
对FastCGI有一个通俗的解释:FastCGI事先就需要启动,而且可以启动多个CGI模块,在那里一直运行等着web发请求,然后再给php解析运算,完成后生成html返回给web后,但是完成后它不会退出,而是继续等着下一个web请求。参考这里。
PHP-FPM就是针对于PHP的FastCGI的一种实现,他负责管理一个进程池,来处理来自Web服务器的请求。
但是PHP-FPM仅仅是个“PHP FastCGI 进程管理器”, 它仍会调用PHP解释器本身来处理请求,PHP解释器(在Windows下)就是php-cgi.exe。
nginx通常采用PHP-FPM模式运行php程序,它的基本配置如下:
Apache这里就先不补充了。
php的编程接口SAPI提供两种连接模式mod_php和mod_fastapi。本文围绕这个两种模式展开了相关介绍。参考文章已在文中列出。