【Nginx19】Nginx学习:FastCGI模块(一)基础配置

Nginx学习:FastCGI模块(一)基础配置

万众瞩目啊,总算到 FastCGI 了。看我文章和视频的各位大佬们8成以上都是 PHPer 吧,要做 PHP ,FastCGI 的配置就少不了。CGI 、FastCGI 、PHP-FPM 这些概念,咱们在很早之前的 了解PHP-FPMhttps://mp.weixin.qq.com/s/NUpDnfYfbPuWmal4Am3lsg 这篇文章中就学习过了。不记得的小伙伴可以回去看下哦,如果感觉说得太简单了,大家还可以去自己搜索一下相关的资料。

FastCGI 模块的全称是 ngx_http_fastcgi_module ,包含在核心源码中,不需要单独编译了。

基本配置

还是拿我们在 HTTP 核心模块中第一篇文章中的例子来说。最简单的配置就是下面这样。

代码语言:javascript
复制
location ~ \.php$ {
    root           html;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    include        fastcgi_params;
}

没错,就这么简单的几个配置,我们后面会一一说明它们的作用。标准的连接 PHP-FPM 就是这么简单,但是,CGI 是通用网关接口,因此,不仅仅是 PHP ,Python、Java、C++ 之类的任何语言,只要是实现了 FastCGI 接口,那么他们都可以通过这种形式与 Nginx 进行交互。并且 FastCGI 也提供这些语言的 API ,只不过我对这些语言不熟悉,而且大部分情况下,使用 Nginx 的 FastCGI 都是和 PHP 打配合的,因此,咱们也就不多赘述了。有兴趣,并且精通这些语言的小伙伴可以自己找资料调试一下哦。

接下来,我们今天就先看看上面这个配置中的这三条配置指令是干嘛的。

fastcgi_pass

设置 FastCGI 服务器的地址。

代码语言:javascript
复制
fastcgi_pass address;

没有默认值,也可以将这个配置项当做是 FastCGI 的开关。它只能配置在 location 子模块中,也就是说,必须是指定路径的或者条件的 location 才能使用 FastCGI 。

它的参数就一个,之前我们就学习过,可以使用 127.0.0.1:9000 这种端口形式的,也可以使用 unix:/var/sock/php-fpm/www.sock 这种形式。在开头 PHP-FPM 的文章中有过详细的说明。一般来说,本机使用,肯定是 UnixSocket 这种形式更好啦,毕竟不需要再走连接请求了。而且一般也很少人会把 Nginx 和 PHP-FPM 分开放,即使是做负载均衡,也是直接代理到每台主机的 Nginx 端口上。因此,建议本机的 Nginx+PHP 组合尽量都走 UnixSocket 。

另外,这个服务器地址也可以是一组服务器,会以循环的方式请求,类似于默认的负载均衡配置,不过还是那句话,很少有人这么玩。详细的负载均衡 upstream 模块我们后面也会学到,主要还是看那边的吧。

地址参数还可以包含变量,并且如果地址被指定为域名,则在所描述的服务器组中搜索该名称,如果没有找到,则使用解析器来确定。

fastcgi_index

$fastcgi_script_name 变量的值中设置将附加在以斜杠结尾的 URI 之后的文件名。

代码语言:javascript
复制
fastcgi_index name;

其实和大家最常见的那个 index 是一样的,只不过 index 是拼接到 root 或者 alias 路径的后面,而这个配置,则是将指定的默认文件拼接到以斜杠结尾的 fastcgi_script_name 变量的后面。这个变量又是哪里来的呢?它呀,就是 FastCGI 当中的 uri 变量,也就是我们的请求 URI 。

  • $fastcgi_script_name 请求 URI,如果 URI 以斜杠结尾,则请求带有由 fastcgi_index 指令配置的索引文件名附加到它的 URI。此变量可用于设置确定 PHP 中脚本名称的 SCRIPT_FILENAME 和 PATH_TRANSLATED 参数。比如说,我们请求配置一个 /php/ 路径,加上上面的 FactCGI 配置。
代码语言:javascript
复制
location /php/ {
    root           html;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  /home/www/html1/php$fastcgi_script_name;
    include        fastcgi_params;
}

然后请求 /php/info/ ,那么实际访问的就是 fastcgi_script_name 也就是 /php/info/ ,完整的 SCRIPT_FILENAME 路径就是 /home/www/html1/php/info/ ,最后拼上 fastcgi_index 的设置,它是针对 fastcgi_script_name 的,因此实际 fastcgi_script_name 的内容是 /php/info/index.php 。最终,完整的访问到的文件就是 /home/www/html1/php/info/index.php 。

需要注意的是,如果我们访问的是静态页面,那么还是会走 root 或者 alias 的,不会走到 FastCGI 配置的路径中。而且,之前的文章也说过了,SCRIPT_FILENAME 指定的路径需要是绝对路径,这个也是容易配错的地方。

fastcgi_param

设置应传递给 FastCGI 服务器的参数。

代码语言:javascript
复制
fastcgi_param parameter value [if_not_empty];

没有默认值,但可以配置在 http、server、location 模块中。它的 value 值可以包含文本、变量及其组合。当且仅当当前级别上没有定义 fastcgi_param 指令时,这些指令才从上级的配置级别继承。一般来说,PHP 必须的主要是这两个。

