下面,来说一下,我在日常开发中遇到的4中499问题,以及相应的问题定位处理方法。
在客户端请求服务端接口时,有些接口请求确实很慢。我来随便举个例子:
select*fromtestwheretest_idin(2,4,6,8,10,12,14,16);比如我们有一张test表,表中有500万条数据,我们查询了上述的一条whereinSQL,而test_id字段并没有索引,导致进行了全表扫描。这条SQL就很慢,请求个几秒钟都是很正常的。
解决这种问题很简单,找到对应的慢请求,优化即可,一般情况下都是慢SQL,比如上面的例子,字段没有索引,加个索引就好了。
这种情况呢,就是接口是真的慢,不是偶然现象,是什么时候请求都慢,这个也最好解决,优化接口即可。
还有一种情况是nginx导致的499问题。
从上图我们可以发现,request_time非常小,不可能是请求接口超时,那是什么原因导致的这个问题呢?
通过谷歌发现,有同学遇到过这种情况,就是连续两次过快的post请求就会出现499的情况,是nginx认为这是不安全的连接,主动断开了客户端的连接。
解决方案是在nginx配置:
proxy_ignore_client_aborton;这个参数的意思是proxy忽略客户端的中断,一直等待着代理服务器的返回,如果没有执行错误,则记录的日志是200日志,如果执行超时,记录的日志是504日志。
该配置只对代理服务器起作用,比如有有两台nginx服务器,第一台服务器反向代理到第二台nginx服务器,第二台nginx服务器指向PHP服务,那么该参数只有配置在第一台nginx服务器上才会生效,在第二台nginx服务器上配置不会生效。
配置该参数后,当客户端断开连接之后,服务器仍然会继续执行,存在着拖垮服务器的风险。所以线上根据自己的情况合理使用。
可以看到,上述出现499的情况都比较固定,都是在凌晨2点之后的十分钟内。
这个时候我们一般快速想到的是是不是有什么定时任务占用资源了,事实上确实如此,不过定位到这个问题却不太容易,下面说一下我是怎样定位这个问题的。
机器:接着我怀疑出问题的这几台机器有问题,然后我查看了机器的监控图表(使用的是falcon),发现凌晨两点并没有什么异常情况。(其实这个也可以推断出来,该服务出现499在多台机器上,不可能所有机器都有问题,而且这台机器上还部署着其他项目,其他项目也没有问题,说明不太可能是这台机器有问题。)
数据库:既然是这个服务有问题,我又查看了这个服务连接的主要数据库的监控图表(同样是falcon),也没有发现什么问题。(其实是有问题的,不过我没有察觉)
nginx:既然上述都没有问题,是不是上层的nginx有什么问题。因为upstream_response_time根本没有值,有可能是该请求根本没有到后端的PHP服务,是不是凌晨两点的时候nginx有问题。最后发现我其实理解错了,同样涉及上述参数proxy_ignore_client_abort,如果该参数没有设置为on的话,到服务端的请求不会继续执行,upstream_response_time记录的就是-,这个是没问题的。说明nginx没问题。
异常请求:那么有没有可能是凌晨两点的时候有一波异常请求。该请求为post请求,正好nginx开启了post日志,通过nginx记录的请求参数,重新拼装了一下进行请求,发现没有问题。说明和请求参数无关。
数据库:
error.log:
slow.log:
我们平时也会看到一两个499的情况,但是再重新执行一下该请求,响应速度非常快,根本无法复现,这种偶尔出现的情况,我们一般可以忽略。这里呢,我和大家简单说一下可能导致该问题的原因。
而且,MYSQL还有一个机制,可能让你的查询更慢,就是在准备刷一个脏页的时候,如果这个数据页旁边的数据页刚好是脏页,就会把这个”邻居“也带着一起刷掉;而且这个把”邻居“拖下水的逻辑还会继续蔓延,也就是对于每个邻居数据页,如果跟它相邻的数据页也还是脏页的话,也会放到一起刷。
有趣的是,这个机制在MYSQL8.0同样被禁止了,该功能由innodb_flush_neighbors参数控制,1表示有连刷机制,0表示只刷自己。MYSQL8.0innodb_flush_neighbors默认为0。
我们来看一下我们的线上配置:
mysql>showvariableslike"%innodb_flush_neighbors%";+------------------------+-------+|Variable_name|Value|+------------------------+-------+|innodb_flush_neighbors|1|+------------------------+-------+1rowinset(0.00sec)很不巧,我们线上是开启的,那么就很有可能突然一个请求499啦。
上面我们介绍了在日常业务开发中,会出现499的4中情况以及定位问题、解决问题的方法,希望能给大家提供一些帮助。