在nginx上跑php容易出现502错误,很多人遇到过这个问题,到底是什么原因导致的呢?

出现502错误后,又有哪些解决办法呢?

本文源起于前段时间处理无线浏览器的一次502报警后总结得来,希望能为大家提供参考。

从报警说起

现象

1、打开静态页面很快,如无线浏览器的更新日志页面,请求云控接口却很慢,报502错误。

2、最开始一周报警1-2次,后来发展到一天报警1次。

处理过程

1、查看错误日志,发现502错误的响应时间都比较长,均为21s左右。见下图:

日志中请求的是云控接口,就是一个读取配置文件然后吐出数据的过程,正常情况下响应时间应该是非常短的。

因此直观猜测是php进程堵死了,云控请求过来时php进程不够用了,从而导致502错误。

使用 netstat -napo | grep "php-fpm" | wc -l 查看了一下当前fastcgi进程个数, 发现已达到php-fpm.conf中pm.max_children的设置值。

重启php-fpm后,报警得以解除,但这并没有找到问题根源,php进程为什么会堵死呢?

2、猜测进程堵死的原因应该是大量的慢请求导致的。在/usr/local/php/etc/php-fpm.conf文件中,发现有关于慢日志的设置:

slowlog = /data/php/log/$pool.log.slow

request_slowlog_timeout = 10

request_terminate_timeout = 0

request_terminate_timeout配置的是一个php脚本的最大执行时间,默认是0s。

0s的含义是让php脚本一直执行下去而没有时间限制。

当再次收到报警时,查看php的slow log,果然发现发现大量执行时间超过10s的脚本。慢日志如下:

11-Aug-2014 08:34:53 pool www pid 8683

script_filename = /home/q/system/api.mse.360.cn/src/www/api//index.php0x00000000013d0420 curl_exec() /home/q/system/api.mse.360.cn/src/application/models/bizservice/icon_svc.php:291

0x00000000013cff98 httpRequest() /home/q/system/api.mse.360.cn/src/application/models/bizservice/icon_svc.php:203

0x00000000013cf710 getTitleBySite() /home/q/system/api.mse.360.cn/src/application/models/bizservice/icon_svc.php:33

0x00000000013cf260 getIconAndTitleBySite() /home/q/system/api.mse.360.cn/src/application/controllers/api/IconController.php:25

0x00000000013cf0c0 addSiteAction() /home/q/php/QFrameSmarty/web/QFrameaction.php:46

0x00000000013ce9a0 dispatch() /home/q/php/QFrameSmarty/web/QFrameweb.php:176

0x00000000013ce4b0 dispatch() /home/q/php/QFrameSmarty/web/QFrameweb.php:150

0x00000000013ce190 runController() /home/q/php/QFrameSmarty/web/QFrameweb.php:129

0x00000000013ce018 processRequest() /home/q/php/QFrameSmarty/web/QFrameweb.php:37

0x00000000013cdc50 run() /home/q/system/api.mse.360.cn/src/www/api/index.php:15

终于找到php进程堵死的根源:调用添加icon到浏览器主屏这个接口时,大量的curl抓取页面title执行超时。

慢请求过多导致php进程不能及时释放,所以触发报警。

添加curl的执行超时,上线代码后,php进程终于治“堵”成功,nginx+php-fpm的502报警彻底解除。

为什么会出现502

一般而言,nginx出现502有很多原因,但大都可以归结为资源数量不够用,也就是说后端php-fpm处理有问题。

nginx将正确的客户端请求发给后端的php-fpm进程,由于php-fpm进程的问题导致不能正确解析php代码,最终返回502错误。

1、php-fpm进程数不够用

nginx和fastcgi是通过socket进行连接的,一个php-fpm进程在同一时刻只能响应一个用户请求。它能处理的最大请求数由php-fpm.conf中如下配置决定:

listen.backlog = 128

pm.max_children = 256

这是我们线上服务器的配置,也就是说php-fpm能处理的最大请求数为384。

当客户端的请求数超过这个值时,再试图发送请求会收到Resource temporarily unavailable,这时nginx就会报502错误。

上面提到的业务报警就是由于php-fpm进程数不够用而导致的。

