Skip to content

什么是面向对象?主要特征是什么?

面向对象是程序的一种设计方式,它利于提高程序的重用性,使程序结构更加清晰。主要特征:封装、继承、多态。

SESSION 与 COOKIE的区别是什么,请从协议,产生的原因与作用说明?

SESSION存储在服务器端,COOKIE保存在客户端。Session比较安全,cookie用某些手段可以修改,不安全。Session依赖于cookie进行传递。单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie,而session则存储与服务端,浏览器对其没有限制。

禁用cookie后,session不能正常使用。

Session的缺点:保存在服务器端,每次读取都从服务器进行读取,对服务器有资源消耗。Session保存在服务器端的文件或数据库中,默认保存在文件中,文件路径由php配置文件的session.save_path指定。Session文件是公有的。

php-fpm 运行机制

PHP-FPM(PHP FastCGI Process Manager)是PHP的一个进程管理器,它提供了一种用于处理HTTP请求的方式,特别是当使用FastCGI协议与Web服务器(如Nginx、Apache等)进行交互时。PHP-FPM的工作机制可以概括为以下几个主要部分:

  1. Master进程:

    • 当PHP-FPM启动时,它会首先创建一个Master进程。
    • Master进程负责读取并解析配置文件,然后根据配置创建一定数量的子进程(pool)。
    • Master进程还负责监控子进程的状态,并在需要时重启崩溃的子进程。
  2. 子进程(Pool):

    • 子进程是PHP-FPM的主要工作单元。
    • 根据配置文件中的设置,PHP-FPM可以创建固定数量的子进程(pm.max_children),或者基于请求的数量动态调整子进程的数量(pm.max_requests)。
    • 每个子进程都会独立地处理来自Web服务器的请求。
    • 当子进程处理完一个请求后,它会等待下一个请求,而不是立即退出。这有助于减少频繁创建和销毁进程的开销。
  3. 请求处理:

    • 当Web服务器(如Nginx)接收到一个PHP请求时,它会将请求转发给PHP-FPM的一个子进程。
    • 子进程会解析并执行PHP代码,然后将结果发送回Web服务器。
    • Web服务器再将结果返回给客户端。
  4. 通信机制:

    • PHP-FPM使用FastCGI协议与Web服务器进行通信。
    • FastCGI协议是一种高效的通信协议,允许Web服务器和PHP-FPM之间进行二进制数据的交换。
    • 使用FastCGI协议可以减少网络通信的开销,提高整体的性能。

总的来说,PHP-FPM通过管理一组子进程来处理PHP请求,从而实现了高效的并发处理能力。同时,通过FastCGI协议与Web服务器进行通信,确保了请求的快速响应和数据的正确传输。这使得PHP-FPM成为现代Web应用中处理PHP请求的常见选择之一。

PHP-FPM多少个进程合理?

确定 PHP-FPM 的进程数量并没有一个固定的标准,因为这会受到多种因素的影响,如服务器硬件、应用程序的需求、负载模式等。但是,可以通过以下几个方面来思考和确定一个合理的进程数:

  1. 服务器硬件:

    • CPU 核心数:PHP-FPM 进程应该与 CPU 核心数成比例,以便充分利用多核 CPU 的性能。通常,每个核心可以处理一个 PHP-FPM 进程。
    • 内存:内存限制也是决定进程数的一个重要因素。每个 PHP-FPM 进程都会消耗一定的内存,因此需要根据可用内存来确定最大进程数。
  2. 应用程序需求:

    • 请求并发量:如果应用程序的并发请求量较高,那么需要更多的 PHP-FPM 进程来处理这些请求。
    • 请求处理时间:如果请求处理时间较长,那么可能需要更多的进程来避免请求队列过长。
  3. 负载模式:

    • 负载类型:如果服务器主要处理 CPU 密集型任务,那么每个进程可能需要更多的 CPU 资源。对于 I/O 密集型任务,可能需要更多的进程来并行处理多个 I/O 操作。
    • 负载波动:如果负载波动较大,可能需要使用动态进程管理方式(如 pm = dynamic),让 PHP-FPM 根据负载自动调整进程数。
  4. 配置调优:

    • pm.max_children:这个参数定义了 PHP-FPM 进程的最大数量。需要根据实际情况进行调整。
    • pm.start_serverspm.min_spare_serverspm.max_spare_servers:这些参数用于控制 PHP-FPM 进程的启动和空闲状态,也需要根据实际需求进行调整。

