一 PHP是什么
PHP(“PHP: Hypertext Preprocessor”,超文本预处理器的字母缩写)是一种被广泛应用的开放源代码的多用途脚本语言,它可嵌入到 HTML中,尤其适合 web 开发
PHP 的开发是以服务端脚本为目的
PHP 的命令行模式能使得 PHP 脚本能完全独立于 web 服务器单独运行。如果使用 Unix 系统,需要在 PHP 脚本的最前面加上一行特殊的代码(幻数),使得它能够被执行,这样系统就能知道用哪个程序去运行该脚本。
二 PHP和CGI
说明:各种术语释疑
cgi:它是一种协议,通过cgi协议,web server可以将动态请求和相关参数发送给专门处理动态内容的应用程序
CGI效率:每一个Web请求PHP都必须重新解析php.ini,重新载入全部dll扩展并重初始化全部数据结构!
fork-and-execute模式:CGI方式在遇到连接(用户)请求先要创建cgi的子进程,激活一个CGI进程,然后处理请求,处理完后结束这个子进程。
缺点:所以用cgi方式的服务器有多少连接请求就会有多少cgi子进程,子进程反复加载(频繁调用底层资源)使cgi性能低下
概括:开销比特大
严重:当用户请求数量非常多时(并发访问),会大量挤占系统的资源如内存,CPU时间等,造成效能低下。
fastcgi:也是一种协议,只不过是cgi的优化版,其常驻在内存中
优点:将CGI解释器保持在内存中(常驻)并接受FastCGI进程管理器调度,则可以提供良好的性能、伸缩性、Fail- Over特性等
php-cgi:fastcgi是一种协议,而php-cgi实现了这种协议。不过这种实现比较烂。它是单进程的,一个进程处理一个请求,处理结束后进程就销毁。
php-fmp:对php-cgi的改进版,它直接管理多个php-cgi进程/线程。也就是说,php-fpm是php-cgi的进程管理器因此它也算是fastcgi协议的实现。在一定程度上讲,php-fpm与php的关系,和tomcat对java的关系是类似的。
补充:PHP-FPM其实是PHP源代码的一个补丁,旨在将FastCGI进程管理整合进PHP包中。PHP-FPM提供了更好的PHP进程管理方式,可以有效控制内存和进程、可以平滑重载PHP配置,进程包含 master 进程和 worker 进程两种进程。
master 进程只有一个,负责监听端口,接收来自 Web Server 的请求,而 worker 进程则一般有多个(具体数量根据实际需要配置),每个进程内部都嵌入了一个 PHP 解释器,是 PHP 代码真正执行的地方。
注意:尽管php-fpm的全称为PHP FastCGI Process Manager,但严格地讲php-fpm不是fastcgi的进程管理器,而是php fastcgi对php-cgi的进程管理器。fastcgi只是一种协议,不是进程。就像http协议一样,apache对它的实现是httpd,nginx对它的实现就叫nginx。再次说明,cgi和fastcgi是一种协议。各种支持和WEB交互的编程语言对cgi/fastcgi协议都做了各自的实现(任何一种语言都能写cgi脚本),而php上的php-cgi和php-fpm正是php对fastcgi协议的实现。
盗图一张
说明:在编译php的时候,必须加上--enable-fpm(不同版本可能有差异)
cgi进程/线程:在php上就是php-cgi进程/线程,专门用于接收web server的动态请求,调用并初始化zend虚拟机
cgi脚本:这里指被执行的php源代码文件
zend虚拟机:对php文件做词法分析、语法分析、编译成opcode,并执行。最后关闭zend虚拟机。
cgi进程/线程和zend虚拟机的关系:cgi进程调用并初始化zend虚拟机的各种环境。
cgi脚本三要素:标准输入、标准输出、环境变量!
三 web服务器和web应用程序
web服务器所处理的内容都是静态的,要想处理动态内容,需要依赖于web应用程序,如php、jsp、python、perl等!
核心1:web server如何将动态的请求传递给这些应用程序?
解答:它所依赖的就是cgi协议,也就是web server和web应用程序交流时的规范(如同HTTP协议一样,是规范,就好像两个人谈话,事先进行一些约定俗成的约定)。换句话说,通过cgi协议,再结合已搭建好的web应用程序,就可以让web server也能"处理"动态请求(或者说,当用户访问某个特定资源时,可以触发执行某个web应用程序来实现特定功能)!
再盗图一张
四 php的工作原理详解
1. PHP的所有应用程序都是通过WEB服务器(如IIS,Nginx或Apache)和PHP引擎程序解释执行完成的,工作过程:
(1)当用户在浏览器地址中输入要访问的PHP页面文件名,然后触发一个web请求,并将请求传送到WEB服务器;
(2)WEB服务器接受这个请求,并根据其后缀进行判断是一个PHP请求,WEB服务器从硬盘或内存中调出用户要访问的PHP应用程序,并将其发送给PHP引擎程序;
细节:web server会将这些程序参数和一些环境变量根据cgi协议通过TCP或套接字等方式传递给已启动的cgi程序
补充:也可能是cgi进程,或者是已加载的模块cgi模块!
当cgi进程接收到web server的请求后,调用search程序并执行,同时还会传递参数给search程序
(3)PHP引擎程序将会对WEB服务器传送过来的文件从头到尾进行扫描并根据命令从后台读取,处理数据,并动态地生成相应的HTML页面;
(4)PHP引擎将生成HTML页面返回给WEB服务器,WEB服务器再将HTML页面返回给客户端浏览器;
核心步骤:第二步、第三步!
补充:java的servlet完全能实现CGI的功能!
五 php动态模块安装
说明:php一旦编译完成后,如果想添加新的模块,要么重新编译php,要么编译一个扩展模块(so文件),然后在php.ini中配置一下,就可以被加载使用了。
/usr/local/php/bin/php -m #Linux中查看已经加载了哪些模块!
说明:核心查看是否加载mysql和
补充 web server和php-cgi交互模式
php-fpm模式:可以将php-fpm独立运行在非web服务器上,实现所谓的动静分离。
六 源码安装
# (1)解压
tar jxf php-5.6.35.tar.bz2
yum -y install bzip2 #缺少解压的软件,根据提示安装软件
# (2)进入解压后的目录,开始编译
./configure --prefix=/usr/local/lnmp/php --with-config-file-path=/usr/local/lnmp/php/etc --with-openssl --with-snmp --with-gd --with-zlib --with-curl --with-libxml-dir --with-png-dir --with-jpeg-dir --with-freetype-dir --with-gmp --with-gettext --with-pear --enable-mysqlnd --with-mysql=mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --enable-inlinlse-optimization --enable-soap --enable-ftp --enable-sockets --enable-mbstring --enable-fpm --with-fpm-user=nginx --with-fpm-group=nginx --with-mcrypt --with-mhash
# (3)相关参数的说明
--with-config-file-path=/etc 指定'php.ini'位置(核心配置文件)
--with-MySQL=mysql安装目录,对mysql的支持
--with-MySQLi=mysqli文件目录,'优化'支持
--enable-fpm
# PHP-FPM是一个PHP FastCGI进程管理器,是只用于PHP的,它其实是PHP源代码的一个补丁,旨在将Fast-CGI进程管理整合进PHP包中-->
# 必须将它patch到你的PHP源代码中,在编译安装PHP后才可以使用。新版的PHP已经集成了php-fpm,在./configure的时候带 –enable-fpm参数即可开启PHP-FPM
#以上为php需要编译的模块,把刚才编译mysql的参数要加进来,添加mysqlnd(这是mysql的驱动,php开发的)
# php可能通过底层调用mysql!
# 说明:
--with-freetype-dir 打开对freetype字体库的支持
--with-zlib 打开zlib库支
#编译时遇到的报错就安装:yum install -y libxml2-devel libcurl-devel
# 举例:没有jpeglib.h文件:yum whatprovides */jpeglib.h
# (4)按转依赖软件
yum install -y libjpeg-turbo-devel-1.2.1-1.el6.x86_64 libpng-devel-1.2.49-1.el6_2.x86_64 freetype freetype-devel net-snmp net-snmp-devel
# (5)编译报错,逐步解决依赖性(rhel7可以向下兼容6的包)
yum install -y re2c-0.13.5-1.el6.x86_64.rpm libmcrypt-2.5.8-9.el6.x86_64.rpm libmcrypt-devel-2.5.8-9.el6.x86_64.rpm
# 说明:系统镜像没有的3个包,这里用的是rhel6的包(兼容)
# (6)安装
make && make install
# (7)最好测试一下
make test
# 说明:编译时添加了--with-fpm-user=nginx --with-fpm-group=nginx 参数,所以添加 nginx 用户
配置文件:php-fpm.conf和php-config以及php-cgi
(1)修改php-fpm的配置文件
查看配置文件中以下几项是否开启
cp php-fpm.conf.default(解压的文件) /usr/local/lnmp/php/etc/php-fpm.conf
# 复制一份模版文件
user = nginx #nginx进程启动的用户
group = nginx
pid = run/php-fpm.pid
# 看用户和用户组是不是nginx(nginx用户会调用)
说明:是nginx来调用的php的,所以这里要改成nginx!
(2)拷贝更改php主配置文件
cp php.ini-production /usr/local/lnmp/php/etc/php.ini
# /usr/local/lnmp/php/etc/当前目录进行的操作!
# 修改时区:date.timezone = Asia/Shanghai
# 虚拟机是什么就写什么
(3)php脚本
cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
# 复制一份启动脚本(解压的目录中)!
chmod a+x /etc/init.d/php-fpm
# 加执行权限!
(4)启动脚本
/etc/init.d/php-fpm start #启动脚本
netstat -antlupe|grep php #测试:查看端口-->9000(记住)