PHP7内核实现原理-基本架构
菜皮日记 / 7 / 2023-09-09 10:59:49

发展史

PHP 最早是由 Lerdorf 于 1995年,使用 Perl 语言,以 Personal Home Page Tools (PHP Tools) 的形式创建的,目的是为了方便记录个人网站的访客记录和支持留言本等功能,此时称为 PHP 1

后来越来越多的网站开始使用 PHP 并希望能提供更多的功能,之后 Lerdorf 将 PHP 开源,此时称为 PHP 2

1997 年两个以色列程序员 Zeev Suraski 和 Andi Gutmans 重写了 PHP 的解析器,并于 1998 年正发布,此为 PHP 3,并从此开始 PHP 改为 Hypertext Preprocessor,新版的解析器命名为 Zend Engine。Zend 的命名来自于两位作者的名字。

2000 年,以 Zend 1.0 为基础的 PHP 4 发布。2004 年,以 Zend 2.0 为基础的 PHP 5 发布,至此 PHP 支持了面向对象、PDO、命名空间等特性,性能方面也大幅提升。

2015 年 12 月 3 日 PHP 7 发布,重构了 PHP 中很多重要且常用的数据结构,内存占用得到显著优化,性能也得到了大幅提升。

PHP 的组成

  • SAPI:

    PHP 本身可以理解为一组库函数,而 SAPI 则是其接入层,应用程序通过调用 SAPI 来间接调用 PHP 的函数,类似于 Shell 与 Linux 内核的关系。严格来讲 SAPI 不算是 PHP 内核的一部分。

  • Zend 引擎:

    Zend 引擎是 PHP 和核心,是 PHP 最最基础的部分。Zend 分为两部分:

    • 编译器:将应用层的 PHP 代码编译为抽象语法树 AST,进一步编译为可执行的 opcodes 。
    • 执行器:负责执行 opcodes

示意图:

SAPI 介绍

SAPI 即 Server Application Programming Interface,是应用程序与 PHP 内核交互的一套 API 规范。常见的 SAPI 实现有:

  • Apache mod_php 模块:

    该模块实现 SAPI 规范,使得让 Apache 与 PHP 做交互。

  • FastCGI/FPM:

    一般配合 Nginx 服务器处理 web 请求。

  • cli:

    命令行中执行 PHP 。

上层应用与实现了 SAPI 的模块做交互,上下两层都遵循 SAPI 规范:

FPM(FastCGI Process Manager) 介绍

要了解 FPM,首先要了解 CGI,CGI (Common Gateway Interface)定义了 Web 服务器和应用程序交互的规范,FastCGI 是在其之上优化改进的结果,增加了worker 常驻等特性,不用每次都 fork 新的进程来处理请求。

FastCGI 采用多进程模型,与 web 服务器配合处理 web 请求。服务器负责处理解析网络请求,之后交给 FastCGI,FastCGI 将请求交给其管理的 worker pool,由具体一个 worker 来处理请求。

FastCGI 中的 master 进程通过共享内存的方式获取 worker 进程的状态,通过发送信号的方式管理 worker。

FastCGI 也是一种协议,而 FPM 则是实现了这种协议的进程管理器。

FPM 可以同时监听多个端口,一个端口对应一个 worker pool

FPM 配置,监听在 unix sock 上

; worker pool名称
[www]
user = www
group = www

; 配置worker pool接收FastCGI请求的地址
; 可以是ip:port 也可以是unix sock
; The address on which to accept FastCGI requests.
; Valid syntaxes are:
;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific IPv4 address on
;                            a specific port;
;   '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on
;                            a specific port;
;   'port'                 - to listen on a TCP socket to all addresses
;                            (IPv6 and IPv4-mapped) on a specific port;
;   '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory.
listen = /run/php7-cgi.sock

listen.owner = www
listen.group = www
listen.mode = 0660
pm = dynamic
pm.max_children = 20
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 20

Nginx 与 FPM 通过 unix sock 交互配置

server
{
    listen 80;
    server_name xxx.xxx.com;
    index index.html index.php;
    root  /home/xxx/public;

    location / {
        if (!-e $request_filename){
            rewrite ^/(.*) /index.php last;
        }
    }
    location ~ [^/]\.php(/|$)
    {
        try_files $uri =404;
                # Nginx 转发请求给 PHP
        fastcgi_pass  unix:/run/php7-cgi.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
    }
}

FPM master 管理 worker 的几种方式:

  • static:初始化就固定 worker 数不变
  • dynamic:动态调整 worker 数量
  • ondemand:相当于懒加载,一开始不创建 worker,之后请求到来在创建。

本文由mdnice多平台发布


PHP7内核实现原理-基本架构
作者
菜皮日记
许可协议
CC BY 4.0
发布于
2023-09-09
修改于
2023-09-28
Bonnie image
尚未登录