前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PHP - 语言底层运行及生命周期

PHP - 语言底层运行及生命周期

原创
作者头像
stark张宇
发布2023-02-07 18:27:21
6450
发布2023-02-07 18:27:21
举报
文章被收录于专栏:stark张宇stark张宇

概述

PHP在业界被调侃,是世界上最好的语言,PHP确实是Web开发里的利器,具体点说,就是一个用C语言实现包含大量组件模块的软件框架。是一个强大的UI框架。

PHP动态语言执行过程:拿到一段代码后,经过词法解析、语法解析等阶段后,源程序会被翻译成一个个指令(opcodes),然后ZEND虚拟机顺次执行这些指令完成操作。PHP本身是用C实现的,因此最终调用的也是C的函数,实际上,我们可以把PHP看做一个C开发的软件。

分层体系

复杂的结构需要分层,TCP/IP协议因为分层得到了很好的应用,不熟悉的同学可以去我的计算机网络专栏的文章里看一看,PHP也是主要分为四层,分层处理,提高处理效率和职能。

PHP从下倒上是一个4层体系:

1、Zend引擎:Zend整体用纯C实现,是PHP的内核部分,他将PHP代码翻译(词法、语法解析等一系列编译过程)为可执行opcode的处理并实现相应的处理方法、实现了基本的数据结构(如:hash_table、OO)、内存分配机制及管理、提供了相应的api方法供外部调用,是一切的核心,所有的外围功能均围绕Zend实现。

2、Extensions:围绕着Zend引擎,extensions通过组件式的方式提供各种基础服务,我们常见的各种内置函数(array系列)、标准库等都是通过extension来实现CGI即通用网关接口,用户也可以根据需要实现自己的extension的典型应用)。

博主梦话:印象里在win上开发的时候,有个ext文件夹,里面装载着各种类库,就是Extensions层存放扩展文件的路径。

3、Sapi: Sapi全称 Server Application Programming Interface ,也就是服务端应用编程接口,Sapi通过一系列钩子函数,使得PHP可以和外围交互数据,这是PHP非常优雅和成功的设计,通过sapi成功的将PHP本身和上层应用解耦隔离,PHP可以不再考虑如何针对不同应用进行兼容,而应用本身也可以针对自己的特点实现不同的处理方式。

4、上层应用:这就是我们平时编写的PHP程序,通过不同的spai方式得到各种各样的应用模式,如何通过webserver实现web应用、在命令行下已脚本方式运行等等。

Sapi

Sapi通过一系列的接口,使得外部应用可以和PHP交换数据并可以根据不同应用特点实现特定的处理方法,我们常见一些sapi有:

代码语言:txt
复制
var_dump(php_sapi_name()); # 输出当前php运行模式

1、CGI/FastCGI

下文有详细解释。

2、APACHE2HANDLER

PHP作为Apache模块,Apache服务器在系统启动后,预先生成多个进程副本驻留在内存中,一旦有请求出 现,就立即使用这些空余的子进程进行处理,这样就不存在生成子进程造成的延迟了。这些服务器副本在处理完一次HTTP请求之后并不立即退出,而是停留在计 算机中等待下次请求。对于客户浏览器的请求反应更快,性能较高。

3、apache模块的DLL

该运行模式是我们以前在windows环境下使用apache服务器经常使用的,而在模块化(DLL)中,PHP是与Web服务器一起启动并运行的。

博主梦话:印象里在win上开发的时候,有个ext文件夹,里面装载着各种类库,就是.dll结尾的文件。

4、Cli

在最开始设计PHP这门语言时是为了执行脚本,所以win上和Linux中都有 Cli模式,Cli模式会强制使用一些配置参数,强制关闭缓冲区的数据,执行也非常高效,常用的参数:

代码语言:txt
复制
-a 交互式运行PHPCLI程序
-c 告诉PHP,从那个路径寻找php.ini
-l 检查php文件的语法,不执行
-m 查看编译的模块

Cli模式的生命周期

模块初始化阶段->请求初始化阶段->脚本执行阶段->请求关闭阶段->模块关闭阶段

后来Swoole中为了追求性能,在启动服务的时候使用常驻内存的方式预先加载在内存里,在脚本中千万不要写配置文件中,因为在Cli模式下第一次的执行没有被释放,第二次的又来执行,会造成服务内存问题。