综上所述,合理的 PHP-FPM 进程数应该根据服务器硬件、应用程序需求和负载模式进行综合考虑。可以通过观察服务器的性能指标(如 CPU 使用率、内存使用率、请求响应时间等)来不断调整和优化进程数,以达到最佳的性能和资源利用率。通常建议从较低的进程数开始,然后逐渐增加,直到找到最佳的平衡点。

GET和POST的区别

  1. 数据传输方式不同:GET方法的数据传输是通过URL传递的,而POST方法的数据传输是通过HTTP请求体传递的。
  2. 请求长度限制不同:GET请求对URL的长度有限制,不同浏览器和服务器对URL的长度限制不同,一般在2KB到8KB之间。而POST请求没有对请求体长度做特别限制,可以传输大量数据。
  3. 安全性不同:GET请求的参数是明文传输的,因此不适合传输敏感信息,如密码等。POST请求传输的数据不会显示在URL中,因此安全性更高。
  4. 缓存不同:GET请求可以被缓存,因为GET请求是幂等的,即多次相同的GET请求对服务器的状态没有影响,可以使用缓存来提高性能。而POST请求不可以被缓存。

HTTP 状态中302、403、 500代码含义?

一二三四五原则:(即一:消息系列;二:成功系列; 三:重定向系列;四:请求错误系列;五:服务器端错误系列。)

  • 302:临时转移成功,请求的内容已转移到新位置
  • 403:禁止访问
  • 500:服务器内部错误
  • 401:代表未授权。

请写出数据类型(int char varchar datetime text)的意思;请问 varchar 和 char有什么区别?

Int 整数

char 定长字符

Varchar 变长字符

Datetime 日期时间型

Text 文本型

Varchar与char的区别 char是固定长度的字符类型,分配多少空间,就占用多长空间。

Varchar是可变长度的字符类型,内容有多大就占用多大的空间,能有效节省空间。由于varchar类型是可变的,所以在数据长度改变的时,服务器要进行额外的操作,所以效率比char类型低。

isset() 和 empty() 区别

isset判断变量是否存在,可以传入多个变量,若其中一个变量不存在则返回假;

empty判断变量是否为空为假,只可传一个变量,如果为空为假则返回真。

请说明 PHP 中传值与传引用的区别

在PHP中,传值和传引用是两种不同的参数传递方式,它们在函数调用过程中对原始变量的影响有所不同:

  1. 按值传递 (Pass by Value):

    • 当函数接收一个参数并按值传递时,函数内部会创建一个原变量的副本,并将这个副本的值传入函数内部。
    • 在函数内部对该变量进行的任何操作都不会影响到函数外部的原始变量。
    • 对于简单类型(如整型、浮点型、字符串、布尔值等),复制的是变量的完整值。
    • 如果传递的是复杂类型如数组或对象,虽然不是复制整个结构,但由于PHP的对象和数组都是引用计数的,因此实际上还是复制了一个新对象/数组的引用,而不是原始对象/数组本身。
  2. 按引用传递 (Pass by Reference):

    • 使用&符号显式声明一个参数为引用传递时,函数接收到的是变量的内存地址,即直接指向原始变量的引用。
    • 在函数内部对引用变量所做的任何修改都会反映到函数外部的原始变量上。
    • 不仅限于改变变量的值,还可以通过引用更改变量本身,例如重新赋值为另一个变量或资源。

优缺点:

  • 按值传递的优点在于函数内部的操作不会影响外部作用域,保证了数据隔离性,但缺点是对于大型对象或数组而言,复制其引用会占用额外的内存和处理时间。
  • 按引用传递的优点是可以直接修改外部变量,减少内存开销,特别适用于大数据结构或者需要改变实参状态的情况,缺点是可能带来代码可读性和副作用的问题,如果开发者未意识到这一点,可能会引发意料之外的全局范围内的副作用。

