我们在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,那么需要修复它。
提前感谢!
======
进一步更新:
有两种情况:
- 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"
- 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_timeout
和proxy_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
完成。