前情提要:本篇博客详细的介绍了FastCGI及相关的实战案例,同时还介绍了PHP的动态扩展模块memcached以及相关整合及实验案例
环境:
系统:RHEL9.6
nginx版本:nginx version: nginx/1.28.2
一、FastCGI简介


1.1 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服务器之间传递信息的标准化接口。

1.2 为什么会有FastCGI
CGI协议虽然解决了语言解析器和 Web Server 之间通讯的问题,但是它的效率很低,因为 Web Server 每收到一个请求都会创建一个CGI进程,PHP解析器都会解析php.ini文件,初始化环境,请求结束的时候再关闭进程,对于每一个创建的CGI进程都会执行这些操作,所以效率很低,而FastCGI是用来提高CGI性能的,FastCGI每次处理完请求之后不会关闭掉进程,而是保留这个进程,使这个进程可以处理多个请求。这样的话每个请求都不用再重新创建一个进程了,大大提升了处理效率。
1.3 什么是PHP-FPM
PHP-FPM(FastCGI Process Manager:
-
FastCGI进程管理器)是一个实现了Fastcgi的程序,并且提供进程管理的功能。
-
进程包括master进程和worker进程。master进程只有一个,负责监听端口,接受来自web server 的请求
-
worker进程一般会有多个,每个进程中会嵌入一个PHP解析器,进行PHP代码的处理。
二、FastCGI配置指令简介
Nginx基于模块ngx_http_fastcgi_module实现通过fastcgi协议将指定的客户端请求转发至php-fpm处理,其配置指令如下
cpp
fastcgi_pass address:port;
#转发请求到后端服务器,address为后端的fastcgi server的地址,可用位置:location, if in location
fastcgi_index name;
#fastcgi默认的主资源,示例:fastcgi_index index.php;
fastcgi_param parameter value [if_not_empty];
#设置传递给FastCGI服务器的参数值,可以是文本,变量或组合,可用于将Nginx的内置变量赋值给自定义key
fastcgi_param REMOTE_ADDR $remote_addr; #客户端源IP
fastcgi_param REMOTE_PORT $remote_port; #客户端端口
fastcgi_param SERVER_ADDR $server_addr; #请求的服务器IP地址
fastcgi_param SERVER_PORT $server_port; #请求的服务器端口
fastcgi_param SERVER_NAME $server_name; #请求的server name
#Nginx默认配置示例:
location ~ \.php$ {
root /scripts;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; #默认脚本路径
#fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params; #此文件默认系统已提供,存放的相对路径为prefix/conf
}
三、FastCGI实战案例 : Nginx与php-fpm在同一服务器
编译安装更方便自定义参数或选项,推荐大家使用源码编译
官方网站:<www.php.net>
3.1 PHP源码编译
- 下载源码包和依赖
cpp
# 下载源码包和依赖
[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 #依赖
- 解压
cpp
[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
- 源码编译
cpp
# 下载依赖
[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
[root@Nginx ~]# rpm -ivh oniguruma-devel-6.9.6-1.el9.6.x86_64.rpm # 找不到依赖就强制安装
警告:oniguruma-devel-6.9.6-1.el9.6.x86_64.rpm: 头V4 RSA/SHA256 Signature, 密钥 ID 350d275d: NOKEY
错误:依赖检测失败:
oniguruma = 6.9.6-1.el9.6 被 oniguruma-devel-6.9.6-1.el9.6.x86_64 需要
[root@Nginx ~]# rpm -ivh oniguruma-devel-6.9.6-1.el9.6.x86_64.rpm --nodeps
警告:oniguruma-devel-6.9.6-1.el9.6.x86_64.rpm: 头V4 RSA/SHA256 Signature, 密钥 ID 350d275d: NOKEY
Verifying... ################################# [100%]
准备中... ################################# [100%]
正在升级/安装...
1:oniguruma-devel-6.9.6-1.el9.6 ################################# [100%]
[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 \ #用cgi方式启动程序
--with-fpm-user=nginx \ #指定运行用户身份
--with-fpm-group=nginx \
--with-curl \ #打开curl浏览器支持
--with-iconv \ #启用iconv函数,转换字符编码
--with-mhash \ #mhash加密方式扩展库
--with-zlib \ #支持zlib库,用于压缩http压缩传输
--with-openssl \ #支持ssl加密
--enable-mysqlnd \ #mysql数据库
--with-mysqli \
--with-pdo-mysql \
--disable-debug \ #关闭debug功能
--enable-sockets \ #支持套接字访问
--enable-soap \ #支持soap扩展协议
--enable-xml \ #支持xml
--enable-ftp \ #支持ftp
--enable-gd \ #支持gd库
--enable-exif \ #支持图片元数据
--enable-mbstring \ #支持多字节字符串
--enable-bcmath \ #打开图片大小调整,用到zabbix监控的时候用到了这个模块
--with-fpm-systemd #支持systemctl 管理cgi
[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 instsall
- 配置PHP
cpp
[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
[global]
; Pid file
; Note: the default prefix is /usr/local/php/var
; Default Value: none
pid = run/php-fpm.pid
[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
41 listen = 0.0.0.0:9000
[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
989 date.timezone = Asia/Shanghai
[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
# Mounts the /usr, /boot, and /etc directories read-only for processes invoked by this unit.
#ProtectSystem=full #注释此参数
[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
- 配置环境变量
cpp
[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
3.2 PHP整合Nginx访问测试
- 创建php目录和测试网页
cpp
[root@Nginx ~]# mkdir /webdata/dragon.org/php/html -p
[root@Nginx ~]# vim /webdata/dragon.org/php/html/index.php
<?php
phpinfo();
?>
- 编辑Nginx子配置文件
cpp
[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;
}
}
- 访问测试

四、php的动态扩展模块(php的缓存模块)memcached
Memcached不是数据库,而是纯内存的分布式缓存系统------它像书桌上的便签纸,临时存放你频繁查阅的资料,用完即丢,只为让你少跑几次书架(数据库) 。其核心原理是:用内存空间换访问速度 ,通过Key-Value存储+LRU淘汰+客户端一致性哈希 三要素,在微秒级响应高并发请求,但绝不持久化数据。
软件下载:http://pecl.php.net/package/memcache

4.1 利用memcache实现php的缓存加速
- 安装memcached
cpp
[root@Nginx ~]# dnf install memcached.x86_64 -y
- 配置memcached
cpp
[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
- 升级php对memcached的支持
cpp
[root@Nginx ~]# php -m #查看php支持的插件
[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
[root@Nginx memcache-8.2]# vim /usr/local/php/etc/php.ini
939 extension=memcache
[root@Nginx memcache-8.2]# systemctl restart php-fpm.service
[root@Nginx memcache-8.2]# php -m | grep memcache
memcache
- 测试性能
cpp
[root@Nginx memcache-8.2]# vim memcache.php
define('ADMIN_USERNAME','admin'); // Admin Username
define('ADMIN_PASSWORD','123'); // Admin Password
$MEMCACHE_SERVERS[] = '172.25.254.10:11211'; // add more as an array
#$MEMCACHE_SERVERS[] = 'mymemcache-server2:11211'; // add more as an array
[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/
#测试
# 关闭memcache
[root@Nginx memcache-8.2]# systemctl stop memcached.service
[root@Nginx memcache-8.2]# ab -n 1000 -c 300 php.dragon.org/index.php
This is ApacheBench, Version 2.3 <$Revision: 1913912 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking php.dragon.org (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests
Server Software: nginx/1.28.2
Server Hostname: php.dragon.org
Server Port: 80
Document Path: /index.php
Document Length: 78477 bytes
Concurrency Level: 300
Time taken for tests: 0.200 seconds
Complete requests: 1000
Failed requests: 994 # 可见几乎全部失败
(Connect: 0, Receive: 0, Length: 994, Exceptions: 0)
Total transferred: 78641900 bytes
HTML transferred: 78478900 bytes
Requests per second: 5000.98 [#/sec] (mean)
Time per request: 59.988 [ms] (mean)
Time per request: 0.200 [ms] (mean, across all concurrent requests)
Transfer rate: 384068.55 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 1.5 0 4
Processing: 3 50 14.0 56 60
Waiting: 1 50 14.0 56 60
Total: 7 51 12.7 56 62
Percentage of the requests served within a certain time (ms)
50% 56
66% 57
75% 57
80% 57
90% 58
95% 59
98% 59
99% 61
100% 62 (longest request)
# 开启memcache
[root@Nginx memcache-8.2]# systemctl start memcached.service
[root@Nginx memcache-8.2]# ab -n 1000 -c 300 php.dragon.org/index.php
This is ApacheBench, Version 2.3 <$Revision: 1913912 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking php.dragon.org (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests
Server Software: nginx/1.28.2
Server Hostname: php.dragon.org
Server Port: 80
Document Path: /index.php
Document Length: 78479 bytes
Concurrency Level: 300
Time taken for tests: 0.193 seconds
Complete requests: 1000
Failed requests: 105 # 可见失败大幅减少
(Connect: 0, Receive: 0, Length: 105, Exceptions: 0)
Total transferred: 78641890 bytes
HTML transferred: 78478890 bytes
Requests per second: 5174.32 [#/sec] (mean)
Time per request: 57.979 [ms] (mean)
Time per request: 0.193 [ms] (mean, across all concurrent requests)
Transfer rate: 397381.38 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 1.3 0 4
Processing: 5 49 13.1 55 60
Waiting: 1 49 13.1 54 60
Total: 7 50 11.9 55 62
Percentage of the requests served within a certain time (ms)
50% 55
66% 55
75% 56
80% 57
90% 57
95% 58
98% 59
99% 60
100% 62 (longest request)

五、nginx+memcached高速缓存

5.1 重新编译nginx
部署方法
在我们安装的nginx中默认不支持memc和srcache功能,需要借助第三方模块来让nginx支持此功能,所以nginx需要重新编译
cpp
[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
5.2 整合memcached
cpp
# 编辑配置文件
[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;
}
}
[root@Nginx conf]# nginx -s reload
#测试
[root@Nginx conf]# ab -n 10000 -c500 http://php.dragon.org/index.php
This is ApacheBench, Version 2.3 <$Revision: 1913912 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking php.dragon.org (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests
Server Software: nginx/1.28.2
Server Hostname: php.dragon.org
Server Port: 80
Document Path: /index.php
Document Length: 153 bytes
Concurrency Level: 500
Time taken for tests: 0.380 seconds
Complete requests: 10000
Failed requests: 0 # 可见没有失败,性能非常qian
Non-2xx responses: 10000
Total transferred: 3030000 bytes
HTML transferred: 1530000 bytes
Requests per second: 26289.09 [#/sec] (mean)
Time per request: 19.019 [ms] (mean)
Time per request: 0.038 [ms] (mean, across all concurrent requests)
Transfer rate: 7778.90 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 8 1.4 8 12
Processing: 4 11 2.3 11 20
Waiting: 1 8 2.3 8 13
Total: 10 19 2.0 18 25
Percentage of the requests served within a certain time (ms)
50% 18
66% 19
75% 20
80% 20
90% 21
95% 22
98% 23
99% 24
100% 25 (longest request)