总结起来,传值是复制一份新的副本,而传引用则是共享同一个内存空间。在实际编程中,根据需求选择合适的传递方式非常重要。

现在编程中经常采取MVC三层结构,请问MVC分别指哪三层,有什么优点?

MVC三层分别指:业务模型、视图、控制器,由控制器层调用模型处理数据,然后将数据映射到视图层进行显示,优点是:①可以实现代码的重用性,避免产生代码冗余;②M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式

AJAX的优势是什么?

ajax是异步传输技术,可以通过javascript实现,也可以通过JQuery框架实现,实现局部刷新,减轻了服务器的压力,也提高了用户体验。

在程序的开发中,如何提高程序的运行效率?

A、优化SQL语句,查询语句中尽量不使用select *,用哪个字段查哪个字段;少用子查询可用表连接代替;少用模糊查询;

B、数据表中创建索引;

C、对程序中经常用到的数据生成缓存。

对于大流量的网站,您采用什么样的方法来解决访问量问题?

A、有效使用缓存,增加缓存命中率

B、使用负载均衡

C、对静态文件使用cdn进行存储和加速

D、想法减少数据库的使用

E、查看出现统计的瓶颈在哪里

F、反向代理

语句include和require的区别是什么?为避免多次包含同一文件,可用什么语句代替它们?

区别:

在失败的时候:

  • include产生一个warning,而require产生直接产生错误中断
  • require在运行前载入
  • include在运行时载入

代替:

  • require_once
  • include_once

foo()和@foo()之间有什么区别?

@代表所有warning忽略

简述php的垃圾收集机制。

PHP的垃圾收集(Garbage Collection,GC)是自动释放已分配内存给不再使用的变量的过程。PHP使用了引用计数和写时复制技术来管理内存。

  1. 引用计数:当一个变量被赋值时,它的值的内存被增加一个引用计数。当该变量的引用被销毁时,这个计数会减少。一旦内存的引用计数减到0,PHP知道这块内存不再需要,并会在适当的时候释放它。
  2. 写时复制(Copy-on-Write, COW):当复制一个变量到另一个变量时,PHP不会真正复制内存,而是让两个变量共享同一块内存。只有当其中一个变量需要修改内存时,才会真正复制内存。

如何实现PHP的安全最大化?怎样避免SQL注入漏洞和XSS跨站脚本攻击漏洞?

答:基本原则:不对外界展示服务器或程序设计细节(屏蔽错误),不相信任何用户提交的数据(过滤用户提交)。

echo、print_r、print、var_dump区别

  • echo:语句结构;
  • print:是函数,有返回值
  • print_r:能打印数组,对象
  • var_dump:能打印对象数组,并且带数据类型

写出smarty模板的特点

速度快,编译型,缓存技术,插件机制,强大的表现逻辑

PHP如何实现页面跳转

方法一:php函数跳转,缺点,header头之前不能有输出,跳转后的程序继续执行,可用exit中断执行后面的程序。

php
header("Location:网址");//直接跳转
header("refresh:3;url=http://www.jsdaima.com");//三秒后跳转

方法二:利用meta

php
echo "";

如何把一个GB2312格式的字符串装换成UTF-8格式?

php
iconv('GB2312','UTF-8','js代码(http://www.jsdaima.com)是IT资源下载与IT技能学习平台。');

如果需要原样输出用户输入的内容,在数据入库前,要用哪个函数处理?

htmlspecialchars或者htmlentities

什么是 CSRF 攻击 ?XSS 攻击?如何防范?

CSRF,跨站请求伪造,攻击方伪装用户身份发送请求从而窃取信息或者破坏系统。

讲述基本原理:用户访问A网站登陆并生成了cookie,再访问B网站,如果A网站存在CSRF漏洞,此时B网站给A网站的请求(此时相当于是用户访问),A网站会认为是用户发的请求,从而B网站就成功伪装了你的身份,因此叫跨站脚本攻击。

CSRF防范:

A、合理规范api请求方式,GET,POST

B、对POST请求加token令牌验证,生成一个随机码并存入session,表单中带上这个随机码,提交的时候服务端进行验证随机码是否相同。

XSS,跨站脚本攻击。

防范:不相信任何输入,过滤输入。

