使用PHP的set_time_limit()函数来避免nginx 504网关超时错误

155

当我的PHP脚本运行时间比平常长时,我会收到nginx的504超时消息。 set_time_limit(0)似乎无法防止这种情况发生!如果在nginx上运行php5-fpm时它不起作用怎么办?那么正确设置时间限制的方法是什么?

错误:

504 Gateway Time-out
nginx/1.2.7
13个回答

237

你可以有几种方法来设置php-fpm的超时。在/etc/php5/fpm/pool.d/www.conf中,我添加了这行:

request_terminate_timeout = 180

此外,在/etc/nginx/sites-available/default文件中,我在有问题的服务器的位置块中添加了以下行:

fastcgi_read_timeout 180;
整个位置块看起来像这样:
location ~ \.php$ {
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_read_timeout 180;
    include fastcgi_params;
} 

现在只需要重新启动php-fpm和nginx,对于处理时间少于180秒的请求就不会再出现超时问题了。


2
如果有其他人想知道,我的默认设置(nginx + php5-fpm)是60秒,所以如果您在60秒内看到脚本的“网关超时”,应该添加“fastcgi_read_timeout”设置。 - mn.
1
我已经试了好几天,@pymkin的回答是对我有用的。对于像我这样的业余爱好者,想知道如何重新启动nginx和php5-fpm,请运行以下两个命令:sudo service nginx restart & sudo service php5-fpm restart。唯一不同的是,我只将这些设置应用于我的一个网站,而不是服务器上所有网站的配置。 - Pamela
5
遗憾的是,在该“location”块中,无论我将fastcgi_read_timeout设置为多少秒,它仍然在60秒后超时。 - Spencer Williams
1
这应该是被接受的答案。尝试了很多解决方案,但只有这个有效。我正在使用Laravel Homestead并遇到了504网关超时错误,而这个解决了它。 - Anbu369
1
如果使用Laravel,则需要在处理php脚本的“location”块中设置此选项,而不是docroot。 - Ryan DuVal
显示剩余3条评论

66

