一次线上接口超时的排查过程JackieZheng

昨天下午,收到一个504的告警,显然这是一个超时告警。当时由于手头有其他事情,没在意,就只是瞄了一眼,但是引起告警的方法很熟悉,是我写的,第一反应有点诧异。

诧异之后,继续处理手头的工作。

一小时过后,又收到同样的告警,显然不是偶尔,肯定是哪儿出问题了,于是开始排查。

报警的接口是一个Controller层ControllerA的getControllerAMethod接口,其调用了多个微服务,并最终拼装结果数据进行返回。出问题的是ServiceM,ServiceM服务里的getServiceMMethod方法逻辑也很简单,主要是两次数据库查询,从MySQL数据库取到数据并返回给调用方。

调用链如下图所示

语言:Go

DB:MySQL

数据库交互:database/sql(公司在此基础上做了一些定制和封装,本质还是database/sql)

下面开始介绍这个问题的具体排查过程。

拿到告警,从告警信息和对应的日志详情信息来看,属于超时问题。

第一反应是查看sql语句是否是慢查询(虽然打心里知道这个可能性极低),sql语句很简单,形如

selecta,b,cfromtableAwhereain(a1,a2,a3)不看执行计划也知道是可以命中索引的。

本能反应的排查就是这么索然无味,开始下一步排查。

既然是超时问题,有可能是上游超时,也可能是下游超时,第一步排查已经排除了下游因为慢查询导致超时的可能性。

但是从日志排查可以发现,在ServiceM层看getServiceMethod方法对应sql查询几乎都是几十毫秒返回。

于是开始仔细阅读getServiceMMethod方法代码,下面是代码功能的伪代码实现

rows,err=db.query(sql1)iferr!=nil{...}deferrows.Close()forrows.Next(){rows.scan(...)}rows,err=db.query(sql2)iferr!=nil{...}deferrows.Close()forrows.Next(){rows.scan(...)}

看完代码,开始有点小兴奋,我想没错了,大概就是这个rows的问题了。

在《Go组件学习——database/sql数据库连接池你用对了吗》这篇我主要介绍了有关rows没有正常关闭带来的坑。所以开始联想是否是因为在遍历rows过程中没有正确关闭数据库连接,造成连接泄露,以至于后面的查询拿不到连接导致超时。

原因我已经分析的清清楚楚,但是具体是哪一步除了问题呢,唯一能想到的是这里两次查询使用的是同一个rows对象,是不是某种情况导致在前一次已经关闭了连接而下一次查询直接使用了关闭的连接而导致超时呢?

此时报警开始越来越频繁,于是将这里两次查询由原来的一个rows接收改为使用两个rows分别接收并关闭,然后提交代码,测试通过后开始上线。

代码上线后,效果立竿见影。

告警立马停止,日志也没有再出现超时的信息了,一切又恢复到了往日的平静,这让我坚信,我应该是找到原因并解决问题了吧。

回到家后,心里还是有些不踏实,从11点开始,我拿出电脑,开始各种模拟、验证和还原告警的原因。

7、三小时后,意识到风平浪静可能是假象

从11点开始,一直到两点,整整三个小时,我不但没有找到原因,反而发现我的解决方式可能并没有解决问题。

因为出问题的代码并不复杂,如上所示,即只有两个Select查询。

于是我写了一段一样的代码在本地测试,跑完后并没有出现超时或者拿不到连接的情况。甚至,我将maxConn和IdleConn都设置为1也无不会出现超时。

funconeConnWithRowsNextWithError(){db,_:=db.Open("mysql","root:rootroot@/dqmcharset=utf8&parseTime=True&loc=Local")db.SetMaxOpenConns(1)rows,err:=db.Query("select*fromtestwherename='jackie'limit10")iferr!=nil{fmt.Println("queryerror")}i:=1forrows.Next(){i++ifi==3{break}fmt.Println("close")}row,_:=db.Query("select*fromtest")fmt.Println(row,rows)}

但是原来的代码是有deferrows.Close()方法的,这个连接最终肯定是会关闭的,不会出现内存泄露的情况。

这一刻,我想到了墨菲定律(因为没有真正解决问题,问题还回再次出现)。

于是,我又开始扒源码,结合日志,发现一条重要线索,就是很多查询任务都是被主动cancel的。没错,这个cancel就是context.Timeout返回的cancel(这段代码是我司在database/sql基础上丰富的功能)。

cancel触发的条件是执行database/sql中的QueryContext方法返回了err

//QueryContextexecutesaquerythatreturnsrows,typicallyaSELECT.//Theargsareforanyplaceholderparametersinthequery.func(db*DB)QueryContext(ctxcontext.Context,querystring,args...interface{})(*Rows,error){varrows*Rowsvarerrerrorfori:=0;i

于是把这段代码一直往下翻了好几层,还一度怀疑到我们自研代码中的一个参数叫QueryTimeout是否配置过小,但是去看了一眼配置(这一眼很重要,后面会说),发现是800ms,显然是足够的。