大量慢请求占据了php进程,php-fpm进程数很快达到峰值。php-fpm被卡死不能处理新的请求时,nginx并不会收到请求被拒绝的类似信息,而是把请求积压在socket上;

此时浏览器所得到的响应就是一个“正在等待响应”的提示,除非socket报错或浏览器关闭否则等待永远不会停止。

当积压数超过backlog的设置值时,高峰时间大量的云控请求就会触发服务端的502报警。

为了验证这一结论,在测试服务器上修改php-fpm.conf文件中的配置进行一个简单测试。

修改php-fpm.conf的相关配置如下:

listen.backlog = 8

pm = dynamic pm.max_children = 8

pm.min_spare_servers = 2

pm.max_spare_servers = 4

重启php-fpm,客户端发送多于16个请求,每个请求脚本都sleep 10s。采用http_load进行压测,结果如下:

21 fetches, 25 max parallel, 18044 bytes, in 30.0058 seconds

859.238 mean bytes/connection

0.699864 fetches/sec, 601.35 bytes/sec

msecs/connect: 0.472571 mean, 0.637 max, 0.229 min

msecs/first-response: 17094.7 mean, 22743.7 max, 10002.3 min

5 bad byte counts

HTTP response codes:

code 200 – 16

code 502 – 5

从压测结果可以看到,php-fpm能处理的最大请求数应为16,超出这个值的请求会报502错误。

2、php脚本执行超时

在php.ini和php-fpm.conf中分别有这样两个配置项:max_execution_time和request_terminate_timeout。

文档中对其注释如下:;

The timeout for serving a single request after which the worker process will

; be killed. This option should be used when the 'max_execution_time' ini option

; does not stop script execution for some reason. A value of '0' means 'off'.

; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)

; Default Value: 0

;request_terminate_timeout = 0

这两项都是用来配置一个php脚本的最大执行时间的,默认为0s。

当超过这个时间时,php-fpm不仅会终止脚本的执行,还会终止执行脚本的worker进程。

当Nginx会发现与自己通信的socket连接断掉了,以为上游服务器挂了,于是返回给客户端502错误。

修改php-fpm.conf配置如下:

request_terminate_timeout = 10

重启php-fpm,写一个php脚本,sleep 20s。打开浏览器访问测试页面,执行该php脚本验证一下,结果如下图:

由于php脚本执行时间超过配置规定时间,进程被异常终止,所以nginx返回502,验证了上面的结论。

如何避免502

如果服务器并发量非常大,那只能先增加机器,然后按以下方式优化会取得更好效果;但如果并发不大却出现502,一般都可以归结为上述两个原因,php-fpm进程数不够用和php脚本执行超时。

1、增加php-fpm进程数

使用 netstat -napo | grep "php-fpm" | wc -l 查看一下当前fastcgi进程个数。

如果个数接近 php-fpm.conf里配置的pm.max_children上限,就需要调高进程数。

因为max_children设置的较小,那么fastcgi就会“很累”,处理速度也很慢,等待的时间也较长。

但设置max_children也会受到机器资源的限制,因此也并不能无限增加,增大进程数,内存占用也会相应增大。

正常情况下每个php-fpm进程所耗费的内存在20M左右,因此我们线上服务器的配置基本上是最佳的。

2、调整request_terminate_timeout

request_terminate_timeout可以根据服务器的性能进行设定,一般来说性能越好你可以设置越高。

在我们的线上服务器建议直接使用默认值0s就可以了,这样能够避免php进程被异常终止而导致502错误。

可以看到,增加php-fpm进程数和调整request_terminate_timeout均属于配置问题。

在我们的线上环境,相关配置基本上已达到最优,此时要避免502最最重要的还是要控制好程序中的超时。

curl、file_get_contents等函数都要设置超时时间,mysql慢查询请求也要尽量避免。

总结一下

1、nginx出现502错误一般都是后端的php-fpm出问题引起的。

2、pm.max_children不能无限增加,要视机器资源而定。

3、php-fpm.conf中request_terminate_timeout最好采用默认值。

4、大量的慢请求往往才是502的罪魁祸首,所以请一定要管好你程序中的超时。