尝试这个链接,它提供了更好的解决方案。步骤如下:

  1. 打开位于/etc/nginx目录下的nginx.conf文件。
  2. http {部分下面添加以下代码:

    client_header_timeout 3000;
    client_body_timeout 3000;
    fastcgi_read_timeout 3000;
    client_max_body_size 32m;
    fastcgi_buffers 8 128k;
    fastcgi_buffer_size 128k;
    

    注意:如果已经存在,请根据需要更改相应的值。

  3. 重新加载Nginx和php5-fpm。

  4. $ service nginx reload
    $ service php5-fpm reload
    

    如果错误持续存在,请考虑增加数值。


2
这并不能找到原因,只是增加了错误出现的次数。但更好的方法是找到为什么加载时间如此之长的解决方案。当我在本地主机上作为唯一客户端时,它需要很长时间才能加载,这对于开发过程中的等待来说并不好。 - Dariux
21
这个问题并不是在询问为什么脚本运行缓慢,而是在询问如何让服务器等待更长时间。有时候需要运行执行非常耗时任务的特殊脚本,这并不是什么坏事。 - orrd
更新的链接(如上):http://www.codetweet.com/nginx/solved-504-gateway-timeout-error-in-nginx-web-server/ - nadavkav
2
对于那些可能会想知道什么需要这么长时间的人来说,例如一个安装脚本从 Web 界面尝试连接到数据库,然后创建许多初始表并填充数据...在收到响应之前可能需要相当长的时间。 - imme
这刚刚导致了我的nginx或php7.2-fpm崩溃,它一直处于重新加载状态,从未加载。请解释每个值的含义。 - mLstudent33
显示剩余2条评论

17

这解决了我遇到的问题,即在我的vagrant box(使用vaprobash)上开始出现504错误。 - Andy Fleming
3
我相信这个答案只适用于你将Nginx用作代理服务器的情况。如果你把Nginx用作主要的Web服务器(与PHP-FPM一起),这种方法是行不通的。 - orrd

17

正确的答案是在您的Nginx配置中增加fastcgi_read_timeout
就是这么简单!


谢谢,你救了我的一天。 - Bauroziq
1
@Bauroziq,您能帮忙详细说明一下我在哪里添加fastcgi_read_timeout文件吗? - Meas
1
只需在nginx.conf文件中的http标签中添加它。 - Bauroziq

16
 sudo nano /etc/nginx/nginx.conf

将这些变量添加到nginx.conf文件中:

http {  
  # .....
  proxy_connect_timeout       600;
  proxy_send_timeout          600;
  proxy_read_timeout          600;
  send_timeout                600;
}

然后重新启动:

service nginx reload

什么是最大值?因为我正在使用PhpStorm进行调试,想要查看变量。 - mLstudent33
实际上,这破坏了我的Nginx PHP设置。600的也需要像那样对齐吗?我不能在终端中使用制表符,对吧? - mLstudent33

11

在这种情况下可能会发生三种超时。可以看到每个答案都只关注了这些可能性中的一个方面。因此,我想写下来,以便未来访问此处的人不需要随机检查每个答案,并在不知道哪个有效的情况下获得成功。

  1. 请求者超时 - 需要设置超时头(请参见请求库中的头配置)
  2. 在转发到代理服务器之前nginx在进行请求时超时,例如:上传巨大文件
  3. 在向代理服务器转发后,服务器没有及时回复nginx超时。例如:在服务器上运行耗时较长的脚本

因此,每个问题的修复方法如下。

  1. 设置超时头,例如:在ajax中

  2. $.ajax({
        url: "test.html",
        error: function(){
            // will fire when timeout is reached
        },
        success: function(){
            //do something
        },
        timeout: 3000 // sets timeout to 3 seconds
    });
    
  3. nginx客户端超时

    http{
         #in seconds
        fastcgi_read_timeout 600;
        client_header_timeout 600;
        client_body_timeout 600;
     }
    
  4. nginx被代理的服务器超时

    http{
      #Time to wait for the replying server
       proxy_read_timeout 600s;
    
    }
    

所以使用你需要的那个。也许在某些情况下,你需要所有这些配置。 我就需要了。


1

您需要在 nginx.conf 中添加额外的 nginx 指令(用于 ngx_http_proxy_module),例如:

proxy_read_timeout 300;

基本上,nginx的proxy_read_timeout指令可以改变代理超时时间,FcgidIOTimeout用于处理执行时间过长的脚本,FcgidBusyTimeout则用于处理需要较长时间才能执行的脚本。

如果您使用FastCGI应用程序,请将这些选项增加:

FcgidBusyTimeout 300
FcgidIOTimeout 250

然后重新加载nginx和PHP5-FPM。

Plesk

在Plesk中,您可以在Web服务器设置下的附加nginx指令中添加它。

对于FastCGI,请在Web服务器设置下的HTTP附加指令中进行检查。

参见:Plesk中如何解决FastCGI超时问题?


FcgidBusyTimeout 变量难道不是只存在于 Apache 中吗? - Slavik

1

别忘了查看你的php-fpm日志!

在我的情况下,使用PHP 7.3时遇到了以下问题:

警告:[pool www]服务器已达到pm.max_children设置(5),请考虑提高它

/etc/php/7.3/fpm/pool.d/www.conf中,我不得不将pm.max_children值从5提高到50(有时我会做一些比较重的本地工作...)。

注意:这可能会使用更多的CPU!


0

由于您正在使用php-fpm,因此应利用fastcgi_finish_request()来处理您知道可能需要更长时间的请求。


你能提供一个例子吗? - fungusanthrax

0

使用set_time_limit(0)在使用php-fpm或类似进程管理器时是无用的。

底线是在使用php-fpm时不要使用set_time_limit,要增加执行超时时间,请查看此教程


8
好的,我会尽力进行翻译。以下是需要翻译的内容:"may be provide some explanation of the answer here as well as this answer may become obselete if link expires." "可以在这里提供一些答案的解释,因为链接可能会失效导致答案过时。" - Lakshmi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接