带着越来越多的问题,我心不甘情不愿的去睡觉了。

今天下午一点,我又收到了这个熟悉的告警,该来的总会来的(但是只收到一次告警)。

前面说了,这个cancel可能是一个重要信息,所以问题的原因是没跑了,肯定是因为超时,超时可能是因为拿不到连接。

因为getServiceMMethod已经排查一通了,并没有连接泄露的情况,但是其他地方会不会有泄漏呢?于是排查了ServiceM服务的所有代码,对于使用到rows对象的代码检查是否有正常关闭。

排查后,希望破灭。

到此为止,我打心里已经排除了是连接泄露的问题了。

期间,我还问了我们DBA,因为我翻了下日志,今天上午8点左右有几条查询都在几百毫秒,怀疑是DB状态异常导致的。DBA给我的回复是数据库非常正常。

我自己也看了监控,DB的状态和往日相比没有什么流量异常,也没有连接池数量的大起大落。

同事说了前几天上了新功能,量比以前大,于是我也看了下新功能对应的代码,也没发现问题。

我想要的根本原因还没有找到,于是开始想是否可以通过其他方式来规避这个未知的问题呢。毕竟解决问题的最好方式就是不解决(换另一种方式)。

也准备在ServiceM服务的getServiceMMethod方法添加缓存,通过缓存来抵挡一部分请求量。

行吧,就到此为止,明天先用这两招试试看。

于是,我准备站起来活动活动,顺便在脑海里盘点下这个告警的来龙去脉。

上游告警,下游超时->

排除下游rows未关闭->

排除数据库状态不稳定->

确定是下游超时->

怀疑是拿不到连接->

拿不到连接,拿不到连接,拿不到连接

于是又去翻数据库参数配置,刚上面是为了翻QueryTimeout参数,依稀记得这里的连接池设置不大。翻到配置看了下,idleConn=X,maxConn=Y。

再去看了一眼getServiceMMethod方法的QPS监控,我觉得我找到了真相。

从凌晨到早上八点,QPS一直在上升,一直到8点左右,突破Y,而maxConn=Y。

那么为什么之前没有出现这种报警呢,我理解是之前量比较小,最近同事上线了新功能,导致该接口被调用次数增加,才凸显了这个问题。

其实,最后原因可能很简单,就是量起来了,配置的连接数显得小了,导致后来的查询任务拿不到连接超时了。

但是这个超时横跨Controller层到Service以及最底层的DB层,而每一层都可能会导致超时,所以排查相对比较困难。