代码语言:javascript
复制
fastcgi_param SCRIPT_FILENAME /home/www/scripts/php$fastcgi_script_name;
fastcgi_param QUERY_STRING    $query_string;

SCRIPT_FILENAME 不用多说,PHP-FPM 要执行文件就要看它。但是我们的配置文件中没有写下面这个 QUERY_STRING 呀,注意哦,在我们的配置中,fastcgi_param 下面还 include 了一个文件。我们打开这个文件看看。

代码语言:javascript
复制
// vim /etc/nginx/fastcgi_params
fastcgi_param  QUERY_STRING       $query_string; #请求的参数;如?app=123  
fastcgi_param  REQUEST_METHOD     $request_method; #请求的方法(GET,POST)  
fastcgi_param  CONTENT_TYPE       $content_type; #请求头中的Content-Type字段  
fastcgi_param  CONTENT_LENGTH     $content_length; #请求头中的Content-length字段

fastcgi_param SCRIPT_NAME $fastcgi_script_name; #脚本名称
fastcgi_param REQUEST_URI $request_uri; #请求的地址不带参数
fastcgi_param DOCUMENT_URI document_uri; #与uri相同
fastcgi_param DOCUMENT_ROOT $document_root; #网站的根目录。在server配置中root指令中指定的值
fastcgi_param SERVER_PROTOCOL $server_protocol; #请求使用的协议,通常是HTTP/1.0或HTTP/1.1
fastcgi_param REQUEST_SCHEME $scheme; #请求协议 http/https
fastcgi_param HTTPS $https if_not_empty; # 是否使用 https

fastcgi_param GATEWAY_INTERFACE CGI/1.1; #cgi 版本
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; #nginx 版本号,可修改、隐藏

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配置中指定的server_name

PHP only, required if PHP was built with --enable-force-cgi-redirect

fastcgi_param REDIRECT_STATUS 200; # 仅 PHP 可用,如果PHP编译的时候使用了--enable-force-cgi-redirect 指令,REDIRECT_STATUS参数应该传输200.

看到了吧,其实就是 Nginx 已经帮我们准备好了一堆配置。这些东西我们在 PHP 的 _SERVER 中可以获取到。比如我们我们添加一个,在外面的 location 中添加吧,尽量还是不动这个默认的 fastcgi_params 配置文件。需要修改哪个值的话也可以通过前后顺序覆盖修改。一定要修改原始的这个 fastcgi_params 文件也可以,因为默认还有一个 fastcgi_params.default 文件会在它的同级目录中,如果没有这个文件的话,记得备份一下哦。</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">location ~ \.php {
………………
include fastcgi_params;
fastcgi_param os_PPP "zyblog"; # 新添加的
fastcgi_param SERVER_SOFTWARE nnn; # 覆盖掉原始的值 nginx/1.23.0 ,变成 nnn
}

大小写没事,普通变量的命名规则就好了。然后在 php 文件中打印 $_SERVER,就可以看到新配置的这个信息。

代码语言:javascript
复制
Array
(
………………
[os_PPP] => zyblog
………………
[SERVER_SOFTWARE] => nnn
………………
)

之前在讲命令行时,我们就讲过,如果是命令行运行 php 文件打印的 _SERVER 和通过 phpcgi 以及 Nginx、Apache 打印的是不同的,这下知道这个 _SERVER 里的参数是怎么来的了吧。

另外还要注意的一点是,header 头里的,在 PHP 的 _SERVER</code> 中是以 <code>HTTP_</code> 开头的,同样,Nginx 的 FastCGI 配置中也有单独添加请求头的,这个我们后面会学到。</p><p>在默认的配置中,还有一个 if_not_empty 的可选参数,用于表示如果值不存在,就传送到 CGI 程序中。上面的例子中,我们没有开启 HTTPS 访问,所以在 PHP 中,HTTPS 也不会在 <code>_SERVER 中显示。

总结

今天的内容很短,但是最基础的 FastCGI 的配置我们都学习到了。其实到现在,一个正常的动态 LNMP 架构中的 N 和 P 部分就已经搭建完成了。使用 Nginx 来搭建 PHP 环境是不是非常地简单方便,这也是 PHP 在之前的 Web2.0 时代能够大行其道的原因。整个 LNMP 环境都不是特别复杂,而且还有很多一键安装以及面板工具,能够帮助我们在分分钟内就搭建起整个线上或者开发环境。

除了 FastCGI 之外 ,Nginx 还提供了 uwsgi ,也就是 Python 以及 Python 框架常用的一类通讯协议。PHP 也可以实现通过 uwsgi 与 Nginx 联通,但是,多此一举嘛,正常情况下也没人这么干,PHP-FPM 提供的 FastCGI 已经是事实标配了。如果硬要玩的话,需要安装额外的操作系统扩展以及环境支持,还要学习 uwsgi 相关的知识。因此,在 HTTP 模块中,我们就不特意再去学习 uwsgi 相关模块的配置指令了,毕竟咱们是标准的 PHPer 。(它的指令和 FastCGI 的非常相似,功能也是大同小异)

此外,还有一个 scgi 模块也不单独写了,都是差不多的。

FastCGI 相关的配置指令还有很多,我们接下来还要继续学习,这时候可不要随便切换频道啦,一起继续前进吧!

参考文档:

http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html