Nginx+PHP(laravel) 环境 499 错误码排查过程小记

Nginx+PHP(laravel) 环境 499 错误码排查过程小记

大家好,又见面了,我是全栈君。

前言

某公安项目过程中,在内网服务器部署 WNMP 环境,运行 Laravel 框架代码,后查看日志发现某一时刻突然所有请求 499,并持续一段时间,遂排查原因。

过程

0x01

经搜索得知:
哪些情况下会使 Nginx 返回 HTTP CODE 499?

首先,这个问题百度谷歌应该都能搜到。
其次,我还是回答一下

499, client has closed connection

代表客户端主动断开了连接,一般是服务端处理时间太长了,客户端等不了就断开了
还有一种情况就是有人攻击,故意消耗服务端资源

在nginx源码中,499对应的定义是 “client has closed connection”。这很有可能是因为服务器端处理的时间过长,客户端“不耐烦”了。要解决此问题,就需要在程序上面做些优化了。

即:「客户端主动关闭连接」

但某一时间段内全部请求均为返回 499,这显然不是所有客户端主动意识上的「关闭」,可能是因为客户端等待超时,自动关闭连接;加上 499 的时间段内包含部分 502,让我不得不怀疑:

PHP 进程「死」了。

0x02

这里的死,不一定是进程结束,也有可能是僵尸,或是陷入死循环,一直在执行某个脚本……

若是逐个检查代码时间来不及(以先解决问题为重),遂排查:
Nginx+FastCGI 到底是谁影响超时时间

以及:
PHP-max_execution_time 与 fpm.request_terminate_timeout 介绍

0x03

经过上面的调整,大约一周后再次维护服务器。发现情况有所改善—— 499 错误已经由某一时段大量、集中出现变为偶尔发生,且只出现在某几个特定 URI 请求上。

我决定对这几个 URI 对应的接口控制器代码进行检查。由于系统开发时间紧张,代码质量并不高,怀疑是否是程序内有 BUG。

首先查看代码执行时间,约为 1900 ms 左右,简直太慢!经过仔细检查,发现几个严重问题:

  • 查出某表「全部结果」,再「遍历」结果集,查询每条记录「多个字段」的关联模型
  • 未执行 php artisan optimize
  • 未关闭 debug 模式
  • 未调整 log_level

其中,后几条或许无关紧要,但第一条绝对是致命的。

假设一种常见的模型关联场景:

某作者有多篇文章,每篇文章又有多条评论、赞。

由此,若是采用类似:

posts = posts::where('user_id', 1);
foreach(posts as post){
    likes = post->likes;
    comments = post->comments;
}

在 Laravel 框架内使用类似如上的方式查询,假设作者的文章数为 n,每篇文章关联的模型有 2 个(likes & comments),则执行此控制器,对于数据库的时间复杂度为:O(n*2+1),需要执行如此大量的 SQL 语句!这在后端设计中应该是需要完全避免的,理想情况的时间复杂度应该是 O(n),n 为常量,不受数据规模的影响。

于是修改代码,过程不再详叙,参见 Laravel 官方文档,或:
Laravel 学习笔记之模型关联预加载

经过修改,在 Chrome 开发者工具内查看请求 Timing,缩短为原来时间的一半,800ms 左右。

(但此值仍然不够理想,受到视图渲染、操作系统等原因的影响,后期继续优化,不属于本文讨论范围。)

后记

对于部分接口,请求一次需要执行几百条 SQL;那么,回到最开始的问题:

某次请求后,突然引发大量 499。究其根本原因,是否在于因代码的不严谨,引起的 MySQL 死锁呢?

值得研讨。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/111681.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • jdbctemplate查询为空报错_java空指针异常举例

    jdbctemplate查询为空报错_java空指针异常举例问题是在:Dao类是不能直接new出来的必须是通过ApplicationContextapplicationContext=newClassPathXMLApplicationContext(“springmvc.xml”)erDaodao=(UserDao)ac.getBean(“UserDaoId得到类UserDao的实例化从而JdbcTemplate的值才能获…

    2022年10月30日
  • 搞懂设计模式-单例模式

    搞懂设计模式-单例模式

  • #1032 : 最长回文子串

    #1032 : 最长回文子串#1032:最长回文子串时间限制:1000ms单点时限:1000ms内存限制:64MB描述   小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进。   这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:“小Ho,你能不能分别在

  • 隐马尔可夫模型有哪些模型参数_隐马尔可夫

    隐马尔可夫模型有哪些模型参数_隐马尔可夫隐马尔可夫模型(HiddenMarkovModel,HMM)是统计模型,它用来描述一个含有隐含未知参数的马尔可夫过程。其难点是从可观察的参数中确定该过程的隐含参数。然后利用这些参数来作进一步的分析,例如模式识别。是在被建模的系统被认为是一个马尔可夫过程与未观测到的(隐藏的)的状态的统计马尔可夫模型。http://bluewhale.cc/2016-06-02/hidden-markov-mod

  • maven打包时打包指定的lib文件夹

    maven打包时打包指定的lib文件夹今天在打包自己的springboot项目时遇到了问题,报找不到类和符号。因为我有些依赖是放在项目lib文件夹中,那么打包的时候要连把它一起打包。修改pom.xml,添加一下内容:<build><plugins><plugin><groupId>or…

  • 解析P12证书

    解析P12证书1.从磁盘上的证书文件中读取证书数据unsignedchar*pbP12Data;//证书数据unsignedlongulP12DataLen;//证书数据长度2.让用户输入证书密码char*szPwd;//证书密码3.将证书密码转换成UNICODE格式(最好采用二次调用方式)LPWSTRpWideChar=NULL;int

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号