THE END
1.可以线上报警吗网上可以报警。网络报警是指举报人通过因特网,将所要举报的网络违法案件线索直接在举报网站填写举报表单或写成电子邮件进行举报的一种方式。公民上网举报,应该注意按照公布的网上举报方式、注意事项和提示进行。https://zhidao.baidu.com/question/336387229571528645.html
2.在网上被骗了,如何线上报案处理?- 登录当地公安机关的网络报警平台来报警. - 进入国家反诈中心官网或打开其 APP,依照系统指引提供证据材料和案件背景信息完成线上报警. 利用邮箱报案 可发送邮件至 wwt12377@163.com 进行一键报案. 微信公众号报案 关注“12321举报中心”微信公众号,点击“我要举报”,选择举报类型,填写相关信息,如手机号、验证码、https://www.jianshu.com/p/ef4615184e47
3.网上被骗怎么线上报警,110网络报案中心在线指南步骤一旦遭遇网络诈骗,及时有效地进行线上报警是挽回损失的第一步。本文将详细介绍如何通过110网络报案中心进行在线报警的步骤,帮助受害者尽快得到警方的帮助。 ### 第一步:确认被骗情况 - **识别诈骗类型**:首先需要明确自己遇到的是哪种类型的网络诈骗(如钓鱼网站、虚假广告、冒充熟人等),这有助于后续向警方提供更https://www.douban.com/group/topic/313490225/
4.mp.weixin.qq.com/s?视频报警:点击“视频报警”图标,即可启动视频连接至110报警服务台。 我的报警:点击右上角“我的报警”图标进入界面,即可查询报警记录及受理情况。(警情状态为“待受理”的,可对警情位置、内容并根据情况及图片、录音、视频等附https://mp.weixin.qq.com/s?__biz=MzA5MjgwNjgxOQ==&mid=2654489606&idx=1&sn=ab818678148bfc439286ebbae7afd4a0&chksm=8a47a4fec1e9f2a7bb213c502af178c800e1153b972ab24b29599a6467b214523953e6d826d7&scene=27
5.洛阳警方已开通线上微信报警服务近日,有网友在洛阳网《百姓呼声》频道发帖称:洛阳市公安局开通有线上报警服务吗?比如可以通过发短信或者微信报警吗? 洛阳市公安局回复:我局110报警台全天24小时受理公众报警、紧急求助和投诉,为进一步拓宽群众报警渠道,我局已开通线上微信报警服务,目前暂未开通短信报警功能。微信报警具体操作流程如下: https://mobile.lyd.com.cn/news/system/2023/11/20/032435645.shtml
6.线上可视化,精益现场管理—基于透明化嘲的SQCDP可视化管理梳理SQCDP可视化指标,构建模板,配置场景,进行各指标的线上透明化展示,在此基础上对指标的实时结果进行监控,暴露出的问题自动触发报警,且可结合线上问题处理功能在线进行问题的下发与跟踪处理。 图2 SQCDP管控实现逻辑 01、指标梳理与定义,构建看板的牢固根基 https://www.asktempo.com/news/industry-information/1463.html
7.大规模线上应用TiDB会遇到的坑,本文都帮你排除好了在版本升级的时候,我们遇到的问题是配置不一样,小版本也不一样,由于我们做了一些自定义的配置,可能在这个版本就不生效了,导致升级时出问题、报错。因为都是线上的集群,每次成本都很高。整体来说,集群管理难度增加,每次升级版本的体验都不太友好。 3、日志规范不统一 https://database.51cto.com/art/201911/605959.htm
8.线上被骗了200块钱怎么办线上被骗了200块钱怎么办?线上被骗200元可这样做:保留聊天记录、交易记录等证据,向涉事网络平台举报,还应报警。虽未达刑事立案标准,但警方会记录,若骗子多次小额诈骗达标准可追责,警方也可能追回款项。接下来华律网小编将为您介绍相关内容。一、线上被骗了200块钱怎么办 如果在线上被骗了200元,可以采取以下措施https://www.66law.cn/laws/3199396.aspx
9.从上牌到安装各种配件,九号电动车B90评测:上车即走,下车即锁参数上都不敢过于马虎,这对于小白用户十分友好,不用担心被骗;在安全性上,九号和小牛均以智能化切入,远程查看车子实时位置、异动远程报警等功能都能做到“安心使用”,同时两者还推出了盗车险服务,例如九号买车便送一年盗抢险,在此期间车辆被盗则有相关赔付;最后在体验层面,九号和小牛均在细节方面做了优化以此来提升https://www.yoojia.com/ask/17-11579777107581017677.html
10.MyBatis版本升级引发的线上告警回顾及原理分析最终的定位是:当MyBatis版本为3.2.3时,线上代码是正常可用的,但只要升一个版本,也就是自3.2.4开始,就开始不兼容目前的用法。不过,我们当时的思路并不是很好,应该从小版本逐个往上升或者使用二分法,可以加速定位版本的效率。 最后,我们定位到了产生报警的根本问题。总的来说,MyBatis版本由inf-bom引入而来,inf-https://tech.meituan.com/2020/06/18/inf-bom-mybatis.html
11.炸药库防外来入侵报警监控联动方案规格,图片,属性2.方便维护。太阳能全无线对射在主机的显示中每对都拥有唯一的地址代码,某对对射发生故障或报警都会在主机上有相应提示,比如008这对对射电池低电,就会在主机显示屏上显示“008低电”,所以对于故障对射的维护很方便。传统的有线对射不仅要检查对射本身是否有异常,还要排查电缆线路方面的问题,维护起来相当烦琐。 http://www.ffddcc.com/product/715.html
12.校园一键式紧急报警系统与公安机关100%联网项目实施方案防暴恐演练演习联网处突应急系统集安全演练演习,安全教育,联网报警、移动报警、电话线报警、报警定位,警情群播,多警演练,一警多发,多区编组,一点报警,多处联动,一呼百应,群防群治,地图弹窗,视频联动,监控弹屏,实时对讲,远程广播为一体,具有报警及时性、方便性、隐蔽性等特点,极大的解决了现有报警的问题缺陷,满足http://www.chinesessg.com/3g/show.asp?m=117&d=30
13.杭州司机接到一跨市大单,包裹里竟装了14.5万元现金!细心的他报警半路上,司机发现不对劲 报了警 近日,杭州富阳警方首次成功拦截了一起通过“网约车快送”进行“线上诈骗+线下取钱”的案件。 9月10日凌晨2点多,富阳区公安分局场口派出所接到一位网约车司机李师傅的报警,说接了一个去金华兰溪的大单,但这个单很古怪。 https://m.gmw.cn/2024-09/12/content_1303846441.htm
14.武汉市中心医院在湖北省首推智慧化全院血糖管理新模式一站式帮糖友术前血糖线上“报警” “控糖”专班实时干预 “后湖院区骨外科41床患者的血糖26mmol/L,为极较高血糖,请及时处理!”3月3日9点21分,全院血糖管理专班内分泌科喻佛定医生手机上收到系统发出的“紧急提醒”,10分钟后赶到病房,与骨外科血糖管理联络员王希鹏医生、患者的管床医生现场开起“联合会诊”。 http://news.cnhubei.com/content/2022-03/16/content_14580515.html