安全对一套程序来说至关重要,请说说在开发中应该注意哪些安全机制?

A、防远程提交; B、防SQL注入,对特殊代码进行过滤; C、防止注册机灌水,使用验证码。

对json数据格式的理解?

JSON(javascript object Notation)是一种轻量级的数据交换格式,json数据格式固定,可以被多种语言用作数据的传递。

什么是事务?及其特性?

答:事务:是一系列的数据库操作,是数据库应用的基本逻辑单位。

事务特性:

A、原子性:即不可分割性,事务要么全部被执行,要么就全部不被执行。

B、一致性或可串性。事务的执行使得数据库从一种正确状态转换成另一种正确状态

C、隔离性。在事务正确提交之前,不允许把该事务对数据的任何改变提供给任何其他事务,

D、持久性。事务正确提交后,其结果将永久保存在数据库中,即使在事务提交后有了其他故障,事务的处理结果也会得到保存。

或者这样理解:

事务就是被绑定在一起作为一个逻辑工作单元的SQL语句分组,如果任何一个语句操作失败那么整个操作就被失败,以后操作就会回滚到操作前状态,或者是上有个节点。为了确保要么执行,要么不执行,就可以使用事务。要将有组语句作为事务考虑,就需要通过ACID测试,即原子性,一致性,隔离性和持久性。

什么是锁?

答:数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。

加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更新操作。

基本锁类型:锁包括行级锁和表级锁

索引的作用?和它的优点缺点是什么?

答:索引就一种特殊的查询表,数据库的搜索引擎可以利用它加速对数据的检索。它很类似与现实生活中书的目录,不需要查询整本书内容就可以找到想要的数据。索引可以是唯一的,创建索引允许指定单个列或者是多个列。缺点是它减慢了数据录入的速度,同时也增加了数据库的尺寸大小。

如何通俗地理解三个范式?

第一范式:1NF是对属性的原子性约束,要求属性具有原子性,不可再分解;

第二范式:2NF是对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性;

第三范式:3NF是对字段冗余性的约束,即任何字段不能由其他字段派生出来,它要求字段没有冗余。

主键、外键和索引的区别?

定义: 主键--唯一标识一条记录,不能有重复的,不允许为空 外键--表的外键是另一表的主键, 外键可以有重复的, 可以是空值 索引--该字段没有重复值,但可以有一个空值

作用: 主键--用来保证数据完整性 外键--用来和其他表建立联系用的 索引--是提高查询排序的速度

个数: 主键--主键只能有一个 外键--一个表可以有多个外键 索引--一个表可以有多个唯一索引

简述 private、 protected、 public修饰符的访问权限。

  • private : 私有成员, 在类的内部才可以访问。
  • protected : 保护成员,该类内部和继承类中可以访问。
  • public : 公共成员,完全公开,没有访问限制。

堆和栈的区别?

A、堆是程序运行期间动态分配的内存空间,你可以根据程序的运行情况确定要分配的堆内存的大小;

B、栈是编译期间就分配好的内存空间,因此你的代码中必须就栈的大小有明确的定义。

常用的魔术方法有哪些?举例说明

答:php规定以两个下划线(__)开头的方法都保留为魔术方法,所以建议大家函数名最好不用__开头,除非是为了重载已有的魔术方法。

__construct() 实例化类时自动调用。

destruct() 类对象使用结束时自动调用。

set() 在给未定义的属性赋值的时候调用。

get() 调用未定义的属性时候调用。

isset() 使用isset()或empty()函数时候会调用。

unset() 使用unset()时候会调用。

sleep() 使用serialize序列化时候调用。

wakeup() 使用unserialize反序列化的时候调用。

call() 调用一个不存在的方法的时候调用。

callStatic()调用一个不存在的静态方法是调用。

toString() 把对象转换成字符串的时候会调用。

__比如 echo。__invoke() 当尝试把对象当方法调用时调用。

set_state() 当使用var_export()函数时候调用。

__接受一个数组参数。__clone() 当使用clone复制一个对象时候调用。

$this和self、parent这三个关键词分别代表什么?在哪些场合下使用?

$this 当前对象

self 当前类

parent 当前类的父类

