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)


相关推荐

  • SpringBoot整合Mybatis超详细流程

    SpringBoot整合Mybatis超详细流程SpringBoot整合Mybatis超详细流程文章目录SpringBoot整合Mybatis超详细流程前言详细流程0.引入Mybatis1.创建数据2.创建程序目录3.理解后台访问流程4.核心文件配置5.编写entity6.编写dao7.编写Mapper8.编写Service9.编写Controller10.运行项目参考文章前言MyBatis本是apache的一个开源项目iBatis,2010年这个项目由apachesoftwarefoundation迁移到了googlecode,并且

    2022年10月26日
  • 在毕设中学习01——python、正态和标准正态分布、matlab数据文件导出

    在毕设中学习01——python、正态和标准正态分布、matlab数据文件导出在毕设中学习——卷积、python(0521)2022.5.21文章目录在毕设中学习——卷积、python(0521)正态分布标准正态分布matplotlib.pyplot画图Python中读取.m文件np.random.normal()正态分布numpy.random.normal(loc=0,scale=1e-2,size=shape)意义如下:参数loc(float):正态分布的均值,对应着这个分布的中心。loc=0说明这一个以Y轴为对称轴的正态分布,参数scale(float):

  • 【重磅】移动网络性能揭秘(下)–网络协议及性能提升实践

    【重磅】移动网络性能揭秘(下)–网络协议及性能提升实践

  • 各种获取设备唯一标识的方法介绍

    各种获取设备唯一标识的方法介绍一.UDID(UniqueDeviceIdentifier)UDID的全称是UniqueDeviceIdentifier,它就是苹果iOS设备的唯一识别码,它由40位16进制数的字母和数字组成(越狱的设备通过某些工具可以改变设备的UDID)。移动网络可利用UDID来识别移动设备,但是,从IOS5.0(2011年8月份)开始,苹果宣布将不再支持用uniqueIdentifier方法获

  • 简介pid参数整定的基本方法_一阶倒立摆的PID

    简介pid参数整定的基本方法_一阶倒立摆的PID0.前言关于PID参数的整定,网上调节的口诀、原则、方法满天飞,但是并没有具体的到步的教程,作为初学者且非自动化相关专业学生有点看不懂、一脸懵逼,走了不少弯路,呕心沥血才调节好,之后才看得懂那些口诀、原则。为了让大家少走弯路,这里将给出圆周倒立摆直立环PID参数整定的具体步骤。多图预警!圆周倒立摆整体图1.PID编程及理解磨刀不误砍材工,是骡子是马,咱先看看,要想调好PI…

  • Js生成二维码_js在线生成二维码

    Js生成二维码_js在线生成二维码1引入jsjquery.jqprint-0.3.jsjquery.qrcode.min.jsjquery-migrate-1.4.1.js2html元素:二维码生成在img的div中,新增img标签,并设置为display:none3生成二维码$(“#ewm”).qrcode(“http://127.0.0.1:8080/pages/check/infos.h…

    2022年10月17日

发表回复

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

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