【问题标题】:Debugging 504 Gateway Timeout and its actual cause and solution调试504网关超时及其实际原因及解决方法
【发布时间】:2016-04-08 04:15:53
【问题描述】:

我们在 RHEL 6.6 上的 Web 服务器 Varnish + Nginx + FastCGI (php-fpm) 上运行以下堆栈

它是一个动态网站,每次都有不同的结果集,大约有 200 万个网址被 Google 索引。

  • 在 nginx/1.5.12 和 PHP 5.3.3 上运行(即将升级到最新的 nginx 和 PHP)
  • Nginx 连接到本地运行在同一服务器上的 9000 端口上的 php-fpm

我们在某些无法解决的页面上间歇性地收到 504 网关超时。一段时间后,给出 504 的 URL 可以正常工作。 我们从日志中了解了 504,但我们无法复制它,因为它随机发生在任何 URL 上,并且在一段时间后会起作用。

我与开发人员进行了几次讨论,但根据他的说法,底层的 php 脚本几乎没有任何作用,它不应该花费这么长时间(120 秒),但它仍然给出 504 网关超时。

需要确定问题发生的确切位置:

  • 是 Nginx 的问题吗?
  • 是 php-fpm 的问题吗?
  • 是底层 php 脚本有问题吗?
  • 是否有可能是 nginx 无法连接到 php-fpm ?
  • 如果我们使用 Unix 套接字而不是 TCP/IP 连接,它会解决吗?

网址在 120 秒后超时,出现 504

以下是看到的错误: 2016/01/04 17:29:20 [错误] 1070#0: *196333149 连接到上游时上游超时(110:连接超时),客户端:66.249.74.95,服务器:xxxx,请求:“GET /Some /url HTTP/1.1”,上游:“fastcgi://127.0.0.1:9000”,主机:“example.com”

之前的 fastcgi_connect_timeout 为 150 秒 - 在 RHEL 6.6 上默认 net.ipv4.tcp_syn_retries = 5 时,它在 63 秒后给出 502 状态码;之后我们设置 net.ipv4.tcp_syn_retries = 6 然后它在 127 秒后开始给出 502。

一旦我设置了 fastcgi_connect_timeout = 120,它就开始给出 504 状态码。我了解如此高的值的 fastcgi_connect_timeout 并不好。

需要找出我们得到 504 的确切原因(我知道它的超时,但原因未知)。需要找到根本原因才能永久修复它。

我如何确认问题到底出在哪里?

以下是一些已经定义的超时:

在服务器范围的 nginx.conf 下:

  • keepalive_timeout 5;
  • send_timeout 150;

具体vhost.conf下:

  • proxy_send_timeout 100
  • proxy_read_timeout 100
  • proxy_connect_timeout 100
  • fastcgi_connect_timeout 120
  • fastcgi_send_timeout 300
  • fastcgi_read_timeout 300

使用了不同的超时值,因此我可以找出确切触发了哪个超时。

以下是 sysctl.conf 中的一些设置:

  • net.ipv4.ip_local_port_range = 1024 65500
  • net.ipv4.tcp_fin_timeout = 10
  • net.ipv4.tcp_tw_reuse = 1
  • net.ipv4.tcp_syn_retries = 6
  • net.core.netdev_max_backlog = 8192
  • net.ipv4.tcp_max_tw_buckets = 2000000
  • net.core.somaxconn = 4096
  • net.ipv4.tcp_no_metrics_save = 1
  • vm.max_map_count = 256000

如果它的代码写得不好,那么我需要通知开发人员 504 是由于 php 代码中的问题而不是由于 nginx 或 php-fpm 而发生的,如果它是由于 Nginx 或 Php-fpm 导致的,那么需要修复它。

提前致谢!

======

进一步更新:

有两种情况:

  1. 504 @ 120 秒出现以下错误:

2016/01/05 03:50:54 [错误] 1070#0: *201650845 连接到上游时上游超时(110:连接超时),客户端:66.249.74.99,服务器:xxxx,请求:“ GET /some/url HTTP/1.1”,上游:“fastcgi://127.0.0.1:9000”,主机:“example.com”

  1. 504 @ 300 秒出现以下错误:

2016/01/05 00:51:43 [错误] 1067#0: *200656359 从上游读取响应标头时上游超时(110:连接超时),客户端:115.112.161.9,服务器:192.168.12.101 ,请求:“GET /some/url HTTP/1.1”,上游:“fastcgi://127.0.0.1:9000”,主机:“example.com”

  • 在 php-fpm 日志中未发现错误。
  • php-fpm 进程数也正常。后端看起来并没有超载,因为其他请求同时得到了很好的处理。

  • 只使用了一个 php-fpm 池。一个 php-fpm 主(父)进程和其他从(子)进程通常只有在观察到 5xx 时才处于正常范围。 php-fpm 进程的数量没有显着增长,即使增长,服务器也有足够的容量来分叉新进程并服务请求。

【问题讨论】:

    标签: php linux nginx connection-timeout http-status-code-504


    【解决方案1】:

    尝试在您的 nginx 配置中进一步增加 fastcgi_read_timeoutproxy_read_timeout。 您可以将其添加到任何具有长任务的文件的顶部

    ini_set('max_execution_time', '0'); // for infinite time of execution   
    ini_set('max_execution_time', '300'); //300 seconds = 5 minutes
    ini_set('memory_limit','2048M'); // For unlimited memory limit set -1
    

    【讨论】:

      【解决方案2】:

      必须假定您正在重写 URL 或以其他方式通过网关/防火墙重定向,这通常是 504 错误出现的原因。

      504 表示后端服务(即,在网关/防火墙的另一侧 - 内部)已关闭或无法寻址(内部 URL 错误)。它也可能是由后端崩溃引起的,但这应该会显示在日志中(如果打开了调试日志)。

      检查以下内容: (a) 通过访问内部网络来检查应用程序。可以解决吗?参数对吗?它是否按预期工作? (b) 检查网关。它如何重定向(重写)URL?是否安装了允许重定向/重写所需的模块?结果地址在内部是否正确?重定向是否正确编写(正确的类型、参数等)?检查网关上的访问日志可能很有用。

      但是,还有许多其他方式可能会出现此问题,但这是您应该调查的领域。 504 是路由错误。

      【讨论】:

        【解决方案3】:

        长期的解决方法是编辑文件 /etc/sysctl.conf 以包含以下行:

        fs.inotify.max_user_watches=1048576

        你必须运行 sysctl -p 来重新加载 sysctl.conf

        完成。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-06-29
          • 2013-05-20
          • 2012-10-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多