$this在当前类中使用,使用->调用属性和方法

self也在当前类中使用,不过需要使用::调用

parent在类中使用

作用域操作符::如何使用?都在哪些场合下使用?

调用类常量

调用静态方法

__autoload()方法的工作原理是什么?

答:使用这个魔术函数的基本条件是类文件的文件名要和类的名字保持一致。

当程序执行到实例化某个类的时候,如果在实例化前没有引入这个类文件,那么就自动执行__autoload()函数。

这个函数会根据实例化的类的名称来查找这个类文件的路径,当判断这个类文件路径下确实存在这个类文件后就执行include或者require来载入该类,然后程序继续执行,如果这个路径下不存在该文件时就提示错误。

使用自动载入的魔术函数可以不必要写很多个include或者require函数。

简述高并发网站解决方案。

A、前端优化(CND加速、建立独立图片服务器)

B、服务端优化(页面静态化、并发处理[异步|多线程]、队列处理)

C、数据库优化(数据库缓存[Memcachaed|Redis]、读写分离、分库分表、分区)

D、Web服务器优化(负载均衡、反向代理)

PHP遍历文件夹下所有文件

php
<?php
function read_all($dir){
    if(!is_dir($dir)) return false;
    $handle = opendir($dir);
    if($handle){
        while(($fl = readdir($handle)) !== false){
            $temp = $dir.$fl;
            //$fl !='.' && $fl != '..' 排除当前目录及父级目录
            if(is_dir($temp) && $fl!='.' && $fl != '..'){
                echo '目录:'.$temp.'<br>';
                read_all($temp);
            }else{
                if($fl !='.' && $fl != '..'){
                    echo '文件:'.$temp.'<br>';
                }
            }
        }
    }
}
read_all("./dir/");
?>

在命令行中运行php程序

php indx.php

A、从命令行运行php非常简单。但有些注意事项需要各位了解下,诸如$_SESSION之类的服务器变量是无法在命令行中使用的,其他代码的运行则和web服务器中完全一样; B、在命令行中执行php文件的好处之一就是可以通过脚本实现一些计划任务(crontab)的执行,而无须通过web服务器。

延伸1: php -v 显示当前PHP版本 php -m 显示当前php加载的有效模块 php -i 输出无html格式的phpinfo php --rf function

延伸2:向php脚本传递参数: 提示:命令行下执行php,是不走Apache/Nginx等这类东西的,没有什么http协议,所以get,post传参数根本不起作用,并且还会报错。有些时候需要在shell命令下把PHP当作脚本执行,比如定时任务。这就涉及到在shell命令下如何给php传参的问题,通常有三种方式传参。

A、使用$argv or $argc参数接收

php
echo "接收到{$argc}个参数";
 print_r($argv);

B、使用getopt函数

php
$param_arr = getopt('a:b:');
 print_r($param_arr);

C、提示用户输入

php
fwrite(STDOUT,'Please enter your name:');
 echo 'Your name is:'.fgets(STDIN);

你用什么方法检查PHP脚本的执行效率(通常是脚本执行时间)和数据库SQL的效率(通常是数据库Query时间),并定位和分析脚本执行和数据库查询的瓶颈所在?

A、PHP脚本的执行效率

  • a、代码脚本里计时;
  • b、xdebug统计函数执行次数和具体时间进行分析,最好使用工具winCacheGrind分析;
  • c、在线系统用strace跟踪相关进程的具体系统调用。

B、数据库SQL的效率

  • a、sql的explain(mysql),启用slow query log记录慢查询;
  • b、通常还要看数据库设计是否合理,需求是否合理等。

对于大流量的网站,您采用什么样的方法来解决各页面访问量统计问题。

A、确认服务器是否能支撑当前访问量; B、优化数据库访问; C、禁止外部访问链接(盗链), 比如图片防盗链; D、控制文件下载,尤其是大文件; E、使用不同主机分流(负载均衡); F、使用浏览统计软件,了解访问量,有针对性的进行优化。

MySQL数据库作发布系统的存储,一天五万条以上的增量,预计运维三年,怎么优化?

A、设计良好的数据库结构,允许部分数据冗余,尽量避免join查询,提高效率;

