1.1.1. 10.PHP-FPM 与 Nginx


1.基础

静态数据

在整个网站架构中,web server 只是一个内容分发者。如客户端请求的是 index.html 时,web server 会在文件系统中找到这个 index.html 文件,发送给浏览器,这里分发的事静态数据。 静态数据

动态数据

如果请求的是 index.php 文件,那么 web server 会将客户端的请求数据,通过 CGI 协议转发给 PHP 解析器来处理。

动态数据

当 web server 收到 index.php 请求后,会启动相应的 CGI 程序,CGI 程序会找到 PHP 的配置文件 php.ini 进行程序的初始化,然后处理请求,再以规定的 CGI 的规定转换为相应的格式返回给 web server,最后返回给客户端。这就是一个完整的访问流程。

2.几个概念:

  • Web Application:指 Apache 、Nginx
  • Web Server:指 PHP、Java 等。
  • CGI:通用网关接口(Common Gateway Interface),是 Web Server 和 Web Application 之间的一种数据交换协议。
    • CGI 就相当于两个不同国家的人用来交流的翻译器。Web Server 将数据(url,查询字符串,POST 数据,HTTP header 等)通过标准的输入传递给 Web Application , Web Application 根据配置文件初始化后(如 PHP 解析器会先根据 php.ini 文件进行初始化),再处理数据,通过标准的输出返回给 Web Server。
    • 但是 CGI 有个蛋疼的地方,就是每一次web请求都会有启动和退出过程,也就是最为人诟病的 fork-and-execute 模式,这样一在大规模并发下,就死翘翘了。
  • FastCGI:同 CGI,是一种通信协议,在 CGI 的效率上做了优化。

    • 做了哪些优化呢,“PHP 解析器会先根据 php.ini 文件进行初始化” 这里。每次执行程序都会执行一次这个操作,随着 web 的兴起,高并发是常态,这样低效且浪费资源的方式,导致处理每个请求都耗费很长时间。
    • FastCGI 会先启动一个 master,解析配置文件,初始化执行环境,然后在启动多个 worker。当有新请求过来时,通过 master 会传递给 worker 然后立即执行下一给请求,这样就避免了重复劳动,提高了效率。
    • 当 worker 不够用可以根据配置提前启动几个 worker 等着。当 worker 多余时,也会停掉一些,这样就提高了性能,节约了资源。
    • FastCGI 是一个常驻性版本的 CGI,它可以一直执行,不用每次都花费时间去 fork。
    • FastCGI 接口方式采用 C/S 的架构,可以将 Web Server 和 Web Application 分开,同时在服务器上启动一个或多个守护进程。当有请求过来时,直接发送给 FastCGI 进程处理,将结果返回给浏览器。这种方式可以让 Web Server 专心处理静态数据或者将动态数据传给 Web Application ,很大程度上提高了性能。

    FastCGI运行方式

  • PHP-CGI:是 PHP(Web Application)对 Web Server 提供的 CGI 的接口程序。
    • 官方出品的 CGI 程序。但是性能太差。
    • 在修改了 php.ini 文件后,必须重启 PHP-CGI 才能让新 php.ini 生效。无法平滑重启
    • 直接杀死 PHP-CGI 后程序将无法执行。
  • PHP-FPM:是 PHP(Web Application)对 Web Server 提供的 FastCGI 的接口程序。还提供了相对智能的任务管理。
    • PHP-FPM 是 FastCGI 的具体实现,负责管理一个进程池,处理 Web Server 的请求。
    • 是一个 PHP 进程管理器,包含 master 和 worker 两种进程。master 进程只有一个,负责监听端口,接收来自服务器的请求,而 worker 根据配置可以有多个,每个进程内部嵌入了一个 php 解释器,是 PHP 代码真正执行的地方。
    • 具体步骤如下:
      1. FPM 的 master 接受请求
      2. master 根据配置指定给 worker 进行请求处理,如没有可用 worker 则返回错误,nginx 报 502。
      3. worker 请求超时,返回错误,nginx 报 504。
      4. 请求处理结束,返回结果。
    • 当修改了 php.ini 之后,PHP-CGI 程序是无法重启的。所以 PHP-FPM 的做法是当旧的进程处理完旧请求后,杀死。通过启动新的 worker 进程来启用新的配置,这样实现平滑重启。 运行方式升级过程

3.nginx

Nginx 不仅仅是一个 Web 服务器,也是一个功能强大的 Proxy 服务器。提供了很多协议,如 HTTP,当然也有与 FPM 相关的 FastCGI 协议。Nginx 提供了 FastCGI 模块来将 HTTP 请求映射为对应的 FastCGI 请求。

Nginx 的 FastCGI 模块提供了 fastcgi_param 指令,主要处理参数的映射关系。这些都是基本不变的,会单独放在一个文件中。

$ cat /usr/local/nginx/conf/fastcgi.conf

fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  REQUEST_SCHEME     $scheme;
fastcgi_param  HTTPS              $https if_not_empty;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

在 Nginx 的服务器配置中,最重要的 fastcgi_pass 指令,这个指令用于监听 FPM 进程地址,Nginx 会把所有的 php 请求 翻译成 FastCGI 请求再发送给这个地址。下面一个服务器配置实例。

server {
    listen 80;
    server_name test.me;
    root /usr/local/web/myproject/public;
    index index.php index.html index.htm;

    access_log /usr/local/nginx/logs/test-access.log;
    error_log  /usr/local/nginx/logs/test-error.log;

    location / {
      try_files $uri $uri/ /index.php?$query_string;
    }

    location ~\.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME /usr/local/web/myproject/public/$fastcgi_script_name;
        fastcgi_pass unix:/usr/local/php/var/run/php-fpm.sock;
        fastcgi_index index.php;
    }
}

在这个配置文件中,我们新建了一个虚拟主机,监听端口 80,项目根目录为 /usr/local/web/myproject/public。然后通过 location 指令,将所有以 .php 结尾的请求都交给 FastCGI 模块处理。从而把所有的PHP请求都交给了FPM处理,从而完成Nginx到FPM的闭环。 运行流程

一次完整的请求过程

  1. 在浏览器输入网之后,请求会发送给某个 ip 地址下的 80 端口。
  2. 负责监听 80 端口的 nginx 会接收到这个请求,由于这是一个 HTTP 请求,需要交给对应的模块处理。
  3. 经过初始化和解析请求,确定请求是在 .php 文件中。说明这是一个 PHP 请求,需要 PHP 模块来解析。但是 PHP 和 nginx 不能直接通信,他们之间需要 fastcgi 协议来交换数据。
  4. 而 php-fpm 正是 fastcgi 的实现,所以请求转到了 php-fpm。php-fpm 有一个 master 主进程,主进程负责监听端口和接受来自服务器的请求。主进程下包含若干个 worker,每个 worker 下都有一个 php 解释器。php 解释器处理完请求后,返回给 php-fpm 再交给 nginx 发送给浏览器,完成了一次请求过程。
Copyright © Kagami丶 2019 all right reserved,powered by Gitbook该文件修订时间: 2019-12-10 20:25:25

results matching ""

    No results matching ""