首页/发现新知
视界 · 深度阅读

Nginx FastCGI 实现 PHP 动态页面解析的原理与配置

本文详解Nginx通过FastCGI协议与PHP-FPM协同实现PHP动态页面解析的原理与配置,涵盖CGI/FastCGI演进、PHP-FPM进程模型、Nginx fastcgi_pass核心指令,感兴趣的朋友跟随小编一起看看吧

目录
  • 1.1 CGI、FastCGI、PHP-FPM 基础概念
    • CGI 的由来
    • 为什么会有 FastCGI
    • 什么是 PHP-FPM?
  • 1.2 FastCGI 核心配置指令
    • 1.3 实战案例:Nginx + PHP-FPM(同机部署)
      • 1.3.1 PHP 8.3.30 源码编译部署
        • 1、下载源码包与依赖包
        • 2、解压源码包
        • 3、安装编译依赖
        • 4、configure 编译配置
        • 5、PHP-FPM 配置文件初始化
        • 6、配置 systemd 管理 php-fpm
        • 7、配置系统环境变量
      • 1.3.2 Nginx 整合 PHP-FPM,访问测试
      • 1.4 PHP 动态扩展:Memcache 缓存模块
        • 1.4.1 部署 Memcached 服务
          • 1.4.2 编译 memcache PHP 扩展
            • 1.4.3 AB 压测对比(PHP 层缓存)
            • 1.5 Nginx + Memcache 高速缓存(srcache+memc 模块)
              • 1.5.1 重新编译 Nginx,添加 memc、srcache 模块
                • 1.5.2 Nginx 配置 srcache 缓存
                  • 1.5.3 压测验证 Nginx 层缓存效果

                  前面章节学习的 Nginx 七层、四层负载均衡都偏向静态资源与 TCP/UDP 流量转发。Nginx 本身只能处理静态 HTML、图片等静态资源,不能直接解析 PHP 这类动态脚本。FastCGI 就是 Nginx 和 PHP 解析器之间通信的标准协议,用来实现动态网页解析。

                  1.1 CGI、FastCGI、PHP-FPM 基础概念

                  CGI 的由来

                  最早的 Web 服务器只能简单地响应浏览器发来的 HTTP 请求,并将存储在服务器上的 HTML 文件返回给浏览器,也就是静态 HTML 文件,但是后期随着网站功能增多网站开发也越来越复杂,以至于出现动态技术,比如像 php (1995 年)、Java (1995)、Python (1991) 语言开发的网站。 Nginx/Apache 服务器并不能直接运行 php、Java 这样的文件,Apache 是通过打补丁的方式支持,Nginx 则通过第三方协议交互:将客户端请求转发给第三方服务处理,第三方服务新建进程处理请求,处理完成返回数据给 Nginx 并回收进程,最后 Nginx 返回给客户端。 这个约定就是通用网关接口(Common Gateway Interface,简称 CGI),CGI 是 web 服务器和外部应用程序之间的接口标准,是 cgi 程序和 web 服务器之间传递信息的标准化接口。

                  为什么会有 FastCGI

                  CGI 协议虽然解决了语言解析器和 Web Server 之间通讯的问题,但是它的效率很低:Web Server 每收到一个请求都会创建一个 CGI 进程,PHP 解析器都会解析 php.ini 文件,初始化环境,请求结束的时候再关闭进程。每一个请求都要重复创建、初始化、销毁进程,资源开销巨大。 FastCGI 是 CGI 的优化版本:进程处理完请求之后不会直接关闭,进程保持常驻,可以持续处理多个请求,省去反复创建销毁进程、重复初始化环境的开销,大幅提升动态脚本处理性能。

                  什么是 PHP-FPM?

                  PHP-FPM(FastCGI Process Manager:FastCGI 进程管理器),是一个实现了 FastCGI 协议的程序,并且自带完善的进程管理功能。

                  • master 进程:全局只有 1 个,负责监听端口,接收来自 Nginx 的请求,管理 worker 进程
                  • worker 进程:多个,每个 worker 内置 PHP 解析器,真正执行 PHP 代码逻辑

                  Nginx 模块依赖:ngx_http_fastcgi_module,默认编译 Nginx 时一般自带,专门用来转发 fastcgi 请求。

                  1.2 FastCGI 核心配置指令

                  fastcgi_pass address:port;
                  #转发请求到后端fastcgi服务地址,支持location、if in location
                  fastcgi_index name;
                  #fastcgi默认首页,常用 fastcgi_index index.php;
                  fastcgi_param parameter value [if_not_empty];
                  #传递环境变量、Nginx内置变量给PHP-FPM
                  fastcgi_param REMOTE_ADDR $remote_addr;     #客户端源IP
                  fastcgi_param REMOTE_PORT $remote_port;     #客户端端口
                  fastcgi_param SERVER_ADDR $server_addr;     #Nginx服务IP
                  fastcgi_param SERVER_PORT $server_port;     #Nginx服务端口
                  fastcgi_param SERVER_NAME $server_name;     #虚拟主机server_name

                  基础模板示例:

                  location ~ \.php$ {
                      root /scripts;
                      fastcgi_pass 127.0.0.1:9000;
                      fastcgi_index index.php;
                      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                      include fastcgi_params;
                  }

                  include fastcgi_params; 文件由 Nginx 自带,里面预先定义了大量 FastCGI 需要传递的参数,简化配置。

                  1.3 实战案例:Nginx + PHP-FPM(同机部署)

                  推荐源码编译 PHP,可以自由开启扩展、自定义安装路径。PHP 官网:www.php.net

                  1.3.1 PHP 8.3.30 源码编译部署

                  1、下载源码包与依赖包

                  [root@Nginx ~]# wget https://www.php.net/distributions/php-8.3.30.tar.gz
                  [root@Nginx ~]# wget https://mirrors.aliyun.com/rockylinux/9.7/devel/x86_64/os/Packages/o/oniguruma-devel-6.9.6-1.el9.6.x86_64.rpm

                  2、解压源码包

                  [root@Nginx ~]# tar zxf php-8.3.30.tar.gz
                  [root@Nginx ~]# ls
                  anaconda-ks.cfg                lee.png            nginx-1.29.4.tar.gz  test.c
                  daolian.png                    nginx-1.28.1       php-8.3.30
                  echo-nginx-module-0.64         nginx-1.28.1.tar.gz php-8.3.30.tar.gz
                  echo-nginx-module-0.64.tar.gz  nginx-1.29.4       test
                  [root@Nginx ~]# cd php-8.3.30

                  3、安装编译依赖

                  [root@Nginx ~]# dnf install gcc -y
                  [root@Nginx ~]# dnf install systemd-devel.x86_64 -y
                  [root@Nginx ~]# dnf install libxml2-devel.x86_64 -y
                  [root@Nginx ~]# dnf install sqlite-devel.x86_64 -y
                  [root@Nginx ~]# dnf install libcurl-devel.x86_64 -y
                  [root@Nginx ~]# dnf install libpng-devel.x86_64 -y
                  [root@Nginx ~]# dnf search oniguruma -y
                  #安装oniguruma-devel依赖,依赖缺失使用--nodeps强制安装
                  [root@Nginx ~]# rpm -ivh oniguruma-devel-6.9.6-1.el9.6.x86_64.rpm --nodeps
                  

                  4、configure 编译配置

                  [root@Nginx ~]# cd php-8.3.30/
                  [root@Nginx php-8.3.30]# ./configure \
                  --prefix=/usr/local/php \
                  --with-config-file-path=/usr/local/php/etc \
                  --enable-fpm  \
                  --with-fpm-user=nginx \
                  --with-fpm-group=nginx \
                  --with-curl \
                  --with-iconv \
                  --with-mhash \
                  --with-zlib \
                  --with-openssl \
                  --enable-mysqlnd \
                  --with-mysqli \
                  --with-pdo-mysql \
                  --disable-debug \
                  --enable-sockets \
                  --enable-soap \
                  --enable-xml \
                  --enable-ftp \
                  --enable-gd \
                  --enable-exif \
                  --enable-mbstring \
                  --enable-bcmath \
                  --with-fpm-systemd
                  

                  编译 & 安装

                  [root@Nginx php-8.3.30]# make && make install
                  

                  5、PHP-FPM 配置文件初始化

                  [root@Nginx php-8.3.30]# cd /usr/local/php/etc
                  [root@Nginx etc]# cp -p php-fpm.conf.default  php-fpm.conf
                  [root@Nginx etc]# vim php-fpm.conf
                  

                  修改 pid 配置:

                  [global]
                  pid = run/php-fpm.pid
                  

                  进入 pool 配置目录:

                  [root@Nginx etc]# cd php-fpm.d/
                  [root@Nginx php-fpm.d]# cp www.conf.default www.conf
                  [root@Nginx php-fpm.d]# vim www.conf
                  #修改监听地址
                  listen = 0.0.0.0:9000
                  

                  拷贝生产版 php.ini,修改时区:

                  [root@Nginx php-fpm.d]# cp /root/php-8.3.30/php.ini-production  /usr/local/php/etc/php.ini
                  [root@Nginx php-fpm.d]# vim /usr/local/php/etc/php.ini
                  date.timezone = Asia/Shanghai
                  

                  6、配置 systemd 管理 php-fpm

                  [root@Nginx ~]# cp /root/php-8.3.30/sapi/fpm/php-fpm.service /lib/systemd/system/
                  [root@Nginx ~]# vim /lib/systemd/system/php-fpm.service
                  #注释掉ProtectSystem=full
                  #ProtectSystem=full
                  

                  重载 unit、开机自启并启动服务

                  [root@Nginx ~]# systemctl daemon-reload
                  [root@Nginx ~]# systemctl enable --now php-fpm
                  #查看监听端口
                  [root@Nginx ~]# netstat -antlupe | grep php
                  tcp        0      0 0.0.0.0:9000            0.0.0.0:*               LISTEN      0          329917     165562/php-fpm: mas
                  

                  7、配置系统环境变量

                  [root@Nginx ~]# vim ~/.bash_profile
                  export PATH=$PATH:/usr/local/nginx/sbin:/usr/local/php/sbin:/usr/local/php/bin
                  [root@Nginx ~]# source  ~/.bash_profile
                  #验证
                  [root@Nginx ~]# php -m
                  

                  1.3.2 Nginx 整合 PHP-FPM,访问测试

                  #创建网站目录
                  [root@Nginx ~]# mkdir /webdata/dragon.org/php/html -p
                  #新建phpinfo测试页
                  [root@Nginx ~]# vim /webdata/dragon.org/php/html/index.php
                  

                  index.php 内容:

                  
                  

                  编辑 Nginx 子配置文件:

                  [root@Nginx ~]# vim /usr/local/nginx/conf.d/php.conf
                  
                  server {
                      listen 80;
                      server_name php.dragon.org;
                      root /webdata/dragon.org/php/html;
                      location ~ \.php$ {
                          fastcgi_pass 127.0.0.1:9000;
                          fastcgi_index index.php;
                          include fastcgi.conf;
                      }
                  }

                  重载 Nginx 配置,浏览器访问 php.dragon.org/index.php 查看 php 信息页面。

                  1.4 PHP 动态扩展:Memcache 缓存模块

                  Memcached 不是数据库,是纯内存分布式 K-V 缓存系统。原理:内存换速度,LRU 淘汰策略,数据不保存在磁盘,适合缓存高频查询数据,减少数据库压力。 软件地址:http://pecl.php.net/package/memcache

                  1.4.1 部署 Memcached 服务

                  [root@Nginx ~]# dnf install memcached.x86_64 -y
                  [root@Nginx ~]# vim /etc/sysconfig/memcached
                  
                  PORT="11211"
                  USER="memcached"
                  MAXCONN="1024"
                  CACHESIZE="64"
                  OPTIONS="-l 0.0.0.0,::1"

                  启动服务

                  [root@Nginx ~]# systemctl enable --now memcached.service
                  [root@Nginx ~]# netstat -antlupe | grep memcache
                  tcp        0      0 0.0.0.0:11211           0.0.0.0:*               LISTEN      991        437305     166169/memcached
                  tcp6       0      0 ::1:11211               :::*                    LISTEN      991        437306     166169/memcached
                  

                  1.4.2 编译 memcache PHP 扩展

                  [root@Nginx ~]# php -m
                  [root@Nginx ~]# tar zxf memcache-8.2.tgz
                  [root@Nginx ~]# cd memcache-8.2/
                  [root@Nginx memcache-8.2]# dnf install autoconf -y
                  [root@Nginx memcache-8.2]# phpize
                  [root@Nginx memcache-8.2]# ./configure  && make && make install
                  #查看编译生成的扩展文件
                  [root@Nginx memcache-8.2]# ls /usr/local/php/lib/php/extensions/no-debug-non-zts-20230831/
                  memcache.so  opcache.so
                  

                  修改 php.ini 加载扩展

                  [root@Nginx memcache-8.2]# vim /usr/local/php/etc/php.ini
                  extension=memcache
                  

                  重启 php-fpm 验证扩展

                  [root@Nginx memcache-8.2]# systemctl restart php-fpm.service
                  [root@Nginx memcache-8.2]# php -m  | grep memcache
                  memcache
                  

                  1.4.3 AB 压测对比(PHP 层缓存)

                  准备 memcache 管理页面:

                  [root@Nginx memcache-8.2]# vim memcache.php
                  define('ADMIN_USERNAME','admin');
                  define('ADMIN_PASSWORD','123');
                  $MEMCACHE_SERVERS[] = '172.25.254.10:11211';
                  

                  拷贝到网站目录:

                  [root@Nginx memcache-8.2]# cp -p memcache.php  /webdir/timinglee.org/php/html/
                  [root@Nginx memcache-8.2]# cp -p example.php /webdir/timinglee.org/php/html/
                  
                  • 关闭 memcached 压测
                  [root@Nginx memcache-8.2]# systemctl stop memcached.service
                  [root@Nginx memcache-8.2]# ab -n 1000 -c 300 php.dragon.org/index.php
                  

                  压测结果摘要:大量请求失败,并发压力下性能较差

                  Complete requests:   1000
                  Failed requests:     994
                  Requests per second: 5000.98 [#/sec] (mean)
                  • 开启 memcached 压测
                  [root@Nginx memcache-8.2]# systemctl start memcached.service
                  [root@Nginx memcache-8.2]# ab -n 1000 -c 300 php.dragon.org/index.php
                  

                  压测摘要:失败请求数量大幅下降,缓存生效

                  Complete requests:   1000
                  Failed requests:     105
                  Requests per second: 5174.32 [#/sec] (mean)

                  小结:这一层是PHP 代码层面调用 memcache 缓存,缓存逻辑写在 PHP 程序里。下面我们实现 Nginx 层直接缓存,由 Nginx 优先读取 memcache。

                  1.5 Nginx + Memcache 高速缓存(srcache+memc 模块)

                  原理:第三方模块 memc-nginx-module + srcache-nginx-module,让 Nginx 直接读写 memcache。请求到达 Nginx 优先去 memcache 读取缓存,命中直接返回;未命中才转发给 fastcgi 处理,处理完成后存入 memcache,这一层缓存是 Nginx 侧,性能更高。 原生 Nginx 不自带这两个模块,需要重新编译 Nginx 添加第三方模块。

                  1.5.1 重新编译 Nginx,添加 memc、srcache 模块

                  [root@Nginx ~]# systemctl stop nginx.service
                  #备份原有配置
                  [root@Nginx ~]# cp /usr/local/nginx/conf/   /mnt/ -r
                  [root@Nginx ~]# rm -fr /usr/local/nginx/
                  [root@Nginx ~]# rm -rf nginx-1.29.4 nginx-1.28.1
                  #解压源码和第三方模块包
                  [root@Nginx ~]# tar zxf nginx-1.28.1.tar.gz
                  [root@Nginx ~]# cd nginx-1.28.1/
                  [root@Nginx ~]# tar zxf srcache-nginx-module-0.33.tar.gz
                  [root@Nginx ~]# tar zxf memc-nginx-module-0.20.tar.gz
                  [root@Nginx ~]# cd nginx-1.28.1/
                  

                  编译参数

                  [root@Nginx nginx-1.28.1]# ./configure  --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --add-module=/root/memc-nginx-module-0.20 --add-module=/root/srcache-nginx-module-0.33
                  [root@Nginx nginx-1.28.1]# make && make install
                  

                  恢复备份配置文件

                  [root@Nginx ~]# cd /usr/local/nginx/conf
                  [root@Nginx conf]# rm -fr nginx.conf
                  [root@Nginx conf]# cp /mnt/conf/nginx.conf /mnt/conf/conf.d/ . -r
                  [root@Nginx conf]# systemctl start nginx.service
                  

                  1.5.2 Nginx 配置 srcache 缓存

                  [root@Nginx conf]# vim /usr/local/nginx/conf/conf.d/php.conf
                  
                  upstream memcache {
                      server 127.0.0.1:11211;
                      keepalive 512;
                  }
                  server {
                      listen 80;
                      server_name php.timinglee.org;
                      root /webdir/timinglee.org/php/html;
                      index index.php index.html;
                      location /memc {
                          internal;
                          memc_connect_timeout 100ms;
                          memc_send_timeout 100ms;
                          memc_read_timeout 100ms;
                          set $memc_key $query_string;
                          set $memc_exptime 300;
                          memc_pass memcache;
                      }
                      location ~ \.php$ {
                          set $key $uri$args;
                          srcache_fetch GET /memc $key;
                          srcache_store PUT /memc $key;
                          fastcgi_pass 127.0.0.1:9000;
                          fastcgi_index index.php;
                          include fastcgi.conf;
                      }
                  }

                  重载 Nginx

                  [root@Nginx conf]# nginx  -s reload
                  

                  1.5.3 压测验证 Nginx 层缓存效果

                  [root@Nginx conf]# ab -n 10000 -c500 http://php.dragon.org/index.php
                  

                  压测结果摘要:缓存命中后无失败请求,QPS 大幅提升

                  Complete requests:  10000
                  Failed requests:     0
                  Requests per second: 26289.09 [#/sec] (mean)

                  到此这篇关于Nginx FastCGI 实现 PHP 动态页面解析的文章就介绍到这了,更多相关Nginx FastCGI PHP 动态页面内容请搜索爱读视界以前的文章或继续浏览下面的相关文章希望大家以后多多支持爱读视界!

                  您可能感兴趣的文章:

                  • Nginx中fastcgi_cache实现PHP页面缓存加速
                  • Nginx FastCGI缓存的实现示例
                  • 利用nginx + fastcgi实现图片识别服务器
                  • PHP+FastCGI+Nginx配置PHP运行环境
                  • Nginx(PHP/fastcgi)的PATH_INFO问题
                  • Nginx+PHP(FastCGI)搭建高并发WEB服务器(自动安装脚本)第二版
                  • Nginx0.5.33+PHP5.2.5(FastCGI)搭建胜过Apache10倍的Web服务器
                  • PHP统计nginx访问日志中的搜索引擎抓取404链接页面路径
                  读到这里,发现更多一点。探索更多内容 ↗