B、选择合适的表字段数据类型和存储引擎,适当的添加索引;

C、mysql库主从读写分离;

D、找规律分表,减少单表中的数据量提高查询速度;

E、添加缓存机制,比如memcached,redis等;

F、不经常改动的页面,生成静态页面;

G、书写高效率的SQL。比如 SELECT * FROM TABEL 改为 SELECT field_1, field_2, field_3 FROM TABLE。

Mysql的存储引擎,myisam和innodb的区别。

A、MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持;

B、MyISAM类型的表强调的是性能,其执行速度比InnoDB类型更快;

C、InnoDB不支持FULLTEXT类型的索引;

D、InnoDB中不保存表的具体行数,也就是说,执行select count(*) from table时,InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可;

E、对于AUTO_INCREMENT类型的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中,可以和其他字段一起建立联合索引;

F、DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的删除;

G、LOAD TABLE FROM MASTER操作对InnoDB是不起作用的,解决方法是首先把InnoDB表改成MyISAM表,导入数据后再改成InnoDB表,但是对于使用的额外的InnoDB特性(例如外键)的表不适用;

H、MyISAM支持表锁,InnoDB支持行锁。

MyISAM:成熟、稳定、易于管理,快速读取。一些功能不支持(事务等),表级锁。 InnoDB:支持事务、外键等特性、数据行锁定。空间占用大,不支持全文索引等。

设计模式

创建型:员工当生抽(原型、工厂、单例、生成器、抽象工厂)

结构型:是敲响外带组装(适配器、桥接、享元、外观、代理、组合、装饰)

行为型:被责命碟中装模防观测(备忘录、责任链、命令、迭代器、中介者、状态、模板方法、访问者、观察者、策略)

代码管理

通常一个项目是由一个团队去开发,每个人将自己写好的代码提交到版本服务器,由项目负责人按照版本进行管理,方便版本的控制,提高开发效率,保证需要时可以回到旧版本。

CGI、FastCGI、PHP-FPM 关系

在整个网站架构中,Web Server(如Apache)只是内容的分发者。举个栗子,如果客户端请求的是 index.html,那么Web Server会去文件系统中找到这个文件,发送给浏览器,这里分发的是静态数据。

如果请求的是 index.php,Web Server 收到这个请求后,会启动对应的 CGI 程序,这里就是 PHP 的解析器。接下来PHP解析器会解析 php.ini 文件,初始化执行环境,然后处理请求,再以规定 CGI 规定的格式返回处理后的结果,退出进程,Web server 再把结果返回给浏览器,这就是一个完整的动态PHP Web访问流程。

  • **Web Server :**一般指 Apache、Nginx、IIS、Lighttpd、Tomcat 等服务器。
  • Web Application: 一般指 PHP、Java、Asp.net 等应用程序。
  • **CGI:**是 Web Server 与 Web Application 之间数据交换的一种协议。
  • **FastCGI:**同 CGI,是一种通信协议,但比 CGI 在效率上做了一些优化。同样,SCGI 协议与 FastCGI 类似。
  • **PHP-CGI:**是 PHP (Web Application)对 Web Server 提供的 CGI 协议的接口程序。
  • **PHP-FPM:**是 PHP(Web Application)对 Web Server 提供的 FastCGI 协议的接口程序,额外还提供了相对智能一些任务管理。

PHP 的垃圾收集机制

PHP 可以自动进行内存管理,清除不再需要的对象。PHP 使用了引用计数(reference counting)的垃圾回收(garbage collection)机制。每个对象都内含一个引用计数器,当 reference 连接到对象,计数器加1。当reference离开生存空间或被设为NULL,计数器减1。当某个对象的引用计数器为零时,PHP 释放其所占的内存空间

CLI 模式的生命周期

阶段调用函数作用
模块初始化阶段php_module_startup()主要进行 PHP 框架, zend 引擎的初始化操作
请求初始化阶段php_request_startup()对 fpm 来说, 是在 worker 进程读取,并解析完请求数据后的一个阶段
脚本执行阶段php_execute_script()解析 php 语法,生成抽象语法树
请求关闭阶段php_request_shutdown()请求结束时执行
模块关闭阶段php_module_shutdown()进程关闭时执行