CGI/FastCGI

之前互联网上的Web服务都属于html,静态资源分布,随着互联网的发展,后来出现了像asp、jsp、php这种动态语言,动态语言的特点是需要Web服务器的解析Cgi就是Web服务器和动态语言通信的网关。

CGI即通用网关接口(Common Gateway Interface),它是动态语言的产物,是负责Web服务与PHP通信的接口,CGI方式在遇到连接请求(用户 请求)先要创建cgi的子进程,激活一个CGI进程,然后处理请求,处理完后结束这个子进程。这就是 fork-and-execute 模式。所以用cgi 方式的服务器有多少连接请求就会有多少cgi子进程,子进程反复加载是cgi性能低下的主要原因。

在这个基础上产生了FastCGI,FastCGI像是一个常驻(long-live)型的CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去fork一 次。PHP使用PHP-FPM(FastCGI Process Manager),全称PHP FastCGI进程管理器进行管理。

FPM的三种模式运行模式

重点要介绍的是FPM的三种模式运行模式:内存优先(ondemand)、静态池(static)、服务优先(dynamic)。

ondemand

php-fpm启动的时候不会启动worker进程,按需启动worker,有链接进来后,才会启动。

代码语言:txt
复制
listen = 127.0.0.1:9001
pm = ondemand
pm.process_idle_timeout = 60
pm.max_children = 10

连接到来时(只有链接,不没有数据也会创建,telnet也会创建),创建新worker进程,worker进程数的创建收max_children设置限制,也受限于全局的process.max设置(三种模式都受限此,下文中有全局配置项讲解),如果空闲时间超过了process_idle_timeout的设置就会销毁worker进程。

优点:按流量需求创建,不浪费系统资源。

缺点:因为php-fpm是短连接的,如果每次请求都先建立连接,大流量场景下会使得master进程变得繁忙,浪费cpu,不适合大流量模式,不推荐使用此模式。

dynamic

会初始化创建一部分worker,在运行过程中,动态调整worker数量,最大worker数再pm.max_childrenprocess.max之间。

代码语言:txt
复制
pm.max_children < worker进程数量 < process.max
代码语言:txt
复制
pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 6

当空闲进程数小于min_spare_servers时,创建新的子进程,总子进程数小于等于pm.max_children,小于等于process.max,当空闲进程数大于max_spare_servers,会杀死启动时间最长的子进程,如果子进程(idle状态)数大于max_children,会打印warning日志,结束处理。

process小于 max_children ,计算一个num,启动num个worker。

优点:动态扩容,不浪费系统资源。

缺点:所有worker都在工作,新的请求到来需要等待创建worker进程,最长等待1s(内部存在一个1s的定时器,去查看,创建进程),频繁启停进程消耗cpu,请求数稳定,不需要频繁销毁

static

启动固定大小数量的worker,也有1s的定时器,用于统计进程的一些状态信息,例如空闲worker个数,活动worker个数

代码语言:txt
复制
#需要主意的是,必须配置这个参数,而且只有这个参数有效
pm.max_children = 10 

NGINX与php-fpm的通信

我理解的php-fpm是PHP对FastCGi封装的模块,是PHP对CGI网关通信的优化和扩展,Web服务器都在php-fpm实现。配置文件里的listen。listen负责监听ip和端口,查看php-fpm的配置文件,查看监听端口,默认是9000,然后配置你的Nginx。

代码语言:txt
复制
	ps aux | grep php
	listen = 127.0.0.1:9000

Nginx Server里配置:

代码语言:txt
复制
server {
     listen      80;
     server_name  www.baidu.com;
     root /home/work/www/baidu/;
     index index.php;

     location / {
         add_header Access-Control-Allow-Origin *;
         add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
         add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
     }

     location ~ / {
      rewrite ^(.*)$ /index.php$1 break;
      fastcgi_pass   127.0.0.1:9000;
      fastcgi_index  index.php;
      fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
      fastcgi_param  ENVIROMENT 0;
      include fastcgi_params;
     }
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
    • 分层体系
      • Sapi
        • CGI/FastCGI
          • FPM的三种模式运行模式
            • ondemand
            • dynamic
            • static
          • NGINX与php-fpm的通信
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档