为什么PHP项目运行报错502,Nginx + php-fpm 出现502错误分析相关推荐

  1. vue/cle3项目运行报错sockjs-node/info解决方案

    https://cloud.tencent.com/developer/article/1489598 vue/cle3项目运行报错sockjs-node/info解决方案 在这篇文章中: bug复现 ...

  2. 【项目运行报错】These dependencies were not found: core-js/modules/es6.array.fill in ./node_modules

    项目运行报错 These dependencies were not found: core-js/modules/es6.array.fill in ./node_modules/cache-loa ...

  3. vue 项目运行报错 multiple chunks emit assts to the same filename js/401.js(chunks 401 and 401)

    VUE项目运行报这个错误也没有说哪里有错误,只说有名字冲突,整个项目搜下来都没发现有相同的名字,百度也没人说.自己摸索的解决掉了.有两种情况. 情况一:如果是添加路由的时候就报这个错 解决办法: 把c ...

  4. 为什么PHP项目运行报错502,Nginx+PHP-FPM遇到的502报错

    1 首先查看一下目前php-fpm的进程数量 ps aux |grep php-fpm |grep -v grep |grep "^www"|wc -l 将输出结果与nginx.c ...

  5. 为什么PHP项目运行报错502,PHP的502报错

    相信自己,加油! **** nginx+php 出现502 bad gateway,一般这都不是nginx的问题,而是由于 fastcgi或者php的问题导致的 服务器出现 502 的原因是连接超时 ...

  6. vue项目运行报错 node_modules/.bin/vue-cli-service: Permission denied

    vue项目运行 npm run serve 报错 sh: /Users/wang/WebstormProjects/test_web/node_modules/.bin/vue-cli-service ...

  7. Python项目运行报错 django.core.exceptions.ImproperlyConfigured: WSGI application ‘WebTool.wsgi.application

    问题描述:使用Pycharm运行python项目报错:django.core.exceptions.ImproperlyConfigured: WSGI application 'WebTool.ws ...

  8. 查看node的位置_升级Node版本RN项目运行报错cb.apply is not a function

    今日打算安装一下ReactNative官方推荐的脚手架工具Ignite. infinitered/ignite​github.com Ignite是一套整合了 Redux 以及一些常见 UI 组件的脚 ...

  9. vue使用vuetify创建项目运行报错:error Component name XXX should always be multi-word vue/multi-word-compon

    报错如下: You may use special comments to disable some warnings. Use // eslint-disable-next-line to igno ...

最新文章

  1. 【C语言】一文搞定如何计算结构体的大小----结构体内存对齐规则
  2. 举两个栗子:如何正确建立个人的机器学习项目集
  3. 使用internal(com.android.internal)和hidden(@hide)APIs – Part 5
  4. 问题集锦(21-25)
  5. MVP架构设计 进阶三
  6. 【Oracle】【日期、时间】 date与数字时间戳互转
  7. 80m的mysql文件要导入多久_mysql导入数据库文件最大限制更改解决方法:You probably tried to upload too large file...
  8. java面试常考系列四
  9. ARM汇编ADR,LDR等伪指令
  10. 年逾九十院士潘际銮:身背千亿科研价值身居斗室
  11. 【dfs】Election of Evil
  12. 信息学奥赛一本通C++语言——1053:最大数输出
  13. Django系列:(1)PyCharm下创建并运行我们的第一个Django工程
  14. PHP SEVER预定义变量
  15. (转)Cesium教程系列汇总
  16. Atlas中间件实现Mysql读写分离
  17. java远程桌面_java – 实现远程桌面共享解决方案
  18. 一个全网最详细 Python 教程,不信你来学一学!
  19. zabbix 报警 Lack of free swap space on Zabbix server 处理
  20. royal tsx连接闪退_Royal TSX for Mac(最强远程管理软件)

热门文章

  1. 这几个小妙招让你学会如何压缩图片大小
  2. 笨方法学python 34-38
  3. 论文笔记及Pytorch复现:A Dual-Stage Attention-Based Recurrent Neural Network for Time Series Prediction
  4. 服务器接收协议,协议分析-服务器接收
  5. 性能测试基础(四)吞吐量
  6. 某211大学生保研思路分享【写给所有怀揣远大梦想的你们】
  7. java web第三章 Day3 2020080605018
  8. 去除qq短视频水印 伪原创视频技巧
  9. word表格无法调整行高
  10. 用计算机处理图像属于啥技术,计算机技术在图像处理中的应用