调试504网关超时及其实际原因和解决方案



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

它是一个动态的网站,每次都有不同的结果集,并且有大约200万个url被谷歌索引。

  • 它运行在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连接,它会解决吗

URL在使用504 120秒后超时

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

早期的fastcgi_connect_timeout为150秒,它用于在63秒后给出502状态代码,RHEL 6.6上的默认net.ipv4.tcp_syn_reries=5;之后,我们设置net.ipv4.tcp_syn_reries=6,然后它在127秒后开始给出502。

一旦我设置fastcgi_connect_timeout=120,它就开始给出504状态代码。我知道具有如此高值的fastcgi_connect_timeout是不好的。

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

我如何确认问题的确切位置?

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

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

  • keepalive_timeout 5
  • send_ timeout 150

在特定vhost.conf下:

  • 代理发送超时100
  • 代理读取超时100
  • 代理连接超时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_filn_timeout=10
  • net.ipv4.tcp_tw_reuse=1
  • net.ipv4.tcp_syn_reries=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,服务器:x.x.x.x,请求:"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进程的数量并没有显著增长,即使增长了,服务器也有足够的能力派生新进程并为请求提供服务。

尝试在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

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

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

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

然而,这个问题还有很多其他的发生方式,但这是你应该调查的领域。504是路由错误。

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

fs.inotify.max_user_watches=1048576

您必须运行sysctl-p才能重新加载sysctl.conf

完成。

相关内容

最新更新