Nginx与PHP的FPM – 资源暂时不可用 – 502错误

Nginx与PHP的FPM – 资源暂时不可用 – 502错误

我正在使用一些代码来发送超过160 GET请求asynchronous使用curl到我的API,这是在Ubuntu服务器16.04运行Nginx的Php-fpm。 每个请求在将其作为JSON响应返回之前,从数据库中提取不同的数据select。 这个请求的数量足够小,我相信它不应该达到各种默认限制(套接字连接数,文件描述符等)。 然而,他们全部被发送/同时收到的事实似乎是造成问题。

绝大多数请求都会成功 ,但是一对(连续testing中一致的号码,但根据configuration不同)会得到一个“502错误的网关”响应。

如果我看看nginx错误日志( /var/log/nginx/error.log ),我看到这些错误消息:

 2017/11/21 09:46:43 [error] 29#29: *144 connect() to unix:/run/php/php7.0-fpm.sock failed (11: Resource temporarily unavailable) while connecting to upstream, client: 192.168.3.7, server: , request: "GET /1.0/xxx HTTP/1.1", upstream: "fastcgi://unix:/run/php/php7.0-fpm.sock:", host: "my.domain.org" 

日志中的“502错误网关”错误消息的数目总是与我从API收到的完全一样。

同时,在执行testing期间( tail -100f /var/log/php7.0-fpm.log )观察fpm日志文件时,没有任何反应。 它只是有以下几点:

 [21-Nov-2017 11:54:29] NOTICE: fpm is running, pid 329 [21-Nov-2017 11:54:29] NOTICE: ready to handle connections [21-Nov-2017 11:54:29] NOTICE: systemd monitor interval set to 10000ms 

虽然我的fpmconfiguration(在/etc/php/7.0/fpm/php-fpm.conf )指定了一个error_log = /var/log/php7.0-fpm.log的错误日志,但似乎没有这样的文件,提示没有错误。

工作configuration

我发现,如果我调整fpmconfiguration,我可以让Web服务器工作(没有502错误),如果我configuration/etc/php/7.0/fpm/pool.d/www.conf文件使用static数字15线程,而不是dynamic产生进程或使用较less数量的静态进程。

 pm = static pm.max_children = 15 

我相信这是有效的,因为已经有足够的线程准备好去突然打中,并且不会产生延迟或closures线程。 但是,这意味着我的networking服务器将使用比我想要的更多的内存。 理想情况下,我希望pm.max_children是等于服务器上vCPU数量的两倍(等于或小于8)。 在这种情况下,我正在使用四核服务器,但是可能会缩小到双核实例。 理想情况下,我希望服务器及时回答所有的请求,即使总的时间更长,比如队列和调整超时。

configuration设置

默认的php-fpm listen.backlog值是511 ,但是我把它设置为2000,只是为了消除它是一个因素。 listen.backlog = 2000

对于Nginx,我设置了1024个worker_connectionsworker_processes auto; ,所以应该是4。

我也有以下的缓冲区和超时设置,以防止它们成为一个因素:

 ## # Buffere settings ## client_body_buffer_size 10M; client_header_buffer_size 1k; client_max_body_size 512m; large_client_header_buffers 2 1k; ## # Timeout settings ## client_body_timeout 120; client_header_timeout 120; keepalive_timeout 120; send_timeout 120; fastcgi_connect_timeout 60s; fastcgi_next_upstream_timeout 40s; fastcgi_next_upstream_tries 10; fastcgi_read_timeout 60s; fastcgi_send_timeout 60s; fastcgi_cache_lock_timeout 60s; 

值得注意的是,我们在20秒左右的时间内获得了所有的请求(包括502),所以我们没有达到这些要求。 此外,即使fastcgi_next_upstream_tries设置为10,我只收到1个资源不可用的消息,每个502错误消息,而不是10倍,许多10倍尝试它应该尝试。

相似/相关的问题

我发现在serverfault和堆栈溢出上有许多类似的任务。 我在这里详细说明,所以这个问题不会被标记为重复。

  • Serverfault – 请求不会在使用Nginx和PHP-FPM的pm.max_children之后排队 。 似乎是一个非常类似的问题,但即使是3年前发布也没有答案,而且比这里的细节要less得多。 此外,我的一些请求必须成功排队,不像问题,表明一旦达到最大值,所有请求都被丢弃。

  • ServerFault – nginx错误502和资源暂时不可用),同时连接到上游,客户端 。 这篇文章看起来很相似(他正在描述同样的问题),但作为答案之一指出,他的套接字文件不匹配,我的是。 我的/etc/php/7.0/fpm/pool.d/www.confconfiguration文件有:

    listen = /run/php/php7.0-fpm.sock

你可以看到nginx提供的错误信息中的套接字文件。

  • ServerFault – 需要增加nginx吞吐量到上游unix套接字 – linux内核调优? 这里的答案build议设置net.core.somaxconnnet.core.netdev_max_backlog我相应地设置为4096和1000。 这个问题依然存在。

  • ServerFault的 – php-fpm.sock连接到上游时失败(11:资源暂时不可用) – 这里的build议是有pm = ondemand和max_children设置为4000.这不适合我,因为它可能会导致我的四核服务器有4000线程,只是吃了内存。

相信 Nginx对于PHP-fpm方面来说太快了。 在某些时候,fpm只是不响应nginx请求,所以Nginx放弃并返回一个502错误。 有没有一种方法(可能是一个或两个configurationvariables)来解决这个问题,以便fpm排队请求,或者让nginx稍后重试( fastcgi_next_upstream_tries似乎没有任何效果)? 我不介意Web服务器提供所有请求(增加超时)需要多长时间 ,只有我可以将我的fpm进程数设置为与我的CPU相关的适当数字,并且所有这160个请求将被服务。

更新 – 使用TCP套接字工作正常

我只是尝试交换FPM从unix文件套接字侦听到TCP套接字,详细在这里 。

例如,将fpm更改为: Listen 127.0.0.1:9000并更新nginx以使用: fastcgi_pass 127.0.0.1:9000;

这似乎已经成功解决了这个问题。 例如,即使我使用dynamic池,甚至只有2 fpm线程的静态池,我也没有得到任何502错误。

然而,我想知道为什么这个工程,而不是使用本地unix文件套接字,是否只是一个configuration的变化,我可以让基于文件套接字的解决scheme的工作,因为这是默认的,很多人可能正在使用。

我相信你可以使用ngx_http_limit_req_module来实现这个function,把数字configuration成所需的r / s,并使用burst设置队列的大小,configuration类似于:

 limit_req_zone $binary_remote_addr zone=php:10m rate=2r/s; server { location ~ \.php$ { limit_req zone=php burst=10; } 

这个例子将允许平均每秒2个请求,排队第三个到第十个请求(如果有的话)。 如果有超过10个r / sa 503错误将被返回( limit_req_status