在浏览器点击一个按钮, 发起一个请求, 最终服务器经过一系列复杂的计算之后, 响应给客户端数据. 现在用通俗的方式解释一下这个过程. 完成整个过程主要由以下几个角色各司其职
浏览器 (客户端): 负责通过http协议与服务器对话, 方式是发送-接收http数据包
这里要理解的一点是, 对于浏览器而言, 他要做的工作就是按照网址, 从对应的服务器上获取对应文件中的内容. 这一点是不会变的.
web服务器 (服务端): 负责接收http请求, 按照请求返回对应文件的内容
要什么文件就给什么文件, 找不到文件或者找到的文件不让看就报4xx系列错误, 找到文件但是发生故障了没法返回文件内容, 就报5xx系列错误
CGI协议 (服务器中的普通话): 负责统一cgi程序的数据格式,让 web服务器 和 CGI程序 都能看得懂
CGI程序 (Common Gateway Interface) : 会说普通话的程序都叫CGI程序, 就是说, 只要打印的字符串是按照CGI协议来的, 这个程序就是CGI程序. 服务器中运行着PHP, Perl, Python, java, C++, C等等各种语言, 无论哪种语言, 肯定都是可以向标准输出stdio 打印字符串的, 比如 helloworld. 各种程序如果想把信息通过网络传输给客户端, 那就必须要按照CGI标准来打印.
PHP-CGI (php的翻译官): 负责解析PHP代码, 最终按照CGI协议输出运算结果
在 PHP5.4 RC2 版本以前, PHP内置的解释器就是php-cgi . 我们写PHP的时候知道, 如果要执行一个PHP脚本, 要调用PHP解释器来执行, 如 php test.php , 然后test.php中的代码就会被逐条解释执行. 网络请求来了之后, 就是由php-cgi执行的 php test.php这个过程. 在 PHP5.4 RC2 版本以后, php-cgi的角色由 php-fpm 替代
FastCGI (快速说普通话标准): 负责解决CGI性能问题
由于各类语言编写的CGI程序响应速度较慢, 所以就有了这个标准. 注意fast-cgi并不是一个程序, 而是一种实现标准, 它只规定了凡是满足了这个标准的程序, 都被称作是FastCGI的一种实现. 常见的FastCGI程序有spawn-fcgi , FCGI Wrap , php-fpm , fcgi-cgi 等
PHP-FPM (php的高级翻译官): 负责解析PHP代码, 最终按照CGI协议输出运算结果
php-fpm 就是实现了FastCGI标准的一个软件 原本的php-fpm (FastCGI Process Manager)是负责管理cgi进程的程序, 当网络请求变多的时候, 每个cgi进程都会经历初始化PHP环境, 读取php.ini配置文件, 读取xx.php代码, 解释, 执行, 然后返回结果的过程. 这个过程性能很差, 网络拥堵严重. PHP-FPM经过多次实践改造后, 替代了php-cgi, 先加载好整个PHP环境, 创建好线程池, 请求一来就只做解释执行PHP代码的工作, 性能稳定,可靠.
名词解释完毕. 现在的PHP框架已经复杂到了看不懂的地步, 如Laravel, lumen, 每年更新一次, YII, ThinkPHP等等框架, 层层封装, 看上去和上面的请求过程似乎都联系不上. 实际上, 本质过程, 就是一个计算后打印字符串的过程, 只不过调用链随着时代发展越来越复杂, 越来越长. 大致步骤如下:
- 浏览器发起请求:
http:xxx.com/a/b/c - 服务器接收请求, 查找
a 目录下b 目录下的c 文件 - 服务器找不到
c 文件, 根据nginx中的tryfiles 配置, 将/a/b/c 这个uri 转发给index.php , 由它处理, 交接过程如下. 1). 服务器将所有请求信息传递给FastCGI程序, 此时服务器中运行的FastCGI程序是php-fpm , 请求就自然给了它. 2). php-fpm 拿到请求后, 开始从index.php 开始解释执行. 3).index.php 开始加载框架 4). 框架开始解析路由, 所有的服务器参数都要归功于CGI协议, 这些都是由nginx包装好传来的, 这样PHP中的$_SERVER 中才有了一切想要的信息. 5). 框架根据路由加载服务, 签名验证, 连接数据库, 执行Controller等等一系列复杂操作 6). 最终, 整个PHP框架一定会echo 一个字符串出来 7). 这个字符串再由php-fpm通过socket 发送给nginx - nginx终于在PHP这里找到了他想要找的文件, 文件内容就是这个echo出来的字符串. nginx认为这是一个文件的内容, 实际上是经过复杂计算动态生成的内容.
以上, 就是整个PHP调用链.
|