淄博张店网站建设,做任务领佣金的网站源码,昆明网络建设,开发公司 网站建设价格Nginx学习#xff1a;FastCGI模块#xff08;四#xff09;错误处理及其它 FastCGI 最后一篇#xff0c;我们将学习完剩下的所有配置指令。在这里#xff0c;错误处理还是单独拿出来成为一个小节了#xff0c;而剩下的内容都放到其它中进行学习。不要感觉是其它的就没用了… Nginx学习FastCGI模块四错误处理及其它 FastCGI 最后一篇我们将学习完剩下的所有配置指令。在这里错误处理还是单独拿出来成为一个小节了而剩下的内容都放到其它中进行学习。不要感觉是其它的就没用了有些配置指令还是非常重要的哦或许正好你现在的项目就能用上呢。 今天学习的内容都是可以设置在 http、server、location 中的有特殊情况的我会单独说。 错误处理 FastCGI 模块的错误处理可不是 error_page 那种指定跳转页面什么的当然也有一个和它相关的配置之前我们就学过了。其它大部分的配置其实是假设万一连接的后端服务器出现问题了该怎么办的这里也会牵涉到一点 upstream 相关的内容这一块我们后面还会细说主线还是先看看 FastCGI 模块是怎么处理这些问题的吧。 fastcgi_next_upstream 指定在哪些情况下应将请求传递给下一个服务器。 fastcgi_next_upstream error | timeout | invalid_header | http_500 | http_503 | http_403 | http_404 | http_429 | non_idempotent | off ...; 默认值是 error timeout; 每个参数的意思其实也比较明显就是遇到这些指定的情况时要不要将请求转发给下一个 upstream 中配置的 server 。 error 与服务器建立连接、向其传递请求或读取响应标头时发生错误invalid_header 服务器返回空响应或无效响应http_xxx 返回指定的状态码比如 http_500 就是 PHP 那边返回了 500 状态码时non_idempotent 通常如果请求已发送到上游服务器1.9.13则使用非幂等方法POST、LOCK、PATCH的请求不会传递到下一个服务器显式启用此选项允许重试此类请求禁止将请求传递到下一个服务器 这个测试比较麻烦我们需要再启动一个 PHP-FPM 然后在 Nginx 的 http 模块下配置一下 upstream 也就是服务器组这个具体内容我们会在后面服务器组模块的学习中学到这个模块的内容就是 Nginx 负载均衡的配置。 # 再启动一个PHP需要修改php-fpm.conf及php-fpm.d/www.conf里面的内容比如 listen 部分和 pid 部分
# 然后执行一下 php-fpm 就可以了# http 模块下
upstream fcgicache {server unix:/var/sock/php-fpm/www.sock;server unix:/var/sock/php-fpm/www2.sock;
} 启动多个 PHP-FPM 这里不多解释了不会的小伙伴可以查下资料或者到时候看视频哈。然后再修改 Nginx 配置中 fastcgi_pass 指向这个新的服务器组。 fastcgi_pass fcgicache; 默认配置中的 error 这个选项其实就已经帮我们处理掉 502 这种连接问题了比如说这时候我们 kill 掉一个 PHP-FPM 进程但是程序依然可以正常响应也就是说一般的 502 这种连接错误是 error 处理的。那么要如何检测其它的错误情况下 fastcgi_next_upstream 的效果呢我们可以在 php 文件中进行修改。 // 3.php
echo posix_getpid();
if (posix_getpid() 1648){throw new Exception(错了);
} posix_getpid() 是 PHP 的 Posix 扩展中的函数如果没有话可以自己装一下。它可以获取到我们当前执行的进程 ID 查看进程情况 [rootlocalhost phpfpm2]# ps -ef | grep php
root 1640 1 0 09:47 ? 00:00:00 php-fpm: master process (/root/phpfpm2/php-fpm.conf)
www 1641 1640 0 09:47 ? 00:00:00 php-fpm: pool www
www 1642 1640 0 09:47 ? 00:00:00 php-fpm: pool www
www 1643 1640 0 09:47 ? 00:00:00 php-fpm: pool www
www 1644 1640 0 09:47 ? 00:00:00 php-fpm: pool www
www 1645 1640 0 09:47 ? 00:00:00 php-fpm: pool www
root 1648 1 0 09:47 ? 00:00:00 php-fpm: master process (/etc/php-fpm.conf)
www 1649 1648 0 09:47 ? 00:00:00 php-fpm: pool www
www 1650 1648 0 09:47 ? 00:00:00 php-fpm: pool www
www 1651 1648 0 09:47 ? 00:00:00 php-fpm: pool www
www 1652 1648 0 09:47 ? 00:00:00 php-fpm: pool www
www 1653 1648 0 09:47 ? 00:00:00 php-fpm: pool www 可以看到两个 php-fpm 进程的情况上面 PHP 代码的意思就是小于 php-fpm: master process (/etc/php-fpm.conf) 这个进程 ID 的进程也就是另外一个 PHP-FPM 的进程处理时都抛出一个异常。直接抛出异常就是 500 错误500 错误是需要单独的 http_500 来配置的。 在没有配置 fastcgi_next_upstream http_500 的情况下刷新页面会一下 500 一下正常这是因为 upstream 默认情况下是轮询的这个以后我们也会细说。现在配置上 fastcgi_next_upstream 。 fastcgi_next_upstream error http_500; 再次不停地刷新页面始终会返回 200 而错误日志中会有 FastCGI 的错误信息。 2022/08/25 10:07:31 [error] 1720#0: *110 FastCGI sent in stderr: PHP message: PHP Fatal error: Uncaught Exception: 错了
…………………… 注意这个配置项不是追加的比如上面如果我们只设置了 http_500 那么之前说的 kill 掉某个 PHP-FPM 转发跳转的效果就没有了。大家可以自己试试哦。 应该记住只有在尚未向客户端发送任何内容的情况下才有可能将请求传递给下一个服务器。也就是说如果在传输响应的过程中发生错误或超时则无法解决此问题。该指令还定义了与服务器通信的不成功尝试。错误、超时和 invalid_header 的情况总是被认为是不成功的尝试即使它们没有在指令中指定。 http_500、http_503 和 http_429 的情况仅在指令中指定时才被视为不成功的尝试。 http_403 和 http_404 的情况永远不会被认为是不成功的尝试。将请求传递到下一个服务器可能会受到尝试次数和时间的限制。 最后有啥用其实通过这个就可以实现 PHP-FPM 的负载均衡只要有一个 PHP-FPM 存在服务就可以一直提供PHP-FPM 使用 TCP 端口形式也是可以分布到不同的主机或者 Docker 中的并且可以实现不同的版本或者版本的平滑升级。 fastcgi_next_upstream_timeout 限制可以将请求传递到下一个服务器的时间。 fastcgi_next_upstream_timeout time; 默认 0 表示关闭此限制。 fastcgi_next_upstream_tries 限制将请求传递到下一个服务器的可能尝试次数。 fastcgi_next_upstream_tries number; 默认是 0 表示不限制。 fastcgi_catch_stderr 设置要在从 FastCGI 服务器接收到的响应的错误流中搜索的字符串。 fastcgi_catch_stderr string; 如果找到指定的字符串则认为 FastCGI 服务器返回了无效响应。这允许在 nginx 中处理应用程序错误例如 location /php/ {fastcgi_pass backend:9000;...fastcgi_catch_stderr PHP Fatal error;fastcgi_next_upstream error timeout invalid_header;
} 其实呀就是我们上面学习过的 fastcgi_next_upstream 只不过不是根据状态码如果在响应字符串中有相应的内容被捕获到了就直接走 fastcgi_next_upstream 的处理了。由于我们都是在一台机器上的 PHP-FPM 一个输出错误了别的也是输出错误也就测不出什么效果有兴趣的小伙伴可以使用跨服务器的 IP Socket 方式连接 PHP 进行测试。 fastcgi_intercept_errors 确定代码大于或等于 300 的 FastCGI 服务器响应是否应传递给客户端或被拦截并重定向到 nginx 以使用 error_page 指令进行处理。 fastcgi_intercept_errors on | off; 默认值是 off 。之前在学习 error_page 时用过也介绍过啦。注意fastcgi_next_upstream 如果同时存在并且 fastcgi_next_upstream 里面有正常响应的那么会走正常响应的如果所有的 upsteam 都返回错误就会按这边的配置。 其它配置 剩下的就是一些不太好划分大类的配置指令了。说实话很多闻所未闻根本就没见过而且平常配置的时候可能真的不太用得上。但是说实话很涨知识哦特别是 PATH INFO 部分我也是边查资料边学习的以前还以为这只是 TP 特有的东西原来是 TP 遵循的 PATH INFO 规范。怎么样感兴趣了吧别急咱们一个一个来看。 fastcgi_connect_timeout 定义与 FastCGI 服务器建立连接的超时时间。 fastcgi_connect_timeout time; 默认是 60s 通常不超过 75 秒。注意它是 Nginx 和 PHP-FPM 建立通讯的时间不是说我们们在 PHP 中 sleep() 一下就可以测出来的。是 TCP 建立连接的超时时间。 fastcgi_force_ranges 启用对来自 FastCGI 服务器的缓存和未缓存响应的字节范围支持无论这些响应中的“Accept-Ranges”字段如何。 fastcgi_force_ranges on | off; 默认值是 off 具体作用不清楚有了解的小伙伴可以评论留言哦。 fastcgi_bind 与 FastCGI 服务器的传出连接源自具有可选端口 (1.11.2) 的指定本地 IP 地址。 fastcgi_bind address [transparent] | off; 看不懂上面的解释吧我也看不懂于是查了一下它是指定 Nginx 与 FastCGI 通信的 IP 地址一般不做设置。指令在调用 connect() 函数之前将解析每个上游 socket 到一个本地地址可以使用在主机拥有多个网卡接口或别名的情况下但是你只允许到外部的连接来自指定的网卡或者地址的情况下。 与回环 IP 地址通信需要设置路由表。 好嘛一般不做设置而且还是看不懂更重要的是我不知道咋测。就这样吧具体的解释官方文档上还有不少不过纯英文的。查到的解释大部分也就是上面那一句话那么我也重复我之前经常说过的话不懂就别瞎设置期待有大佬用过或者明白啥意思的能够用更通俗的话在评论里解释一下让大家一起学习下哈。 fastcgi_ignore_client_abort 确定当客户端关闭连接而不等待响应时是否应关闭与 FastCGI 服务器的连接。 fastcgi_ignore_client_abort on | off; 默认是关闭的。 fastcgi_keep_conn 默认情况下FastCGI 服务器将在发送响应后立即关闭连接。 fastcgi_keep_conn on | off; 当这个指令设置为 on 时nginx 将指示 FastCGI 服务器保持连接打开。这对于到 FastCGI 服务器的 keepalive 连接来说是必要的。我们之前学习过 Nginx 在处理和客户端的连接时的长连接问题对于和 FastCGI 的通信也是可以通过长连接进行连接的。 fastcgi_limit_rate 限制从 FastCGI 服务器读取响应的速度。 fastcgi_limit_rate rate; 默认 0 表示不限制 速率以每秒字节数指定。该限制是针对每个请求设置的因此如果 nginx 同时打开两个到 FastCGI 服务器的连接则总体速率将是指定限制的两倍。仅当启用了来自 FastCGI 服务器的响应缓冲时该限制才有效。和 Nginx 普通的 limit_rate 参数是一样的只不过这是针对后端服务器的。 fastcgi_pass_request_body 指示是否将原始请求正文传递给 FastCGI 服务器。 fastcgi_pass_request_body on | off; 默认值是 on 关了之后在 PHP 这边就拿不到 $_POST 里的东西啦 fastcgi_pass_request_headers 指示是否将原始请求的标头字段传递给 FastCGI 服务器。 fastcgi_pass_request_headers on | off; 默认值是 on 和上面的一样关了 PHP 中就拿不到 header 里面的内容了。这个可以直接打印 $_SERVER查看。 fastcgi_request_buffering 启用或禁用客户端请求正文的缓冲。 fastcgi_request_buffering on | off; 默认值是 on 表示在将请求发送到 FastCGI 服务器之前会从客户端读取整个请求正文。 当缓冲被禁用时请求正文在收到后立即发送到 FastCGI 服务器。在这种情况下如果 nginx 已经开始发送请求正文则无法将请求传递给下一个服务器。 貌似和 fastcgi_next_upstream 有关系但是不知道怎么测试有了解的小伙伴评论留言哈。 fastcgi_send_lowat 如果该指令设置为非零值nginx 将尝试使用 kqueue 方法的 NOTE_LOWAT 标志或 SO_SNDLOWAT 套接字选项使用指定的大小来最小化到 FastCGI 服务器的传出连接上的发送操作数。 fastcgi_send_lowat size; 好巧不巧它的默认值就是 0 意思也就是不开启的具体功能和如何测试我也不太清楚反正不懂就不要设置了有了解这个配置的小伙伴评论留言哦。 fastcgi_send_timeout 设置将请求传输到 FastCGI 服务器的超时时间。 fastcgi_send_timeout time; 默认值是 60s 超时仅在两个连续的写操作之间设置而不是为整个请求的传输设置。如果 FastCGI 服务器在这段时间内没有收到任何内容则关闭连接。 fastcgi_socket_keepalive 为到 FastCGI 服务器的传出连接配置“TCP keepalive”行为。 fastcgi_socket_keepalive on | off; 它的默认值是 off 在默认情况下操作系统的设置对套接字有效。如果该指令设置为值“on”则为套接字打开 SO_KEEPALIVE 套接字选项。好吧又是网络基础知识中的不知道咋测但很明显它是是否在和 FastCGI 绑定的后端之间进行通信的 TCP 是否启用长连接的一个设置。这个长连接和 HTTP 的长连接的概念是相同的无非就是减少建立连接时的消耗从而提升性能。但是不懂就别乱动保持默认就好同时还是更希望有接触过的小伙伴可以来释疑一下哈。 网上能够搜到同时开启 fastcgi_socket_keepalive 和 fastcgi_keep_conn 之后会产生一些问题可能的解决方案是要将 PHP-FPM 的 pm.max_requests 设置成和 keepalive_requests 相同的值。不过我没遇到过也不知道真假哈先记录一下万一将来遇到了就可以试试可能的报错信息是这样的 readv() failed (104: Connection reset by peer) while reading upstream and recv() failed (104: Connection reset by peer) while reading response header from upstream fastcgi_split_path_info 定义一个捕获 $fastcgi_path_info 变量值的正则表达式。 fastcgi_split_path_info regex; 正则表达式应该有两个捕获第一个成为 $fastcgi_script_name 变量的值第二个成为 $fastcgi_path_info 变量的值。 之前我们学过了 $fastcgi_script_name 是干嘛的有点像静态页面中的 $uri 变量返回的都是访问的路径。不过针对 FastCGI 还提供了一个变量 $fastcgi_path_info可以用于实现 PATH INFO 能力。这个东西其实是 PHP 用得比较多的通过 PATH INFO 实现伪静态。最常见的就是 TP 框架的 http://xxxx.com/index.php/xxx/xx 这种路径。不过一般我们会通过 Nginx 的 rewrite 重写去掉中间的 index.php 。最后的请求 URL 就是 http://xxxx.com/xxx/xx 这样的。 我们可以这样配置一个。 fastcgi_split_path_info ^(.\.php)(.*)$;return 200 $uri$fastcgi_script_name$fastcgi_path_info; 然后请求配置了这个参数的路径比如这里是 http://192.168.56.88/fastcgi4/5.php/ppp/hhh 就会看到返回的结果中 $fastcgi_path_info 变量的值是 /ppp/hhh 。默认情况下它是没有值的如果想把这个值传给 PHP 的话就可以加一个 fastcgi_param 。 fastcgi_param PATH_INFO $fastcgi_path_info; 这样在 PHP 中就可以在 $_SERVER 中看到 PATH_INFO 这个属性了。 在 TP6 中如果使用 fastcgi_split_path_info 那么就可以不用再配置官网那个 rewrite 的方式来实现 PATH INFO 路径了。 location / { // …..省略部分代码if (!-e $request_filename) {rewrite ^(.*)$ /index.php?s/$1 last;}
} 官网这个配置其实是对于不支持 PATH INFO 的服务器比如老版本的 Nginx 而采用的一种跳转回兼容模式的方式来实现的 PATH INFO 效果。同时还可以去除 index.php 。我们不使用它直接使用下面这个配置。 location ~ \.php {fastcgi_pass 127.0.0.1:9000;fastcgi_index index.php;fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;include fastcgi_params;fastcgi_split_path_info ^(.\.php)(.*)$;fastcgi_param PATH_INFO $fastcgi_path_info;
} 注意要把 location 默认正则中的最后一个 $ 去掉哦或者换成 \.php(.*)$ 之前默认的是 location ~ \.php$ 这个样子的。然后就可以直接通过完全的 PATH INFO 来使用 TP 了不需要再配官方文档那个 rewrite 的指令。不过需要注意的是 PATH INFO 是有 index.php 的要想去除 index.php 还是得 rewrite 所以说实话还是老实用之前那种形式吧。但如果启用了 PATH INFO 则 rewrite 可以换个写法 rewrite ^(.*)$ /index.php$1 last; 因为我们不需要使用 TP 的兼容模式了也就不需要那个名为 s 的 GET 参数了。 而对于 Laravel 框架来说则走的不是 PATH INFO 模式它是根据 $request_uri 通过 fastcgi_param 传递到 PHP 的 $_SERVER 中的 REQUEST_URI 来进行路由解析分析的所以它在 Nginx 的配置中rewrite 只需要指向 /index.php 就可以了不需要像 TP 那样还要带个 s 参数。Laravel 是这样的 location / {if (!-e $request_filename) {rewrite ^(.*)$ /index.php last;}
} 也就是说使用 Laravel 时不用考虑 PATH INFO 的问题。 fastcgi_store 允许将文件保存到磁盘。 fastcgi_store on | off | string; 默认值是 off on 参数保存具有与指令别名或根目录相对应的路径的文件。 off 参数禁用保存文件。此外可以使用带有变量的字符串显式设置文件名。 根据收到的“Last-Modified”响应头域设置文件的修改时间。响应首先被写入一个临时文件然后文件被重命名。从版本 0.8.9 开始临时文件和持久存储可以放在不同的文件系统上。但是请注意在这种情况下文件是跨两个文件系统复制的而不是廉价的重命名操作。因此建议对于任何给定的位置保存的文件和保存临时文件的目录由 fastcgi_temp_path 指令设置放在同一个文件系统上。 该指令可用于创建静态不可更改文件的本地副本。 简单按照官网的例子试了下好像没啥明显的效果去百度、Google也没找到有啥资料只有一篇文章说不要开会影响性能。好吧还是希望有相关经验的小伙伴评论留言一起学习哦 fastcgi_store_access 为新创建的文件和目录设置访问权限。 fastcgi_store_access users:permissions ...; 默认值是 user:rw 如果指定了任何组或所有访问权限则可以省略用户权限。 总结 错误处理中我们见到了 FastCGI 也是可以做负载均衡的说实话带 pass 这个词的在 Nginx 中其实都可以做负载均衡因为它们其实都是一个意思通过代理到某个地方。最后在其它部分PATH INFO 这一块的知识对我来说确实是收获非常大别看干了这么久而且也用过 TP 但直到今天才真的明白 TP 文档中关于 URL 路径这里讲的是啥意思惭愧啊。 好了到此为止整个 FastCGI 相关的模块就学习完了。怎么样之前说过的学习 Nginx 就是在挑战我们的基础知识水平这话一点都没错吧。很多东西我也不知道但是学习文档特别是写文章的时候为了要表述清楚就需要查询更多的相关资料自然而然地顺带学习到了更多的知识。而且这样学习的效果更好。之前在小视频和一些文章中也提过这就是费曼学习法坚持下去就是最大的收获大家也可以尝试一下哦。 最后再强调一遍uwsgi 和 FastCGI 的很多内容很像后面也不会单独再写 uwsgi 部分的内容了有 Python 同学或者其它语言的同学使用 uwsgi 的可以自己参考一下官方文档进行学习。 参考文档 http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html